Dear all,
i want to use a pin change interrupt in a custom application. There is less documentation, but i figured out how to set up the interrupt, but the vesc crashes when the interrupt occours.
Do i have to configure GPIOC 14/15 in a special way because the pins are OSC_OUT ? Or is the interrupt init at the wrong place ?
Thanks in advance
GEorg
hwconf/hw_gsvesc.h:
...
//Trigger and Speed Hall Pins
#define HW_HALL_TRIGGER_GPIO GPIOC
#define HW_HALL_TRIGGER_PIN 13
#define HW_HALL_ROTARY_A_GPIO GPIOC
#define HW_HALL_ROTARY_A_PIN 14
#define HW_HALL_ROTARY_B_GPIO GPIOC
#define HW_HALL_ROTARY_B_PIN 15
#define HW_HALL_ROTARY_A_EXTI_PORTSRC EXTI_PortSourceGPIOC
#define HW_HALL_ROTARY_A_EXTI_PINSRC EXTI_PinSource14
#define HW_HALL_ROTARY_A_EXTI_CH EXTI15_10_IRQn
#define HW_HALL_ROTARY_A_EXTI_LINE EXTI_Line14
#define HW_HALL_ROTARY_A_EXTI_ISR_VEC EXTI15_10_IRQHandler
...
application/app_dpv.c:
#include "ch.h" // ChibiOS
#include "hal.h" // ChibiOS HAL
#include "mc_interface.h" // Motor control functions
#include "hw.h" // Pin mapping on this hardware
#include "timeout.h" // To reset the timeout
#include "commands.h" //just for printf in terminal
#define AVAILABLE_POWERS 3
CH_IRQ_HANDLER(HW_HALL_ROTARY_A_EXTI_ISR_VEC) {
if (EXTI_GetITStatus(HW_HALL_ROTARY_A_EXTI_LINE) != RESET) {
commands_printf("Rotary A Interrupt fired");
// Clear the EXTI line pending bit
EXTI_ClearITPendingBit(HW_HALL_ROTARY_A_EXTI_LINE);
}
}
// Diving Vehicle thread
static THD_FUNCTION(dpv_thread, arg);
static THD_WORKING_AREA(dpv_thread_wa, 2048); // 2kb stack for this thread
void app_dpv_init(void) {
EXTI_InitTypeDef EXTI_InitStructure;
// Set the UART TX pin as an input with pulldown
palSetPadMode(HW_HALL_TRIGGER_GPIO, HW_HALL_TRIGGER_PIN, PAL_MODE_INPUT_PULLUP);
palSetPadMode(HW_HALL_ROTARY_A_GPIO, HW_HALL_ROTARY_A_PIN, PAL_MODE_INPUT_PULLUP);
palSetPadMode(HW_HALL_ROTARY_B_GPIO, HW_HALL_ROTARY_B_PIN, PAL_MODE_INPUT_PULLUP);
// Interrupt on HALL ROTARY A Pin
// Connect EXTI Line to pin
SYSCFG_EXTILineConfig(HW_HALL_ROTARY_A_EXTI_PORTSRC, HW_HALL_ROTARY_A_EXTI_PINSRC);
// Configure EXTI Line
EXTI_InitStructure.EXTI_Line = HW_HALL_ROTARY_A_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// Enable and set EXTI Line Interrupt to the highest priority
nvicEnableVector(HW_HALL_ROTARY_A_EXTI_CH, 0);
chThdCreateStatic(dpv_thread_wa, sizeof(dpv_thread_wa),
NORMALPRIO, dpv_thread, NULL);
}
static THD_FUNCTION(dpv_thread, arg) {
(void)arg;
chRegSetThreadName("app_dpv");
static bool need_to_change_power_in_future = false;
static float power[AVAILABLE_POWERS] = {0.7, 1, 0.5};
static int power_index = 0;
for(;;) {
if (palReadPad(HW_HALL_TRIGGER_GPIO, HW_HALL_TRIGGER_PIN)) {
mc_interface_set_duty(power[power_index]);
need_to_change_power_in_future = true;
} else {
if(need_to_change_power_in_future){
need_to_change_power_in_future = false;
power_index=(power_index+1)%AVAILABLE_POWERS;
}
// If the button is not pressed, release the motor
mc_interface_release_motor();
}
// Run this loop at 100Hz
chThdSleepMilliseconds(10);
// Reset the timeout
timeout_reset();
}
}
mmh, second post with no answer. maybe i should leave the Free Status ?
I have a similar interrupt problem (see my post here https://vesc-project.com/node/377). Really like to know how to trigger the communication in the custom app with interrupts.
Hi gpzhao,
i solved the interrupt problem. i don't know if i did it in the "vesc" way, but it works for me :)
Have a look at https://github.com/CTSchorsch/blcd in the app_dpv branch. there is a application/app_dpv.c file where i set up the interrupt this way:
the interrupt handler is found in irq_handlers.c
i add:
If i understand the datasheet correctly, you have only one Interrupt per PIN Number. so watch out if there are any other pins with interrupt functions
Regards Georg
I wouldn't set your app interrupt to the highest priority...
Hi TechAUmNu,
thanks, yes maybe. I thought about it too.
But, can you explain why ? I found this somewhere in another custom app and copy it
Regards
Georg
I don't know what other interrupts are being used, but generally system critical stuff is highest priority like system timer. User inputs are normally fairly slow so can tolerate being on a lower priority.
Regarding interrupts in applications, as CTSchorsch pointed out, there many pins often share the same ISR handler, which can be a problem if it is used somewhere else. In the latest version of ChibiOS, the PAL driver has pin interrupt support and makes it super easy to set up interrupts and interrupt handlers. I'm planning to move to that version soon, but it requires a bit of work and testing. After that I will make an example custom app that uses interrupts, terminal callbacks and the now supported IMU and AHRS filter. For now you can go with the example above.
One thing you have to keep in mind though is that you cannot use any communication functions from interrupts, and most mc_interface functions are unsafe. What you can do instead is something like this:
Here a thread is waiting for an event, which is generated from the interrupt handler causing the thread to run one iteration in the loop. ChibiOS should reschedule directly after exiting the interrupt, so the thread should be activated quickly. From the thread you can then use all functions safely.
Hi Benjamin,
thanks for your reply. Just for my understanding: the mc_interface is unsafe if this functions are used IN an interrupt service routine ? the use in the custom app thread is safe ?
Georg
That is correct, everything in mc_interface (and most functions in other files) are safe to use from threads.
Hi again,
i updated to FW 3.53 this night. Now my custom app is not working any more :(
Did you change something in the interrupt handling ? Is now something use external interrupt on pin14 ?
Regards Georg
Hi Benjamin,
any news on updating to a newer ChibiOS ?
As you said Pin Interrupt support on the new ChibiOS is really neat and easy to use.
Would appreciate it.
best regards
Thomas