2020-07-09 07:50 PM
Dear reader
I hope someone can help me with my question. I have programmed an ADC1 on a STM32F103 with the following functions activated:
It all works and generates output based on the code below. The output generated in the loop looks like this
ADC1 = 2890
ADC2 = 0
ADCcnt = 0
ADC_data[0] = 2906
ADC_data[1] = 0
But when I add and activate the interrupt function using NVIC_EnableIRQ which basically only counts the nr of conversions I have a problem.
When I comment in line 89 NVIC_EnableIRQ(ADC1_2_IRQn); everything work till the end of the setup functions but as soon line 89 is executed the loop stops and everything hangs.
I checked the code against what others do but I can't find what is wrong.
What am i missing that i do wrong.
uint16_t value;
uint32_t val32, ADCcnt=0;
uint16_t ADC_data[2] = { 0xAAAA, 0x5555 };
/*
HEX_MEM : Function to output a given section of memory starting from ptr till ptr+(rowa x cols)
a integers mutiple of cols is always output.
cols : nr of colums to out put
rows : nr of rows to be displayed
ptr : pointer/address to the data area to be examend.
Note : replace the prinf() funccvtion
*/
void HEX_MEM(void* ptr, uint8_t width, uint8_t c, uint8_t r) {
uint8_t cols = c, rows = r;
uint8_t rcnt, ccnt;
uint8_t* ptr8;
ptr8 = (uint8_t*)ptr;
switch (width) {
case 8: {
Serial.printf("HEX-MEM ");
for (ccnt = 0; ccnt < cols; ccnt++) Serial.printf(" %X", ccnt);
Serial.printf("\r\n");
for (rcnt = 1; rcnt <= rows; rcnt++) {
Serial.printf("%p: ", ptr8);
for (ccnt = 1; ccnt <= cols; ccnt++) {
Serial.printf("%02X ", (*ptr8));
ptr8++;
}
ptr8 -= ccnt - 1;
for (ccnt = 1; ccnt <= cols; ccnt++) {
if (*ptr8 >= 0x20 && *ptr8 <= 0x7E) Serial.printf("%c.", *ptr8);
else Serial.printf("-.");
ptr8++;
}
Serial.printf("\r\n");
}
} break;
default: Serial.println("Error");
}
}
void ADC1_IRQHandler(void) { // ADC Interupt ISR
ADC1->SR &= ~(0x00000002); // clear EOC status bit
val32 = ADC1->DR;
ADCcnt++;
}
void setup() // The setup() function runs once each time the micro-controller starts
{
Serial.begin(115200);
delay(2000);
Serial.println("program start");
Serial.println("RCC1 ==========================");
HEX_MEM((uint8_t*)RCC, 8, 4, 9);
RCC->APB2ENR = 0x00004615; // Enable: UART1 ADC1, ADC2, IOPCEN IOPAEN, AFIOEN
RCC->AHBENR = 0x00000015; // enable: SRAM, Flash, DMA
GPIOC->CRH = 0x44144444; // Enable: port C PC13 as digital output
GPIOA->CRL = 0x44444400; // Enable: port A PA0 PA1 as analog input
ADC1->SMPR2 = 0x0000003F; // Set Sample time chanel A0 A1 to 239.5 cycles
ADC1->SQR3 = 0x00000020; // Set scan sequence[1.2] to cahnnel A0 en A1
ADC1->SQR1 = 0x00100000; // Set scan sequence cnt=2 cycles
ADC1->CR1 = 0x00000120; // Enable: Scan Mode, IRQ enabled
ADC1->CR2 = 0x00000107; // Enable: DMA, Calibrate, Continues sample Mode, Wakup the ADC
DMA1_Channel1->CNDTR = 0x00000002; // DMA cycle cnt=2
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; // DMA periferal register adress = ADC.DR
DMA1_Channel1->CMAR = (uint32_t)ADC_data; // DMA Memeory adress = ADC_data[0]
DMA1_Channel1->CCR = 0x000005A0; // Set: MEM=16b, PER=16b, MINC=1, CIR=1, EN=1
DMA1_Channel1->CCR |= 0x00000001; // Enable DMA channel1
delay(1); // Stabelise ADCmachine and calibration process(5uS).
ADC1->CR2 |= 0x00000001; // Enable: ADC ADC sampling machine
Serial.println("RCC2 ==========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)RCC, 8, 4, 9);
Serial.println("GPIOA =========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)GPIOA, 8, 4, 7);
Serial.println("GPIOC =========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)GPIOC, 8, 4, 7);
Serial.println("ADC1 ==========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)ADC1, 8, 4, 20);
delay(5000); // Just wait 5 seconds
NVIC_SetPriority(ADC1_2_IRQn, 5); // Set the ADC interupt priority
// NVIC_EnableIRQ(ADC1_2_IRQn); // Enable the ADC interupt.
}
void loop() // Add the main program code into the continuous loop() function
{
digitalWrite(PC13, !digitalRead(PC13)); // Turn the LED from off to on, or on to off
delay(1000);
Serial.printf("ADC1 = %i \n", ADC1->DR & 0x0000FFFF);
Serial.printf("ADC2 = %i \n", ADC1->DR >>16);
Serial.printf("ADCcnt = %i \n", ADCcnt);
Serial.printf("ADC_data[0] = %i \n", ADC_data[0] & 0xFFFF);
Serial.printf("ADC_data[1] = %i \n", ADC_data[1] & 0xFFFF);
Serial.println();
}
2020-07-09 09:29 PM
> NVIC_EnableIRQ(ADC1_2_IRQn)
The name of the ISR suspiciously doesn't match the symbol you use as parameter here, so check in the startup code/vector table the proper ISR name.
Also, you use C++ rather than C, isn't name mangling involved? Ultimately, check in disasm that the proper address is inserted in the vector table.
> ADC1->SR &= ~(0x00000002); // clear EOC status bit
Also this probably doesn't cause directly your problem, but don't RMW into the status register, write directly.
JW
2020-07-09 11:49 PM
Hi Jan, Thanks for trying to help me. I'm working with the IDE of Ardiono but write my software in Visual studio. For the IDE the name of the ISR functions is predefined and loaded in the NVIC interrupt table during compile time. To enable the interrupts in the NVIC the IRQ number must be specified with is defined as ADC1_2_IRQn and has value 18. ISR name and IRQn are not equal but are related.
2020-07-10 04:55 AM
If you set a breakpoint at line 46, does it get hit? I'm not convinced ADC1_IRQHandler is defined correctly.
2020-07-27 10:38 AM
Hi TDK,
I can't set breakpoints, but I can tell you this When I exclude line #86 it works, when i include line 86 it hangs.
I figured out that the interrupt vector table can't be changed the function names for the handles are predefined like ADC1_IRQHandler. I did a check on the address of this function against the address what was in the interrupt vector table and the addresses were different. It seems that by default the Interrupt vector is either a NULL functions or a While(1) forever function. I see my software hanging as soon it call the interrupt functions. It looks like i address a While(1) for ever functions.
It looks like I have a problem with matching the function addresses.
I did dry to use the NVIC_SetVector(TIM4_IRQn, (uint32_t)TIM4_IRQHandler); but now for a TIM4 interrupt, no effect the addresses stay different. I also checked if MS studio refers to the declaration of this ADC1_IRQHandler declaration and it doesn't it sees it as new declared function and that explains the difference in addresses.
My conclusion
I program based on a arduino IDE and use MS studio as a editor. Arduino IDE knows how to attachInterrupts() to a GPIO port but there is no interface for other periferals like TIM and ADC's. The predefined handler function like ADC1_IRQHandler being part of the HAL liberies are not supported under the Arduino IDE environment. Parts of the Hall library are implemented but other parts are missing. My use ISR calls ADC1_IRQHandler and TIM4_IRQHandler are considderd new functionnames and don't mats with the vectors in the fixed ISR vector table.
Question how do I solve that ?