We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I am using the MCBSTM32 evaluation board. I started with the "blinky" project.
I wanted to change it so that I could DMA a block of data from the ADC to memory. OK, I did that and it worked fine.
Next, I wanted to get an interrupt when the specified number of transfers had happened. I modified DMA1_Channel1_IRQHandler in stm32f10x_it.c to toggle a LED and set a flag when it happens. I also set the TCIE bit in DMA_CCR1
Being unfamiliar with the interrupt handler for this processor I looked at the code in STM32_Init.c for inspiration. In there I found that the initialization routines used the following:
NVIC->Enable[n] |= (1 << ( <Position > & 0x1F));
Where n is the 32 bit array element where the bit is in and Position represents the bit position in that element.
With that in mind, and finding no initilization for DMA interrupt, I implemented the following in my code immediately after I enable the DMA chanel:
NVIC->Enable[0] |= (1 << (DMAChannel1_IRQChannel & 0x1F));
Where DMAChannel1_IRQChannel is 0x0B and being the position is less than 32, it should go into the first array element.
Needless to say it does not work. I put a break point on the interrupt and it never breaks. It seems to fault, but gets to an area of code I do not recognise. It is in STM32f10x.s and is the point highlighted in the following:
<snip> EXTI15_10_IRQHandler RTCAlarm_IRQHandler USBWakeUp_IRQHandler B . ENDP ALIGN ; User Initial Stack & Heap IF :DEF:__MICROLIB <snip>
Any help or pointers would be appreciated.
Yes, actually I did so don't give up!!
It ends up that in the stm32f10x_it.c and stm32f10x_it.h files I used the names of the interrupts did not match those in STM32F10x.s! (So much for consistency in programming). Anyway, I finally figured out that this is the default point the program ends up at for an unhandled interrupt.
Here is some code that might help you along. It is for the MCBSTM32 and is just a snip of the initialization and interrupt handler. It has been awhile since I touched this code, so I must state that I can't guarantee that it actually works anymore. It should hopefully gets you going down the right path. Enjoy!
#define DATA_BUFF_SIZE 128 typedef struct { bool done; unsigned short data[DATA_BUFF_SIZE]; }DATA_BUFF; #define DMA_INT_ENABLE 0x00000002 void DMAChannel1_IRQHandler(void) { DMA_Channel1->CCR &= ~DMA_INT_ENABLE; data_buff.done = TRUE; GPIOB->ODR ^= (GPIOB->ODR & 0xFFFF00FF) | 0x200; } void adc_Init (void) { // GPIOA->CRL &= ~0x0000000F; // set PIN1 as analog input (see stm32_Init.c) RCC->AHBENR |= (1<<0); // enable periperal clock for DMA // Setup interrupt for DMA. DMA_Channel1->CMAR = (u32)data_buff.data; // set channel1 memory address DMA_Channel1->CPAR = (u32)&(ADC1->DR); // set channel1 peripheral address DMA_Channel1->CNDTR = DATA_BUFF_SIZE; // transmit data buff size. DMA_Channel1->CCR = 0x000025A0; // configure DMA channel DMA_Channel1->CCR |= DMA_INT_ENABLE; // DMA_Channel1->CCR = 0x00002520; // configure DMA channel // DMA_Channel1->CCR = 0x00002AA2; // configure DMA channel: // Transfer Complete interrupt Enabled, // read from peripheral, // curcular mode (auto reload), // no peripheral increment, // memory increment, // 32 bit perpherial and menory size, // high priority level // no memory to memory mode DMA_Channel1->CCR |= (1 << 0); // DMA Channel 1 enable // Enable interrupt NVIC->Enable[0] |= (1 << (DMAChannel1_IRQChannel & 0x1F)); // enable interrupt RCC->APB2ENR |= (1<<9); // enable periperal clock for ADC1 ADC1->SQR1 &= ~0x00F00000; // only one conversion ADC1->SMPR2 &= 0x00000038; // clear bits 3..5 (channel1) ADC1->SMPR2 |= 0x00000028; // set sample time (55,5 cycles) ADC1->SQR3 &= 0x0000001F; // clear bits 0..4 ADC1->SQR3 |= 0x00000001; // set rank ADC1->CR1 = 0x00000100; // use independant mode, SCAN mode ADC1->CR2 = 0x00000101; // use data align right, single conversion // EXTSEL = Timer 1 CC1 event // enable ADC, DMA mode, external Trigger ADC1->CR2 |= 0x00500000; // start conversion }