ADC ISR stops executing after receiving a CAN frame through ISR

Status
Not open for further replies.
Hello.

I have a program that continuously reads the ADCs using interrupts, and upon request through can relays the data back through CANbus. I'm using collin80's flexcan lib, and pedvide's ADC library.

The problem i'm currently having is that, after receiving a CAN frame and triggering the CAN frame interrupt, the ADC interrupt stops executing, so the values don't get updated. The rest of the interrupts (timing interrupts, CAN interrupts) seem to work fine. Resetting the ADC interrupts doesn't seem to work, as it still remains stuck. When it locks, the NVIC status is as follows:

Code:
NVIC_IS_ENABLED(IRQ_PDB) 0
NVIC_IS_ACTIVE(IRQ_PDB) 0
NVIC_IS_PENDING(IRQ_PDB) 100000000000000000000
NVIC_IS_ENABLED(IRQ_ADC0) 10000000
NVIC_IS_ACTIVE(IRQ_ADC0) 0
NVIC_IS_PENDING(IRQ_ADC0) 0
NVIC_IS_ENABLED(IRQ_ADC1) 10000000000
NVIC_IS_ACTIVE(IRQ_ADC1) 0
NVIC_IS_PENDING(IRQ_ADC1) 0

Do you have any idea on what could cause this behaviour? I have already tried reenabling the global interrupts after receiving a CAN msg, and it does nothing.

Thank you very much for your help

This is the CAN ISR
Code:
bool CAN_reader::frameHandler(CAN_message_t & frame, int mailbox, uint8_t controller) {

	struct CAN_extendedID* received_id_ptr;
	//memcpy(&received_id, &frame.id, sizeof(received_id));
	received_id_ptr = (struct CAN_extendedID*) & frame.id;

#ifdef CAN_DEBUG
	Serial.print("MSG received, mailbox: ");
	Serial.println(mailbox);
	Serial.println(frame.id, HEX);
	Serial.print(received_id_ptr->dest_uscb_flag, HEX);
	Serial.print("  ");
	Serial.print(received_id_ptr->board_id, HEX);
	Serial.print("  ");
	Serial.print(received_id_ptr->msg, HEX);
	Serial.println();
#endif

	if (mailbox == 0) {
		if (received_id_ptr->msg == RPI_REQUEST_START_LOGGING) {
#ifdef RX_DEBUG
			Serial.println("Starting logging");
#endif
			uscb_ptr->createLogFile();
			uscb_ptr->logging = true;
		}
		else if (received_id_ptr->msg == RPI_REQUEST_CONFIG) {
#ifdef RX_DEBUG
			Serial.println("Sending Config");
#endif
			uscb_ptr->sendConfigToCAN();
		}
		else if (received_id_ptr->msg == RPI_REQUEST_LOGGING_STATUS) {
#ifdef RX_DEBUG
			Serial.println("Sending Log Status");
#endif
			uscb_ptr->sendLoggingStatus();
		}
	}
	else if (mailbox == 1) {
		if (received_id_ptr->msg == CANmsg_id_timeset) {
			time_set = true;
			time_t teensy_time;
			memcpy(&teensy_time, &frame.buf, sizeof(time_t));
			setTime(teensy_time);
#ifdef RX_DEBUG
			Serial.print("Time syncronised. New time: ");
			Serial.println(teensy_time);
#endif
		}
	}
}

This is the ADC ISR

Code:
void adc0_isr() {
	static int k = 0;
	k++;
	if (k % 1000 == 0) {
		Serial.println("ADC0_ISR");

	}
	ADC0_measurements[current_ADC0_index] = adc->adc0->readSingle();
	current_ADC0_index++;
	if (current_ADC0_index > 11) {

		current_ADC0_index = 0;
	}
	adc->adc0->startSingleRead(ADC0_pins[current_ADC0_index]);
}

I also have the PDB ISR set:
Code:
void pdb_isr(void) {
	PDB0_SC &= ~PDB_SC_PDBIF; // clear interrupt
}

And this is the code that initialises the ADCs
Code:
void USCB::initADCs() {
	adc->adc0->disableInterrupts();
	adc->adc1->disableInterrupts();

	adc->setReference(ADC_REFERENCE::REF_3V3, ADC_0);
	adc->setReference(ADC_REFERENCE::REF_3V3, ADC_1);
	adc->adc0->setResolution(ADC_RESOLUTION);
	adc->adc1->setResolution(ADC_RESOLUTION);
	adc->setAveraging(ADC_AVERAGING, ADC_0);
	adc->setAveraging(ADC_AVERAGING, ADC_1);

#ifndef HIGH_SPEED_BOARD
	adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, ADC_0);
	adc->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED, ADC_0);
	adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, ADC_1);
	adc->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED, ADC_1);
#else // !HIGH_SPEED_BOARD
	adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, ADC_0);
	adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED, ADC_0);
	adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, ADC_1);
	adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED, ADC_1);
#endif

	adc->adc0->stopPDB();
	adc->adc0->startSingleRead(A0); // call this to setup everything before the pdb starts, differential is also possible
	adc->enableInterrupts(ADC_0);
	adc->adc0->startPDB(MAX_SAMPLING_FREQ*MAX_PINS_PER_ADC); //frequency in Hz
	adc->adc1->stopPDB();
	adc->adc1->startSingleRead(A2); // call this to setup everything before the pdb starts
	adc->enableInterrupts(ADC_1);
	adc->adc1->startPDB(MAX_SAMPLING_FREQ * MAX_PINS_PER_ADC); //frequency in Hz

	// enable PDB    
	interrupts();
}
 
Okay

I've fixed it by lowering the CAN0 MSG interrupt priority to 240:
Code:
NVIC_SET_PRIORITY(IRQ_CAN0_MESSAGE, 240);

I still don't know what causes it, but it works
 
Status
Not open for further replies.
Back
Top