text: /*
   * extint.c
   *
   * author: Furkan Cayci
   * description:
   *   connects the push button located at PA0 to external interrupt 0
   *   lights up the next LED in each press.
   *   Does not elimine debouncing, so will move more then 1 LED most
   *   of the time.
   *
   * external interrupt setup steps:
   *   1. Enable relevant GPIOx port clock from RCC
   * 	 2. Enable SYSCLK clock from RCC
   *   3. Tie the pins(buttons) to EXTIx using EXTICRx
   *   4. Choose the trigger edge using RTSR or FTSR
   *   5. Mask the selected EXTIs from IMR
   *   6. Set priority for the interrupts from IP
   *   7. Enable the EXTIx interrupt from NVIC
   *
   * setup:
   *    uses 1 on-board push button and 4 LEDs
   */
  
  #include "stm32f4xx.h"
  #include "system_stm32f4xx.h"
  
  /*************************************************
  * function declarations
  *************************************************/
  void Default_Handler(void);
  void exti_handler(void);
  int main(void);
  
  /*************************************************
  * Vector Table
  *************************************************/
  // get the stack pointer location from linker
  typedef void (* const intfunc)(void);
  extern unsigned long __stack;
  
  // attribute puts table in beginning of .vectors section
  //   which is the beginning of .text section in the linker script
  // Add other vectors -in order- here
  // Vector table can be found on page 372 in RM0090
  __attribute__ ((section(".vectors")))
  void (* const vector_table[])(void) = {
  	(intfunc)((unsigned long)&__stack), /* 0x000 Stack Pointer */
  	Reset_Handler,                      /* 0x004 Reset         */
  	Default_Handler,                    /* 0x008 NMI           */
  	Default_Handler,                    /* 0x00C HardFault     */
  	Default_Handler,                    /* 0x010 MemManage     */
  	Default_Handler,                    /* 0x014 BusFault      */
  	Default_Handler,                    /* 0x018 UsageFault    */
  	0,                                  /* 0x01C Reserved      */
  	0,                                  /* 0x020 Reserved      */
  	0,                                  /* 0x024 Reserved      */
  	0,                                  /* 0x028 Reserved      */
  	Default_Handler,                    /* 0x02C SVCall        */
  	Default_Handler,                    /* 0x030 Debug Monitor */
  	0,                                  /* 0x034 Reserved      */
  	Default_Handler,                    /* 0x038 PendSV        */
  	Default_Handler,                    /* 0x03C SysTick       */
  	0,                                  /* 0x040 Window WatchDog Interrupt                                         */
  	0,                                  /* 0x044 PVD through EXTI Line detection Interrupt                         */
  	0,                                  /* 0x048 Tamper and TimeStamp interrupts through the EXTI line             */
  	0,                                  /* 0x04C RTC Wakeup interrupt through the EXTI line                        */
  	0,                                  /* 0x050 FLASH global Interrupt                                            */
  	0,                                  /* 0x054 RCC global Interrupt                                              */
  	exti_handler,                       /* 0x058 EXTI Line0 Interrupt                                              */
  	0,                                  /* 0x05C EXTI Line1 Interrupt                                              */
  	0,                                  /* 0x060 EXTI Line2 Interrupt                                              */
  	0,                                  /* 0x064 EXTI Line3 Interrupt                                              */
  	0,                                  /* 0x068 EXTI Line4 Interrupt                                              */
  	0,                                  /* 0x06C DMA1 Stream 0 global Interrupt                                    */
  	0,                                  /* 0x070 DMA1 Stream 1 global Interrupt                                    */
  	0,                                  /* 0x074 DMA1 Stream 2 global Interrupt                                    */
  	0,                                  /* 0x078 DMA1 Stream 3 global Interrupt                                    */
  	0,                                  /* 0x07C DMA1 Stream 4 global Interrupt                                    */
  	0,                                  /* 0x080 DMA1 Stream 5 global Interrupt                                    */
  	0,                                  /* 0x084 DMA1 Stream 6 global Interrupt                                    */
  	0,                                  /* 0x088 ADC1, ADC2 and ADC3 global Interrupts                             */
  	0,                                  /* 0x08C CAN1 TX Interrupt                                                 */
  	0,                                  /* 0x090 CAN1 RX0 Interrupt                                                */
  	0,                                  /* 0x094 CAN1 RX1 Interrupt                                                */
  	0,                                  /* 0x098 CAN1 SCE Interrupt                                                */
  	0,                                  /* 0x09C External Line[9:5] Interrupts                                     */
  	0,                                  /* 0x0A0 TIM1 Break interrupt and TIM9 global interrupt                    */
  	0,                                  /* 0x0A4 TIM1 Update Interrupt and TIM10 global interrupt                  */
  	0,                                  /* 0x0A8 TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */
  	0,                                  /* 0x0AC TIM1 Capture Compare Interrupt                                    */
  	0,                                  /* 0x0B0 TIM2 global Interrupt                                             */
  	0,                                  /* 0x0B4 TIM3 global Interrupt                                             */
  	0,                                  /* 0x0B8 TIM4 global Interrupt                                             */
  	0,                                  /* 0x0BC I2C1 Event Interrupt                                              */
  	0,                                  /* 0x0C0 I2C1 Error Interrupt                                              */
  	0,                                  /* 0x0C4 I2C2 Event Interrupt                                              */
  	0,                                  /* 0x0C8 I2C2 Error Interrupt                                              */
  	0,                                  /* 0x0CC SPI1 global Interrupt                                             */
  	0,                                  /* 0x0D0 SPI2 global Interrupt                                             */
  	0,                                  /* 0x0D4 USART1 global Interrupt                                           */
  	0,                                  /* 0x0D8 USART2 global Interrupt                                           */
  	0,                                  /* 0x0DC USART3 global Interrupt                                           */
  	0,                                  /* 0x0E0 External Line[15:10] Interrupts                                   */
  	0,                                  /* 0x0E4 RTC Alarm (A and B) through EXTI Line Interrupt                   */
  	0,                                  /* 0x0E8 USB OTG FS Wakeup through EXTI line interrupt                     */
  	0,                                  /* 0x0EC TIM8 Break Interrupt and TIM12 global interrupt                   */
  	0,                                  /* 0x0F0 TIM8 Update Interrupt and TIM13 global interrupt                  */
  	0,                                  /* 0x0F4 TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
  	0,                                  /* 0x0F8 TIM8 Capture Compare global interrupt                             */
  	0,                                  /* 0x0FC DMA1 Stream7 Interrupt                                            */
  	0,                                  /* 0x100 FSMC global Interrupt                                             */
  	0,                                  /* 0x104 SDIO global Interrupt                                             */
  	0,                                  /* 0x108 TIM5 global Interrupt                                             */
  	0,                                  /* 0x10C SPI3 global Interrupt                                             */
  	0,                                  /* 0x110 UART4 global Interrupt                                            */
  	0,                                  /* 0x114 UART5 global Interrupt                                            */
  	0,                                  /* 0x118 TIM6 global and DAC1&2 underrun error  interrupts                 */
  	0,                                  /* 0x11C TIM7 global interrupt                                             */
  	0,                                  /* 0x120 DMA2 Stream 0 global Interrupt                                    */
  	0,                                  /* 0x124 DMA2 Stream 1 global Interrupt                                    */
  	0,                                  /* 0x128 DMA2 Stream 2 global Interrupt                                    */
  	0,                                  /* 0x12C DMA2 Stream 3 global Interrupt                                    */
  	0,                                  /* 0x130 DMA2 Stream 4 global Interrupt                                    */
  	0,                                  /* 0x134 Ethernet global Interrupt                                         */
  	0,                                  /* 0x138 Ethernet Wakeup through EXTI line Interrupt                       */
  	0,                                  /* 0x13C CAN2 TX Interrupt                                                 */
  	0,                                  /* 0x140 CAN2 RX0 Interrupt                                                */
  	0,                                  /* 0x144 CAN2 RX1 Interrupt                                                */
  	0,                                  /* 0x148 CAN2 SCE Interrupt                                                */
  	0,                                  /* 0x14C USB OTG FS global Interrupt                                       */
  	0,                                  /* 0x150 DMA2 Stream 5 global interrupt                                    */
  	0,                                  /* 0x154 DMA2 Stream 6 global interrupt                                    */
  	0,                                  /* 0x158 DMA2 Stream 7 global interrupt                                    */
  	0,                                  /* 0x15C USART6 global interrupt                                           */
  	0,                                  /* 0x160 I2C3 event interrupt                                              */
  	0,                                  /* 0x164 I2C3 error interrupt                                              */
  	0,                                  /* 0x168 USB OTG HS End Point 1 Out global interrupt                       */
  	0,                                  /* 0x16C USB OTG HS End Point 1 In global interrupt                        */
  	0,                                  /* 0x170 USB OTG HS Wakeup through EXTI interrupt                          */
  	0,                                  /* 0x174 USB OTG HS global interrupt                                       */
  	0,                                  /* 0x178 DCMI global interrupt                                             */
  	0,                                  /* 0x17C RNG global Interrupt                                              */
  	0                                   /* 0x180 FPU global interrupt                                              */
  };
  
  /*************************************************
  * default interrupt handler
  *************************************************/
  void Default_Handler(void)
  {
  	for (;;);  // Wait forever
  }
  
  /*************************************************
  * external interrupt handler
  *************************************************/
  void exti_handler(void)
  {
  	static uint8_t i = 1;
  
  	// Check if the interrupt came from exti0
  	if (EXTI->PR & (1 << 0)){
  		GPIOD->ODR = (uint16_t)(i << 12);
  
  		/* wait little bit */
  		for(uint32_t j=0; j<1000000; j++);
  
  		if (i == 0x08) {
  			i = 1;
  		} else {
  			i = (uint8_t)(i << 1);
  		}
  
  		// Clear pending bit
  		EXTI->PR = (1 << 0);
  	}
  }
  
  /*************************************************
  * main code starts from here
  *************************************************/
  int main(void)
  {
  	/* set system clock to 168 Mhz */
  	set_sysclk_to_168();
  
  	/* setup LEDs */
  	// enable GPIOD clock (AHB1ENR: bit 3)
  	RCC->AHB1ENR |= (1 << 3);
  	GPIOD->MODER &= 0x00FFFFFF;   // Reset bits 31-24 to clear old values
  	GPIOD->MODER |= 0x55000000;   // Write 01 for all 4 leds to make them output
  
  	/* set up button */
  	// enable GPIOA clock (AHB1ENR: bit 0)
  	RCC->AHB1ENR |= (1 << 0);
  	GPIOA->MODER &= 0xFFFFFFFC;   // Reset bits 0-1 to clear old values
  	GPIOA->MODER |= 0x00000000;   // Make button an input
  
  	// enable SYSCFG clock (APB2ENR: bit 14)
  	RCC->APB2ENR |= (1 << 14);
  
  	/* tie push button at PA0 to EXTI0 */
  	// EXTI0 can be configured for each GPIO module.
  	//   EXTICR1: 0b XXXX XXXX XXXX 0000
  	//               pin3 pin2 pin1 pin0
  	//
  	//   Writing a 0b0000 to pin0 location ties PA0 to EXT0
  	SYSCFG->EXTICR[0] |= 0x00000000; // Write 0000 to map PA0 to EXTI0
  
  	// Choose either rising edge trigger (RTSR) or falling edge trigger (FTSR)
  	EXTI->RTSR |= 0x00001;   // Enable rising edge trigger on EXTI0
  
  	// Mask the used external interrupt numbers.
  	EXTI->IMR |= 0x00001;    // Mask EXTI0
  
  	// Set Priority for each interrupt request
  	NVIC->IP[EXTI0_IRQn] = 0x10; // Priority level 1
  
  	// enable EXT0 IRQ from NVIC
  	NVIC_EnableIRQ(EXTI0_IRQn);
  
  	while(1)
  	{
  	}
  
  	return 0;
  }
  