STM32 F3 Discovery ADC with DMA and Nvic - stm32

I have to use 4 ADC channels in my stm32f3 Discovery, so I've decided to use DMA with Nvic. Values sent by USART are correct, however, the DMA1 Channel1 interrupt is called only once after downloading code to flash. I need a continuous conversion, is there something wrong with ADC/DMA/Nvic configuration?
#include"stm32f30x.h"
#include"stm32f30x_gpio.h"
#include"stm32f30x_rcc.h"
#include"stm32f30x_usart.h"
#include"stm32f30x_misc.h"
#include"stm32f30x_adc.h"
#include"stm32f30x_tim.h"
#include"stm32f30x_dma.h"
#define ADC1_DR ((uint32_t)0x4001244C)
__IO uint16_t calibration_value = 0;
__IO uint32_t TimingDelay = 0;
__IO uint16_t ADC_Values[4];
uint16_t tmp[4];
volatile uint32_t dmaFlag = 0;
volatile char rxData[100];
volatile long int rxIndex=0, rxFlag=0;
void USART_puts( USART_TypeDef* USARTx, char *str )
{
while(*str)
{
while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );
USART_SendData(USARTx, *str);
*str++;
}
}
void adc_init(void);
int main(void)
{
int8_t dmaIndex;
int k;
usart_init();
USART_puts(USART1,"ok");
adc_init();
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_RDY));
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_StartConversion(ADC1);
//
while(1)
{
while(!dmaFlag);
usart_num(tmp[0]);
usart_num(tmp[1]);
usart_num(tmp[2]);
usart_num(tmp[3]);
for(k=0;k<10000000;k++);
dmaFlag= 0;
}
}
void adc_init(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure1;
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure1);
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_InitStructure.ADC_NbrOfRegChannel = 4;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_StructInit(&ADC_InitStructure);
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) != RESET );
calibration_value = ADC_GetCalibrationValue(ADC1);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 4, ADC_SampleTime_7Cycles5);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Values;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16 bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 16 bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
}
void DMA1_Channel1_IRQHandler(void)
{
USART_puts(USART1,"fsfr");
if (DMA_GetITStatus(DMA1_IT_TC1))
{
int dmaIndex;
for(dmaIndex=0; dmaIndex<4; dmaIndex++)
{
tmp[dmaIndex]=ADC_Values[dmaIndex]/4;
}
DMA_ClearITPendingBit(DMA1_IT_TC1);
dmaFlag= 1;
}
}
void usart_init( void )
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig( USART1, USART_IT_RXNE, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd( USART1, ENABLE);
}
void USART1_IRQHandler( void )
{
if( USART_GetITStatus( USART1, USART_IT_RXNE) )
{
rxData[rxIndex] = USART_ReceiveData(USART1);
// USART_ClearITPendingBit(USART1,USART_IT_RXNE);
while( !(rxData[rxIndex] == 'e') )
{
if( USART_GetITStatus( USART1, USART_IT_RXNE) )
{
rxIndex++;
rxData[rxIndex] = USART_ReceiveData(USART1);
if( rxData[rxIndex] == ' ')
rxData[rxIndex] = '0';
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
rxFlag = 1;
}
///USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
void rxDataClear( void )
{
int i=0;
while( rxData[i] )
{
rxData[i] = 0;
i++;
}
rxIndex = 0;
}
void usart_float( float liczba )
{
float tmp;
char dane[7];
tmp = liczba;
dane[0]=(((int)tmp %1000) /100)+0x30;
dane[1]=(((int)tmp %100) /10)+0x30;
dane[2]=(((int)tmp %10))+0x30;
dane[3]='.';
dane[4]=((int)(tmp*10) %10)+0x30;
dane[5]=((int)(tmp*100) %10)+0x30;
dane[6]=((int)(tmp*1000) %10)+0x30;
dane[7]='\0';
USART_puts(USART1,dane);
}
void usart_num(signed int liczba)
{
int i, length=0,znak=0;
char liczba_str[10] = {0};
if( liczba < 0 )
{
znak = 1;
liczba = - liczba;
}
for( i = 1; (i <= liczba) && (length <= 10); i*=10 )
{
if( (liczba/i) > 0 )
length++;
}
if(length == 0)
length = 1;
i = 1;
while(length)
{
liczba_str[length-1]=liczba%(10*i)/i+48;
length--;
i*= 10;
}
if(znak)
USART_puts(USART1,"-");
else
USART_puts(USART1," ");
USART_puts(USART1, liczba_str );
}

Try this to continuous conversion,change this:
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
to :
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
and replace this:
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
by:
ADC_DMAConfig( ADC1, ADC_DMAMode_Circular );
/* Enable ADC1 DMA */
ADC_DMACmd( ADC1, ENABLE );
/* Enable ADC1 */
ADC_Cmd( ADC1, ENABLE );
/* Wait for ADC1 ready */
i = 0xFFFFF;
while(!ADC_GetFlagStatus( ADC1, ADC_FLAG_RDY ) && i) i--;
/* Enable the DMA1 channel1 */
DMA_Cmd( DMA1_Channel1, ENABLE );
/* Start ADC1 Software Conversion */
ADC_StartConversion( ADC1);`

Related

Why can't I enter USART3_IRQHandler?

#if EN_USART2
u16 _distance1=0;
u16 distance1=0;
void USART2_Init(u32 bound) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_Cmd(USART2, ENABLE);
}
void USART2_IRQHandler(void){
u8 a;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){
a =USART_ReceiveData(USART2);
if(a!=0xa5) _distance1=(_distance1<<8)|a;
else
{
distance1=_distance1;
_distance1=0;
}
}
}
#endif
#if EN_USART3
u16 _distance2=0;
u16 distance2=0;
void USART3_Init(u32 bound) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_Cmd(USART3, ENABLE);
}
void USART3_IRQHandler(void){
u8 a;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET){
a =USART_ReceiveData(USART3);
if(a!=0xa5) _distance2=(_distance2<<8)|a;
else
{
distance2=_distance2;
_distance2=0;
}
}
}
#endif
This is part of the code of usart.c. EN_USART2 and EN_USART3 are all 1. main.c is as follows:
#include "stm32f10x.h"
#include "delay.h"
#include "system.h"
#include "usart.h"
// Device header
int main(void)
{
SystemInit();
USART1_Init(115200);
USART2_Init(115200);
USART3_Init(115200);
while(1)
{
printf("difference: %dmm\r\n",distance1-distance2);
delay_ms(100);
}
}
It runs on STM32F103C8T6. PA2 and PA3 connects to an ultrasound module, and PB10 and PB11 connects to another ultrasound module. I found that the interruption service function of USART2 can be implemented, but that of USART3 cannot. Why is that? USART3 and USART2 are all written similarly. (As for how do I know that USART2 doesn't work: I added printf("p") behind a =USART_ReceiveData(USART3);, but I didn't see any "p" on the serial debug window(however, messages printed in main() all displayed well, which means that USART1 is normal).
I searched for the template code, but I can't find anything wrong in my own code.

PWM input capture and repeat. STM32F4

guys.
I generated PWM signal with timer TIM1.
I want get this PWM from TIM1 with timer TIM2 and repeat it on the some GPIO pin.
I used Standart Peripheral Library.
PWM has generated on pin PA8 with timer TIM1 successfully, but i can't receive this PWM signal from PA0 pin with TIM2.
(PA8 и PA0 i connected with cable.)
Help me, please.
type here
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "misc.h"
#include <stdio.h>
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM1_TimeBaseStruct;
TIM_OCInitTypeDef TIM1_OCInitStruct;
TIM_ICInitTypeDef TIM_ICInitStruct;
volatile uint16_t capture1 = 0, capture2 = 0;
volatile uint8_t capture_is_first = 1, capture_is_ready = 0;
const uint32_t myPeriod = 61538 - 1;
const uint32_t myPrescaler = 1 - 1;
const uint32_t myPulse = 5000;
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// Generate PWM on PA8
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// Input capture PWM on PA0
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
TIM1_TimeBaseStruct.TIM_Period = myPeriod;
TIM1_TimeBaseStruct.TIM_Prescaler = myPrescaler;
TIM1_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStruct);
TIM1_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM1_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM1_OCInitStruct.TIM_Pulse = myPulse;
TIM1_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM1_OCInitStruct.TIM_OCNPolarity = TIM_OutputState_Disable;
TIM1_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1, &TIM1_OCInitStruct);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
TIM_TimeBaseInitTypeDef timer_base;
TIM_TimeBaseStructInit(&timer_base);
timer_base.TIM_Prescaler = 24000 - 1;
TIM_ICInitTypeDef timer_ic;
timer_ic.TIM_Channel = TIM_Channel_1;
timer_ic.TIM_ICPolarity = TIM_ICPolarity_Rising;
timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI;
timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1;
timer_ic.TIM_ICFilter = 0;
TIM_ICInit(TIM2, &timer_ic);
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
NVIC_EnableIRQ(TIM2_IRQn);
/* Включаем таймер */
TIM_Cmd(TIM2, ENABLE);
while (1)
{
}
} // main
void TIM2_IRQHandler(void)
{
int i = 0;
i++;
printf("I'm TIM2 IRQ Handler.");
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
capture1 = capture2;
capture2 = TIM_GetCapture1(TIM2);
if (!capture_is_first)
capture_is_ready = 1;
capture_is_first = 0;
if (TIM_GetFlagStatus(TIM2, TIM_FLAG_CC1OF) != RESET)
{
TIM_ClearFlag(TIM2, TIM_FLAG_CC1OF);
// ...
}
}
}
I wrote the receive (input capture) PWM signal code using examples from the Internet, but i can't debug this. Help please. I'm new to embedded dev.

stm32 HAL CAN receive massage in normal mode, it receives but does not come out of interrupt

I wrote a simple code as below for receiving data via can bus.
I have a board and a can bus analyzer for testing. I send data from analyzer to the board.
in debug mode I saw that the data is received correctly, the "data_received" variable is set to '1' too, but the "b" variable has not changed.
it seems that we dont come out of the interrupt function and dont come to while(1)
#include "main.h"
CAN_HandleTypeDef hcan1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN1_Init(void);
CAN_RxHeaderTypeDef RxHeader;
uint8_t data[2];
volatile int data_received=0;
volatile int b=0;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance==CAN1)
{
HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&RxHeader,data);
}
if (RxHeader.DLC==2)
{
data_received=1;
}
else
{
data_received=0;
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_CAN1_Init();
if (HAL_CAN_Start(&hcan1) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING)!= HAL_OK)
{
Error_Handler();
}
while (1)
{
if (data_received==1)
{
b=1;
data_received=0;
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
static void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 3;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_11TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
CAN_FilterTypeDef canfilterconfig;
canfilterconfig.FilterActivation = CAN_FILTER_ENABLE;
canfilterconfig.FilterBank = 18;
canfilterconfig.FilterFIFOAssignment = CAN_RX_FIFO0;
canfilterconfig.FilterIdHigh = 0x103<<5;
canfilterconfig.FilterIdLow = 0x0000;
canfilterconfig.FilterMaskIdHigh = 0x103<<5;
canfilterconfig.FilterMaskIdLow = 0x0000;
canfilterconfig.FilterMode = CAN_FILTERMODE_IDMASK;
canfilterconfig.FilterScale = CAN_FILTERSCALE_32BIT;
canfilterconfig.SlaveStartFilterBank = 20;
HAL_CAN_ConfigFilter(&hcan1, &canfilterconfig);
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11, GPIO_PIN_SET);
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
Have a look inside HAL_CAN_GetRxMessage function, all eight data array bytes are always initialized:
aData[0] = (uint8_t)((CAN_RDL0R_DATA0 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA0_Pos);
aData[1] = (uint8_t)((CAN_RDL0R_DATA1 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA1_Pos);
aData[2] = (uint8_t)((CAN_RDL0R_DATA2 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA2_Pos);
aData[3] = (uint8_t)((CAN_RDL0R_DATA3 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA3_Pos);
aData[4] = (uint8_t)((CAN_RDH0R_DATA4 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA4_Pos);
aData[5] = (uint8_t)((CAN_RDH0R_DATA5 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA5_Pos);
aData[6] = (uint8_t)((CAN_RDH0R_DATA6 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA6_Pos);
aData[7] = (uint8_t)((CAN_RDH0R_DATA7 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA7_Pos);
Yet your data array is only two bytes long. HAL_CAN_GetRxMessage overrites other variables. This might not be your problem, but it's an obvious bug that will bite you eventually.
Note, that after compilation, order of the variables might not be the same as in the source. You might think that data_received is getting overriten, but it might not. To find out actual order of the variables you can look at the map file.

spi master fires uncontrollable dma tc interrupts without receiving nothing

I've already asked this question on the mbed forum, but I did not received an answer.
Introduction
I have two Nucleo L432kc board, I want to make them communicate with the SPI protocol using DMA.
In the following scheme you can see the actual hardware setup:
What works
If I send data from the master to the slave I receive them correctly and when the master is not transmitting the slave does not receive anything.
Master's code
#include <mbed.h>
uint8_t dma_buffer_tx[4];
uint8_t dma_buffer_rx[4];
uint8_t buff[4];
uint32_t receive_buff_length = 4;
unsigned int c = 0;
Serial pc(USBTX,USBRX,921600);
DigitalOut led(LED3);
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
void Error_Handler(){
led.write(1);
while(1){}
}
static void HAL_GPIO_Init(void){
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi1.Instance==SPI1)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA1 ------> SPI1_SCK
PA11 ------> SPI1_MISO
PA12 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
else
Error_Handler();
}
static void SPI1_Init(void)
{
__HAL_RCC_SPI1_CLK_ENABLE();
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
static void DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA1_Channel2;
hdma_spi1_rx.Init.Request = DMA_REQUEST_1;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmarx,hdma_spi1_rx);
/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* SPI1 DMA Init */
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA1_Channel3;
hdma_spi1_tx.Init.Request = DMA_REQUEST_1;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmatx,hdma_spi1_tx);
/* DMA interrupt init */
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
}
extern "C"{
void DMA1_Channel3_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_tx);
}
void DMA1_Channel2_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_rx);
}
void SPI1_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi1);
}
}
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = 0; i < receive_buff_length/2; i++){
buff[i] = dma_buffer_rx[i];
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = receive_buff_length/2; i < receive_buff_length; i++){
buff[i] = dma_buffer_rx[i];
}
printf("%u\n",*(unsigned int *)buff); // to understan when I am actually receiving data
memset(dma_buffer_rx,0,sizeof(dma_buffer_rx));
}
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
c += 5;
dma_buffer_tx[0] = c & 0xFF;
dma_buffer_tx[1] = (c >> 8) & 0xFF;
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi1){
dma_buffer_tx[2] = (c >> 16) & 0xFF;
dma_buffer_tx[3] = (c >> 24) & 0xFF;
}
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* SPI INIT */
SPI1_Init();
/* GPIO USART2 INIT */
HAL_GPIO_Init();
/* DMA INIT */
DMA_Init();
c = 1000;
dma_buffer_rx[0] = c & 0xFF;
dma_buffer_rx[1] = (c >> 8) & 0xFF;
dma_buffer_rx[2] = (c >> 16) & 0xFF;
dma_buffer_rx[3] = (c >> 24) & 0xFF;
while(true){
HAL_SPI_Transmit_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
wait(0.001);
}
}
Slave's code
#include <mbed.h>
uint8_t dma_buffer_tx[4];
uint8_t dma_buffer_rx[4];
uint8_t buff[4];
uint32_t receive_buff_length = 4;
unsigned int c = 0;
Serial pc(USBTX,USBRX,921600);
DigitalOut led(LED3);
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
void Error_Handler(){
led.write(1);
while(1){}
}
static void HAL_GPIO_Init(void){
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi1.Instance==SPI1)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA1 ------> SPI1_SCK
PA11 ------> SPI1_MISO
PA12 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
else
Error_Handler();
}
static void SPI1_Init(void)
{
__HAL_RCC_SPI1_CLK_ENABLE();
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
static void DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA1_Channel2;
hdma_spi1_rx.Init.Request = DMA_REQUEST_1;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmarx,hdma_spi1_rx);
/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* SPI1 DMA Init */
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA1_Channel3;
hdma_spi1_tx.Init.Request = DMA_REQUEST_1;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmatx,hdma_spi1_tx);
/* DMA interrupt init */
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
}
extern "C"{
void DMA1_Channel3_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_tx);
}
void DMA1_Channel2_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_rx);
}
void SPI1_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi1);
}
}
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = 0; i < receive_buff_length/2; i++){
buff[i] = dma_buffer_rx[i];
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = receive_buff_length/2; i < receive_buff_length; i++){
buff[i] = dma_buffer_rx[i];
}
printf("%u\n",*(unsigned int *)buff); // to understan when I am actually receiving data
memset(dma_buffer_rx,0,sizeof(dma_buffer_rx));
}
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
c += 5;
dma_buffer_tx[0] = c & 0xFF;
dma_buffer_tx[1] = (c >> 8) & 0xFF;
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi1){
dma_buffer_tx[2] = (c >> 16) & 0xFF;
dma_buffer_tx[3] = (c >> 24) & 0xFF;
}
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* SPI INIT */
SPI1_Init();
/* GPIO USART2 INIT */
HAL_GPIO_Init();
/* DMA INIT */
DMA_Init();
c = 1000;
dma_buffer_rx[0] = c & 0xFF;
dma_buffer_rx[1] = (c >> 8) & 0xFF;
dma_buffer_rx[2] = (c >> 16) & 0xFF;
dma_buffer_rx[3] = (c >> 24) & 0xFF;
while(true){
HAL_SPI_Receive_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
}
}
What does not work
If I change the role in the communication, so I send the data from the salve to the master swapping the following lines
[...]
HAL_SPI_Transmit_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
wait(0.001);
[...]
with:
[...]
HAL_SPI_Receive_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
[...]
Even if the slave is not powered up the master continusly receives interrupts and invokes the HAL_SPI_RxCpltCallback. If we power up the slave the master prints random numbers.
What I have already tried without success
I've tested the master code on a Nucleo F446 board.
I've set pull-down and pull-up resistors on the MISO pin.
I've tried different cable for the hw connection.
I've tried to directly use the HAL_SPI_TransmitReceive_DMA function, but the behaviour is the same.
Considerations
Walking throught the HAL_SPI_Receive_DMA source I've noticed that in the SPI_MODE_MASTER the HAL_SPI_TransmitReceive_DMA fuction is actually called.
I think that the same buffer is used for transmission and reception, but I don't know how to prove that.
I've also printed the hdma_spi1_rx.Instance->CNDTR and I've noticed that the value increments to 4 whitch is actually the number of bytes that we are going to receive.
SPI master always receives data when it is transmitting. This is how the SPI works. Even if the SPI is not transmitting, the master reads the data all the time.

STM32F103 Timer alternate function remapping

I am experimenting with some VGA generating code by Artekit, at https://www.artekit.eu/vga-output-using-a-36-pin-stm32/. This code generates a PWM signal for HSYNC using TIM2 Channel 2, which is output on port PA1. This all works correctly. Now I would like to remap TIM2 so that the PWM signal is remapped to pin PB3. After calling GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE) the PWM signal no longer appears on PA1 but it does not appear on PB3 although all timer interrupts continue to work as normal. What am I missing?
RCC configuration is as follows:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_SPI1 | RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
Relevant code is below.
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef nvic;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
u32 TimerPeriod = 0;
u16 Channel1Pulse = 0, Channel2Pulse = 0, Channel3Pulse = 0;
// Remap PA1 -> PB3
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
TimerPeriod = 2048;
Channel1Pulse = 144; /* HSYNC */
Channel2Pulse = 352; /* HSYNC + BACK PORCH */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;
TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
/* TIM1 counter enable and output enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
/* Select TIM1 as Master */
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0);
TimerPeriod = 625; /* Vertical lines */
Channel2Pulse = 2; /* Sync pulse */
Channel3Pulse = 24; /* Sync pulse + Back porch */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;
TIM_OCInitStructure.TIM_Pulse = Channel3Pulse;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
/* TIM2 counter enable and output enable */
TIM_CtrlPWMOutputs(TIM2, ENABLE);
/* Interrupt TIM2 */
nvic.NVIC_IRQChannel = TIM2_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 1;
nvic.NVIC_IRQChannelSubPriority = 0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
TIM_ITConfig(TIM2, TIM_IT_CC3, ENABLE);
/* Interrupt TIM1 */
nvic.NVIC_IRQChannel = TIM1_CC_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 1;
nvic.NVIC_IRQChannelSubPriority = 0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
TIM_Cmd(TIM1, ENABLE);
Thanks #old_timer, that put me on the right track. SWO is enabled by default, which is on PB3 and needs to be disabled.
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);
does the trick. The two remappings need to be done separately, combining them does not work.