Somebody help me out with EXTIS

animefreak1233
Sat Oct 31, 2015 4:08 pm
I’m a 16 year old self learned hobbyist (but in no way a beginner to low level programming, coming from AVR C and asm). I’ve been banging my head trying to get the EXTIs on my board working. It’s a maple mini BTW. Also, I only use low level functions and directly write to registers when they’re not available.
I’m using libmaple pure. The code
#include <libmaple/gpio.h>
#include <libmaple/exti.h>
#include <libmaple/rcc.h>
#include <libmaple/libmaple.h>
#include <libmaple/libmaple_types.h>
#include <libmaple/nvic.h>
#include <stdint.h>
//GVars---------------------------------------
volatile int s = 1;
//Functions-----------------------------------
static void myHandler();

int main(void){
RCC_BASE->APB2ENR |= (1 << 3);
//Enabling the clock for PORTB
GPIOB->regs->CRL |= ((1 << 4)|(1 << 5));
GPIOB->regs->CRL &= ~((1 << 7)|(1 << 6));//set PB1 as an output
//set PB8 as an input
gpio_set_mode(GPIOB, 8, GPIO_INPUT_PD);
afio_init();
//Enabling AFIO clock
nvic_init(0x80000000, 0x00);
nvic_globalirq_enable();
nvic_irq_set_priority(NVIC_EXTI_9_5, 0x00);
//Enabling interrupts and configuring priorities

exti_attach_interrupt(AFIO_EXTI_8, AFIO_EXTI_PB, myHandler, EXTI_FALLING);
//setting up the EXTI
//blinky
while(1){

if(s == 1)
{

GPIOB->regs->BSRR = (1 << 1);
delay_us(1000000);
GPIOB->regs->BRR = (1 << 1);
delay_us(1000000);
}

}
}

static void myHandler()
{
s = 0;
}



animefreak1233
Sat Oct 31, 2015 10:12 pm
Been through every one of those, but I can’t use the attachInterrupt() function because I need performance for what I’m making. But the exti_attach_interrupt() function doesn’t seem to do anything but let the interrupt execute once, I also tried putting it in a while loop, nothing happened. If the problem was so simple that looking at the documentation was all I needed to do, I wouldn’t be here…

RogerClark
Sat Oct 31, 2015 10:57 pm
If you need high performance, I suspect that the Arduino API is not the best approach, as everything is abstracted and generally not as fast as it could be

I’d recommend you abandon using the Arduino API and IDE and use something like CooCox, or Em:Blocks or Eclipse and program using the STM32Cube and the Standard peripheral library.

Actually, even the STM32Cube HAL based SPL may be too slow for you, as thats a bit abtracted as well, so you may nee to program using Coocox etc and directly setup the interrupt vector tables etc youself.

The best reference is the STM32F1 series programming manual RM0008 http://www.st.com/web/en/resource/techn … 171190.pdf

As this give full details how how to program things at a low level to get the highest performance.


ahull
Sun Nov 01, 2015 1:10 am
I *think* I see what you are trying to do here… If I am correct and you are trying to blink an LED in response to a stimulus on PB8, try this version.

You need to set (or unset) the flag in your ISR, and then unset (or set) in your loop, whichever is the opposite of the action in the ISR.

You could write this in a much simpler, more Arduinoesque form, but the code below should do what I think you are trying to do.

#include <libmaple/gpio.h>
#include <libmaple/exti.h>
#include <libmaple/rcc.h>
#include <libmaple/libmaple.h>
#include <libmaple/libmaple_types.h>
#include <libmaple/nvic.h>
#include <stdint.h>
//GVars---------------------------------------
volatile int s = 1;
//Functions-----------------------------------
static void myHandler();

int main(void){
RCC_BASE->APB2ENR |= (1 << 3);
//Enabling the clock for PORTB
GPIOB->regs->CRL |= ((1 << 4)|(1 << 5));
GPIOB->regs->CRL &= ~((1 << 7)|(1 << 6));//set PB1 as an output
//set PB8 as an input
gpio_set_mode(GPIOB, 8, GPIO_INPUT_PD);
afio_init();
//Enabling AFIO clock
nvic_init(0x80000000, 0x00);
nvic_globalirq_enable();
nvic_irq_set_priority(NVIC_EXTI_9_5, 0x00);
//Enabling interrupts and configuring priorities

exti_attach_interrupt(AFIO_EXTI_8, AFIO_EXTI_PB, myHandler, EXTI_FALLING);
//setting up the EXTI
//blinky
while(1){

if(s == 1)
{
s=0;
GPIOB->regs->BSRR = (1 << 1);
delay_us(1000000);
GPIOB->regs->BRR = (1 << 1);
delay_us(1000000);
}

}
}

