mavishak / cnss-embedded

1 stars 0 forks source link

Setting External Interrupts #8

Open mavishak opened 3 years ago

mavishak commented 3 years ago

Finally, We have succeeded in enabling External GPIO Interrupts. So now we have a program that blinks LD2 when pressing B1 with init_interrupt(); A program that blinks LD2 when using pull-up with pin D6 and ground with init_interrupt_D6(); And a program that blinks LD2 using SysTick interrupt.

and without interruption: We have a program that blinks LD2 when pressing B1 with init();

Our problem was enabling the line of interrupts with AFIO->EXTICR: Solution

  1. Inorder to write ro AFIO->EXTRIC one must enable RCC clk for the register.
  2. EXTICR is an array: EXTICR[0] contains EXTICR1, EXTICR[1] contains EXTICR2 and so on.

Since we haven't succeeded to connect STM32CubeIDE and GitHub we are posting the code in this issue:

#if !defined(__SOFT_FP__) && defined(__ARM_FP)
  #warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif

#include "stm32f103xb.h"
#include "cmsis_gcc.h"/*for __disable/enable_irq()*/
#include "core_cm3.h" /*for NVIC_enableIRQ()*/
#include "event_queue.h"

//HOW DO YOU SET THE FREQUENCY TO NO HIGHER THAN 18MHz -> This is necessary for APB2 BUS

void init();
void init_interrupt();
void init_interrupt_D6();
uint32_t was_pressed();
void toggle_led();

uint32_t i = 0;

enum {OFF, ON} state;

int main(void)
{

    state = OFF;
    //init();
    init_interrupt();
    //init_interrupt_D6();
    //SysTick_Config(15000000);

    while(1)
    {
        /*if(was_pressed())
        {
            i=5;
            toggle_led();
        }*/

    }
}

/*This function enables user button B1 and led LD2*/
void init()
{
    /*RCC enabled for user button PC13*/
    RCC->APB2ENR |= 0x0010; //enable reset and control clock for port c (see reference manual 8.3.7)

    /*RCC enabled for led PA5*/
    RCC->APB2ENR |= 0x0004; //enable reset and control clock for port A (see reference manual 8.3.7)

    /*Configure user button PC13*/
    GPIOC->CRH &= 0xFF0FFFFF; //reset CNF and MODE only for bit 13, leave all the rest as they are
    GPIOC->CRH |= 0x00400000; //enable input with floating input reset IDR bit 13 (see reference manual 9.2.2)

    /*Configure led PA5*/
    GPIOA->CRL &= 0xFF0FFFFF; //reset CNF and MODE only for bit 5, leave all the rest as they are
    GPIOA->CRL |= 0x00200000; //PA5 configured to General purpose output push-pull | Output mode, max speed 2 MHz

}

/*This function enables user button B1 and led LD2 and interrupts*/
void init_interrupt()
{
    /*RCC enabled for user button PC13*/
    RCC->APB2ENR |= 0x00000010; //enable reset and control clock for port c (see reference manual 8.3.7)

    /*RCC enabled for led PA5*/
    RCC->APB2ENR |= 0x00000004; //enable reset and control clock for port A (see reference manual 8.3.7)

    /*RCC enable AFIO*/
    RCC->APB2ENR |= 0x00000001; //enable AFIO clk for interrupts (see reference manual 8.3.7 and 9.4)

    /*Configure user button PC13*/
    GPIOC->CRH &= 0xFF0FFFFF; //reset CNF and MODE only for bit 13, leave all the rest as they are
    GPIOC->CRH |= 0x00800000; //enable input with pullup/pulldown reset IDR bit 13 (see reference manual 9.2.2)
    GPIOC->ODR |= 0x00002000; // pull up

    /*Configure led PA5*/
    GPIOA->CRL &= 0xFF0FFFFF; //reset CNF and MODE only for bit 5, leave all the rest as they are
    GPIOA->CRL |= 0x00200000; //PA5 configured to General purpose output push-pull | Output mode, max speed 2 MHz

    /*Enable interrupts for PC13 rising triger*/
    __disable_irq();
    /*NOTE: It seems that EXTICR4 is reachable via the third index*/
    AFIO->EXTICR[3] |= 0x00000020; //Set interrupts for port c in line_13(see reference manual 9.4.6)
    EXTI->IMR |= 0x00002000; //Enable iterrupt with mask (see reference manual 10.3.1)
    EXTI->RTSR |= 0x00002000 ; //rising trigger selection register ((see reference manual 10.3.3)
    NVIC_EnableIRQ(EXTI15_10_IRQn); //enable handler
    __enable_irq();

}

