~ruther/uni-mam-arm

uni-mam-arm/arm01/src/main.c -rw-r--r-- 4.7 KiB
f80d4fd6 — Rutherther chore(arm07): add few image upload commands 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <stdint.h>
#include <stm32f4xx.h>
#include "exti.h"
#include "pin.h"
#include "timer.h"
#include "stm32f401xe.h"

#define LED_PIN 5
#define LED_GPIO GPIOA
#define BUTTON_PIN 13
#define BUTTON_GPIO GPIOC
#define BUTTON_GPIO_ID 2 // A 0 B 1 C 2

void hard_fault_handler() {
  while(1) {}
}

void usage_fault_handler() {
  while(1) {}
}

void nmi_handler() {
  while(1) {}
}

void bus_fault_handler() {
  while(1) {}
}


/*----------------------------------------------------------------------------
 * SystemCoreClockConfigure: configure SystemCoreClock using HSI
                             (HSE is not populated on Nucleo board)
 *----------------------------------------------------------------------------*/
void SystemCoreClockSetHSI(void) {

  RCC->CR |= ((uint32_t)RCC_CR_HSION);                     // Enable HSI
  while ((RCC->CR & RCC_CR_HSIRDY) == 0);                  // Wait for HSI Ready

  RCC->CFGR = RCC_CFGR_SW_HSI;                             // HSI is system clock
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);  // Wait for HSI used as system clock

  FLASH->ACR  = FLASH_ACR_PRFTEN;                          // Enable Prefetch Buffer
  FLASH->ACR |= FLASH_ACR_ICEN;                            // Instruction cache enable
  FLASH->ACR |= FLASH_ACR_DCEN;                            // Data cache enable
  FLASH->ACR |= FLASH_ACR_LATENCY_5WS;                     // Flash 5 wait state

  RCC->CFGR |= RCC_CFGR_HPRE_DIV1;                         // HCLK = SYSCLK
  RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;                        // APB1 = HCLK/4
  RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;                        // APB2 = HCLK/2

  RCC->CR &= ~RCC_CR_PLLON;                                // Disable PLL

  // HSI = 16 MHz
  // PLL configuration:  VCO = HSI/M * N,  Sysclk = VCO/P
  // => Sysclk = 48 MHz, APB1 = 12 MHz, APB2 = 24 MHz
  // Since divider for APB1 is != 1, timer clock is 24 MHz
  RCC->PLLCFGR = ( 16ul                   |                // PLL_M =  16
                 (384ul <<  6)            |                // PLL_N = 384
                 (  3ul << 16)            |                // PLL_P =   8
                 (RCC_PLLCFGR_PLLSRC_HSI) |                // PLL_SRC = HSI
                 (  8ul << 24)             );              // PLL_Q =   8

  RCC->CR |= RCC_CR_PLLON;                                 // Enable PLL
  while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP();           // Wait till PLL is ready

  RCC->CFGR &= ~RCC_CFGR_SW;                               // Select PLL as system clock source
  RCC->CFGR |=  RCC_CFGR_SW_PLL;
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);  // Wait till PLL is system clock src
}

pin_t led;
exti_t button_exti;
pin_t button;
timer_t toggle_timer;
timer_t debounce_timer;

// the timer runs at 200 Hz
/* uint16_t timer_values[3] = { 20, 100, 300 }; */
uint16_t timer_values[3] = { 40, 200, 600 };
uint8_t current_timer_value = 1;

void main()
{
  // TODO: enable tim2, exti, syscfg
  SystemCoreClockSetHSI();
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOCEN;
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN;
  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;

  volatile uint32_t dummy;
  dummy = (RCC->AHB1ENR);
  dummy = (RCC->AHB1ENR);
  dummy = (RCC->APB1ENR);
  dummy = (RCC->APB1ENR);
  dummy = (RCC->APB2ENR);
  dummy = (RCC->APB2ENR);

  pin_init(&led, LED_GPIO, LED_PIN);
  pin_into_output_pushpull(&led);
  pin_speed(&led, LOW_SPEED);

  pin_init(&button, BUTTON_GPIO, BUTTON_PIN);
  pin_into_input(&button);

  exti_init(&button_exti, BUTTON_PIN, EXTI, SYSCFG);
  exti_external_interrupt(&button_exti, BUTTON_GPIO_ID);
  exti_falling_interrupt(&button_exti);
  exti_clear_interrupt(&button_exti);
  exti_enable_interrupt(&button_exti);

  // configure toggle timer
  timer_init(&toggle_timer, TIM2, 2);
  timer_set_refresh(&toggle_timer, timer_values[0]);
  timer_configure(&toggle_timer, 1, 60000, 0);
  timer_enable_interrupt(&toggle_timer);
  timer_enable(&toggle_timer);

  // configure debounce timer
  timer_init(&debounce_timer, TIM3, 3);
  timer_set_refresh(&debounce_timer, 10);
  timer_configure(&debounce_timer, 1, 60000, 1);
  timer_enable_interrupt(&debounce_timer);

  __enable_irq();
  while(1) { __WFI(); }
}

// Toggle led timer
void TIM2_handler(void)
{
  timer_clear_interrupt(&toggle_timer);
  pin_toggle(&led);
}

// Debounce button timer
void TIM3_handler(void)
{
  timer_clear_interrupt(&debounce_timer);
  if (!pin_read(&button)) {
    timer_set_refresh(&toggle_timer,
                      timer_values[current_timer_value++]);
    current_timer_value %= sizeof(timer_values) / sizeof(uint16_t);
  }
}

void EXTI15_10_handler(void)
{
  if (exti_is_interrupt(&button_exti)) {
    exti_clear_interrupt(&button_exti);
    timer_set_counter(&debounce_timer, 0);
    timer_enable(&debounce_timer);
  }
}
Do not follow this link