static void myHandler()
{
s = 1;
}


animefreak1233
Sun Nov 01, 2015 1:07 pm
And the ISR doesn’t even execute once…
BTW, I posted an older version of the code, I’ve tried using the algorithm, mine didn’t work, neither does yours…
:(

ahull
Sun Nov 01, 2015 1:40 pm
Hi animefreak1233

Try the sketch below. I just tested on my STM32F103RCT6 with a PIR attached to PB8 (your input pin), and an LED on PB0 (my LED pin). You will need to change the LED pin. I’ve added some debug on the USBserial port, but you can change this to a USART port, or simply comment out the serial_debug lines.
(NOTE: You will need to comment the serial_debug out if you don’t attach to the serial debug output, as otherwise it tends to slow the sketch down.)

//
// STM32duino Simple pin interrupt test.
// Pressing the button triggers an interrupt, which sets/unsets the interrupt flag.
// The main loop switches the LED on ot off depending on the interrupt flag
// NOTE: on my board to switch ON the LED, I write a zero to the port pin.Your board may be different.

volatile int buttonISRFlag = LOW; // must declare volatile, since it's
// modified within the blink() handler
#define INPUT_PIN PB8
#define BOARD_LED_PIN PB0

USBSerial serial_debug;

void setup() {
pinMode(BOARD_LED_PIN, OUTPUT);
pinMode(INPUT_PIN, INPUT);
attachInterrupt(INPUT_PIN, blink, CHANGE);
}

void loop() {

// Spit out the current state of the pin, this should follow the state of buttonISRFlag
// There is a delay between the two which is the lenght of time it takes to service the ISR and get back to this point in the loop
// but for our purposes they will appear the same.
serial_debug.print("INPUT_PINP State: ");
serial_debug.println(digitalRead(BOARD_INPUT_PIN));
//
// 1=LED Off, 0=LED on, so we write !buttonISRFlag to the pin.
digitalWrite(BOARD_LED_PIN, !buttonISRFlag);
// Spit out the state of the ISR flag.
serial_debug.print("ISR Flag state: ");
serial_debug.println(buttonISRFlag);
delay(500);
}

void blink() {
buttonISRFlag=!buttonISRFlag;
}


animefreak1233
Sun Nov 01, 2015 3:01 pm
That stuff works fine, but the problem is that I need to use low level C and not the wirish library. I need it to spit out as much performance as needed, and as such, the wirish library isn’t a good choice compared to simple functions and direct reg manipulation. BTW, I’ve tried tracing out the whole process by scouring through the library sources, but nothing worked. I pretty much pasted the code from the attachInterrupt() but nothing happened

ahull
Sun Nov 01, 2015 3:18 pm
Try this for a libmaple version of the same sketch.

//
// STM32duino Simple pin interrupt test.
// Pressing the button triggers an interrupt, which sets/unsets the interrupt flag.
// The main loop switches the LED on ot off depending on the interrupt flag
// NOTE: on my board to switch ON the LED, I write a zero to the port pin.Your board may be different.

volatile int buttonISRFlag = LOW; // must declare volatile, since it's
// modified within the blink() handler
#define INPUT_PIN PB8
#define BOARD_LED_PIN PB0

USBSerial serial_debug;

void setup() {
// Break down arduino stuff to libmaple equivalent...
// pinMode(BOARD_LED_PIN, OUTPUT);
// gpio_init(gpio_dev * dev)
gpio_init(GPIOB);
// gpio_set_mode(gpio_dev * dev, uint8 pin, gpio_pin_mode mode)
gpio_set_mode(GPIOB, 0, GPIO_OUTPUT_OD);

// Break down arduino stuff to libmaple equivalent...
//pinMode(INPUT_PIN, INPUT);
gpio_set_mode(GPIOB, 8, GPIO_INPUT_FLOATING);

// Break down arduino stuff to libmaple equivalent...
// attachInterrupt(INPUT_PIN, blink, CHANGE);
// afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port)

afio_init();
nvic_globalirq_enable();
exti_attach_interrupt(AFIO_EXTI_8, AFIO_EXTI_PB, blink, EXTI_RISING_FALLING);
afio_exti_select(AFIO_EXTI_8, AFIO_EXTI_PB );
nvic_irq_enable(NVIC_EXTI1);

}

void loop() {

// Spit out the current state of the pin, this should follow the state of buttonISRFlag
// There is a delay between the two which is the lenght of time it takes to service the ISR and get back to this point in the loop
// but for our purposes they will appear the same.
serial_debug.print("INPUT_PIN State: ");

// Read our button
// NOTE: The gpio_read_bit() call doesn't quite do the same as the digitalRead() call
// serial_debug.println(digitalRead(BOARD_INPUT_PIN));
serial_debug.println(gpio_read_bit(GPIOB,8));

// 1=LED Off, 0=LED on, so we write !buttonISRFlag to the pin.
//digitalWrite(BOARD_LED_PIN, !buttonISRFlag);
//gpio_write_bit(gpio_dev * dev, uint8 pin, uint8 val)
gpio_write_bit(GPIOB, 0, !buttonISRFlag);
// Spit out the state of the ISR flag.
serial_debug.print("ISR Flag state: ");
serial_debug.println(buttonISRFlag);
delay(500);
}

void blink() {
buttonISRFlag = !buttonISRFlag;
}


animefreak1233
Sun Nov 01, 2015 3:43 pm
There were a few errors in your code, but it finally WORKS!!! I’ll try to find my way around what caused the problem on my side.
I corrected them. You might wanna take a look at your code

#include <wirish/wirish.h>

volatile int buttonISRFlag = LOW; // must declare volatile, since it's
// modified within the blink() handler
#define INPUT_PIN PB8

void blink();

USBSerial serial_debug;

void setup() {
// Break down arduino stuff to libmaple equivalent...
// pinMode(BOARD_LED_PIN, OUTPUT);
// gpio_init(gpio_dev * dev)
gpio_init(GPIOB);
// gpio_set_mode(gpio_dev * dev, uint8 pin, gpio_pin_mode mode)
gpio_set_mode(GPIOB, 1, GPIO_OUTPUT_PP);

// Break down arduino stuff to libmaple equivalent...
//pinMode(INPUT_PIN, INPUT);
gpio_set_mode(GPIOB, 8, GPIO_INPUT_PD);

// Break down arduino stuff to libmaple equivalent...
// attachInterrupt(INPUT_PIN, blink, CHANGE);
// afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port)

afio_init();
nvic_globalirq_enable();
exti_attach_interrupt(AFIO_EXTI_8, AFIO_EXTI_PB, blink, EXTI_RISING_FALLING);
afio_exti_select(AFIO_EXTI_8, AFIO_EXTI_PB );
nvic_irq_enable(NVIC_EXTI_9_5);

}

void loop() {

// Spit out the current state of the pin, this should follow the state of buttonISRFlag
// There is a delay between the two which is the lenght of time it takes to service the ISR and get back to this point in the loop
// but for our purposes they will appear the same.
serial_debug.print("INPUT_PIN State: ");

// Read our button
// NOTE: The gpio_read_bit() call doesn't quite do the same as the digitalRead() call
// serial_debug.println(digitalRead(BOARD_INPUT_PIN));
serial_debug.println(gpio_read_bit(GPIOB,8));

// 1=LED Off, 0=LED on, so we write !buttonISRFlag to the pin.
//digitalWrite(BOARD_LED_PIN, !buttonISRFlag);
//gpio_write_bit(gpio_dev * dev, uint8 pin, uint8 val)
gpio_write_bit(GPIOB, 1, !buttonISRFlag);
// Spit out the state of the ISR flag.
serial_debug.print("ISR Flag state: ");
serial_debug.println(buttonISRFlag);
delay(500);
}

void blink() {
buttonISRFlag = !buttonISRFlag;
}

int main(void){
init();
setup();
while(1)
loop();
}


ahull
Sun Nov 01, 2015 3:48 pm
animefreak1233 wrote:There were a few errors in your code, but it finally WORKS!!! I’ll try to find my way around what caused the problem on my side.
I corrected them. You might wanna take a look at your code

#include <wirish/wirish.h>

volatile int buttonISRFlag = LOW; // must declare volatile, since it's
// modified within the blink() handler
#define INPUT_PIN PB8

void blink();

USBSerial serial_debug;

void setup() {
// Break down arduino stuff to libmaple equivalent...
// pinMode(BOARD_LED_PIN, OUTPUT);
// gpio_init(gpio_dev * dev)
gpio_init(GPIOB);
// gpio_set_mode(gpio_dev * dev, uint8 pin, gpio_pin_mode mode)
gpio_set_mode(GPIOB, 1, GPIO_OUTPUT_PP);

// Break down arduino stuff to libmaple equivalent...
//pinMode(INPUT_PIN, INPUT);
gpio_set_mode(GPIOB, 8, GPIO_INPUT_PD);

// Break down arduino stuff to libmaple equivalent...
// attachInterrupt(INPUT_PIN, blink, CHANGE);
// afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port)

afio_init();
nvic_globalirq_enable();
exti_attach_interrupt(AFIO_EXTI_8, AFIO_EXTI_PB, blink, EXTI_RISING_FALLING);
afio_exti_select(AFIO_EXTI_8, AFIO_EXTI_PB );
nvic_irq_enable(NVIC_EXTI_9_5);

}

void loop() {

// Spit out the current state of the pin, this should follow the state of buttonISRFlag
// There is a delay between the two which is the lenght of time it takes to service the ISR and get back to this point in the loop
// but for our purposes they will appear the same.
serial_debug.print("INPUT_PIN State: ");

// Read our button
// NOTE: The gpio_read_bit() call doesn't quite do the same as the digitalRead() call
// serial_debug.println(digitalRead(BOARD_INPUT_PIN));
serial_debug.println(gpio_read_bit(GPIOB,8));

// 1=LED Off, 0=LED on, so we write !buttonISRFlag to the pin.
//digitalWrite(BOARD_LED_PIN, !buttonISRFlag);
//gpio_write_bit(gpio_dev * dev, uint8 pin, uint8 val)
gpio_write_bit(GPIOB, 1, !buttonISRFlag);
// Spit out the state of the ISR flag.
serial_debug.print("ISR Flag state: ");
serial_debug.println(buttonISRFlag);
delay(500);
}

void blink() {
buttonISRFlag = !buttonISRFlag;
}

int main(void){
init();
setup();
while(1)
loop();
}


ahull
Sun Nov 01, 2015 3:52 pm
BTW I’m about to take the dog for a walk, so I’ll be back in a couple of hours, just in case you think I’ve lost interest.
I look forward to seeing your uberfast version when I get back. :D

One more thing.. I just spotted this little gem in nvic.h NVIC_USBWAKEUP = 42 -USB wakeup from suspend through EXTI line.
I think I’m going to have to have a play with that.


Rick Kimball
Sun Nov 01, 2015 4:12 pm
If your goal is to stay close to the metal with a variety of ARM cortex-m chips, you might want to look at libopencm3 https://github.com/libopencm3/libopencm3 . It is actively developed ( as opposed to libmaple ) and it already runs on a bunch of different chip and boards. It started life out on the STM32F1 chips so they are fairly well supported.

The BlackMagic Probe (BMP) software is built on top of libopencm3.

-rick


stevech
Sun Nov 01, 2015 11:03 pm
CubeMX + STM’s comprehensive HAL I/O library have the advantage of simplifying changing the target MCU to most any other STM F32xxx.
Has a learning curve.
Not Arduino. But the ST HAL libraries have well documented drivers for all on-chip peripherals. And there are API versions for polling, interrupt, and DMA operation.
ST is updating the HALs and CubeMX several times a year and as new MCUs come out.

If you are a very casual “Make” person, and can tolerate the limited choice of I/O in the Arduino world, esp. for STM32s, then the above isn’t for you.
But, if you want to avoid reinventing I/O drivers, or you want to more easily move code between, say, STM32F1xx and STM32F4xx, then IMO the above are the best tools for avocational or professional use.

compiler project output for GCC with Eclipse or IAR/Keil which have free versions for code < 32KB.

And they’re free.


RogerClark
Sun Nov 01, 2015 11:36 pm
Steve

I’ve already posted, basically the same thing. But the OP seems to want to use Arduino API and yet still have fast responses.

Personally, I think they may be able to resolve their speed problems in one place, but sooner or later they will find another place the Arduino API is too slow.


ahull
Mon Nov 02, 2015 12:24 am
RogerClark wrote:Steve

I’ve already posted, basically the same thing. But the OP seems to want to use Arduino API and yet still have fast responses.

Personally, I think they may be able to resolve their speed problems in one place, but sooner or later they will find another place the Arduino API is too slow.


mrburnette
Mon Nov 02, 2015 1:49 am
ahull wrote:RogerClark wrote:
<…>
If I need to control rocket telemetry or bit bang high speed protocols, I may struggle to do it with native Arduino code. Having said that, with more controllers now targeted by the ‘diono method, additional Arduino hardware choices mean that if you want it quicker, you might be better to simply port to a quicker processor.

Leave a Reply

Your email address will not be published. Required fields are marked *