/*This function Initiolizes D6 (PB10) as input with interrupt and LD2 (PA5) as output*/
void init_interrupt_D6(){

    /*RCC enabled for led PA5*/
    RCC->APB2ENR |= 0x00000004; //enable reset and control clock for port A (see reference manual 8.3.7)

    /*RCC enabled for D6 GPIO - (PB10) (external button)*/
    RCC->APB2ENR |= 0x00000008; //enable reset and control clock for port B (see reference manual 8.3.7)

    /*RCC enable AFIO*/
    RCC->APB2ENR |= 0x00000001; //enable AFIO clk for interrupts (see reference manual 7.3.7 and 9.4)

    /*Configure led PA5*/
    GPIOA->CRL &= 0xFF0FFFFF; //reset CNF and MODE only for bit 5, leave all the rest as they are
    GPIOA->CRL |= 0x00200000; //PA5 configured to General purpose output push-pull | Output mode, max speed 2 MHz

    /*Configure external button PB10*/
    GPIOB->CRH &= 0xFFFFF0FF; //reset CNF and MODE only for bit 10, leave all the rest as they are
    GPIOB->CRH |= 0x00000800; //PB10 configured to Input with pull-up / pull-down | Input mode (reset state)
    GPIOB->ODR |= 0x00000400; //PB10 configures as pull-up (see reference manual 9.2.4 and Table 20 pg. 161)

    /*Enable interrupts for PB10 rising triger*/
    __disable_irq();
    /*NOTE: It seems that EXTICR3 is reachable via the second index*/
    AFIO->EXTICR[2] |= 0x00000100; // Allow interupts for line_10 (see reference manual 9.4.6 and pg. 210)
    EXTI->IMR |= 0x00000400; //Enable iterrupt with mask for port B pin 10 (see reference manual 10.3.1)
    EXTI->RTSR |= 0x00000400 ; //rising trigger selection register - to anable full button press before reacting ((see reference manual 10.3.3)
    NVIC_EnableIRQ(EXTI15_10_IRQn); //enable handler
    __enable_irq();

}
/*This function returns 1 if user button B1 was pressed*/
uint32_t was_pressed()
{

    return (GPIOC->IDR & 0x2000) == 0x2000;
}

void toggle_led()
{

    if(state == OFF)
    {
        GPIOA->ODR |= 0x0020;
        state=ON;
    }
    else
    {
        GPIOA->ODR &= ~(0x0020);
        state=OFF;
    }
}

/*Interrupt service routine for user button*/
void EXTI15_10_IRQHandler(void) //EXTI4_IRQHandler(void)
{
    i=5;

    EXTI->PR = 0x00002000; //reset flag by writing 1 to bit 13 (reference manual 10.3.6)
    EXTI->PR |= 0x00000400; //reset flag by writing 1 to bit 10 (reference manual 10.3.6)
    if(state == OFF)
    {
        GPIOA->ODR |= 0x0020;
        state=ON;
    }
    else
    {
        GPIOA->ODR &= ~(0x0020);
        state=OFF;
    }
}

// interrupt works
void SysTick_Handler(void)
{
    if(state == OFF)
    {
        GPIOA->ODR |= 0x0020;
        state=ON;
    }
    else
    {
        GPIOA->ODR &= ~(0x0020);
        state=OFF;
    }
}