ARMEBS4  revision-26.06.2015
bsp_armebs4.c
1 /************************************************************************//**
2  * \file bsp.h
3  * \brief BSP for ARMEBS44
4  * \author marc dot pignat at hevs dot ch
5  ***************************************************************************/
6 
7 #if defined (BOARD_ARMEBS4)
8 #include "heivs/bsp.h"
9 
10 #include "stm32/stm32f4xx_fsmc.h"
11 #include "stm32/stm32f4xx_rcc.h"
12 #include "heivs/ram_test.h"
13 #include "heivs/time.h"
14 #include "heivs/retarget.h"
15 
16 /**
17  * Pins used by the FSCM (RAM and display)
18  */
19 static const struct gpio_t fscm_pins[] =
20 {
21  // Addresses
22  GPIO_FSMC_A0_PF0,
23  GPIO_FSMC_A1_PF1,
24  GPIO_FSMC_A2_PF2,
25  GPIO_FSMC_A3_PF3,
26  GPIO_FSMC_A4_PF4,
27  GPIO_FSMC_A5_PF5,
28  GPIO_FSMC_A6_PF12,
29  GPIO_FSMC_A7_PF13,
30  GPIO_FSMC_A8_PF14,
31  GPIO_FSMC_A9_PF15,
32  GPIO_FSMC_A10_PG0,
33  GPIO_FSMC_A11_PG1,
34  GPIO_FSMC_A12_PG2,
35  GPIO_FSMC_A13_PG3,
36  GPIO_FSMC_A14_PG4,
37  GPIO_FSMC_A15_PG5,
38  GPIO_FSMC_A16_PD11,
39  GPIO_FSMC_A17_PD12,
40  GPIO_FSMC_A18_PD13,
41  GPIO_FSMC_A19_PE3,
42  GPIO_FSMC_A20_PE4,
43  GPIO_FSMC_A21_PE5,
44 
45  // Datas
46  GPIO_FSMC_D0_PD14,
47  GPIO_FSMC_D1_PD15,
48  GPIO_FSMC_D2_PD0,
49  GPIO_FSMC_D3_PD1,
50  GPIO_FSMC_D4_PE7,
51  GPIO_FSMC_D5_PE8,
52  GPIO_FSMC_D6_PE9,
53  GPIO_FSMC_D7_PE10,
54  GPIO_FSMC_D8_PE11,
55  GPIO_FSMC_D9_PE12,
56  GPIO_FSMC_D10_PE13,
57  GPIO_FSMC_D11_PE14,
58  GPIO_FSMC_D12_PE15,
59  GPIO_FSMC_D13_PD8,
60  GPIO_FSMC_D14_PD9,
61  GPIO_FSMC_D15_PD10,
62 
63  // Control
64  GPIO_FSMC_NE1_FSMC_NCE2_PD7,
65  GPIO_FSMC_NE2_FSMC_NCE3_PG9,
66  GPIO_FSMC_NWE_PD5,
67  GPIO_FSMC_NOE_PD4,
68  GPIO_FSMC_BLN1_PE1,
69  GPIO_FSMC_NBL0_PE0,
70 };
71 
72 /**
73  * \brief init FSMC and related pins
74  *
75  * On this board the external RAM and the LCD are connected on the FSMC
76  */
77 static status_e bsp_init_FSMC(void)
78 {
79  // Setup gpios
80  gpio_setup_list(fscm_pins, ARRAY_SIZE(fscm_pins));
81 
82  // enable clock
83  RCC_AHB3PeriphClockCmd(RCC_AHB3ENR_FSMCEN, ENABLE);
84 
87 
88  // RAM
89  timings.FSMC_AddressSetupTime = 5;
90  timings.FSMC_AddressHoldTime = 2;
91  timings.FSMC_DataSetupTime = 7;
92  timings.FSMC_BusTurnAroundDuration = 3;
93  timings.FSMC_CLKDivision = 0;
94  timings.FSMC_DataLatency = 2;
95  timings.FSMC_AccessMode = FSMC_AccessMode_A;
96 
97  fscm.FSMC_Bank = FSMC_Bank1_NORSRAM1;
98  fscm.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
99  fscm.FSMC_MemoryType = FSMC_MemoryType_PSRAM;
100  fscm.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
101  fscm.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
102  fscm.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
103  fscm.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
104  fscm.FSMC_WrapMode = FSMC_WrapMode_Disable;
105  fscm.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
106  fscm.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
107  fscm.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
108  fscm.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
109  fscm.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
110  fscm.FSMC_ReadWriteTimingStruct = &timings;
111  fscm.FSMC_WriteTimingStruct = &timings;
112 
113  FSMC_NORSRAMInit(&fscm);
114  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
115 
116  // LCD
117  timings.FSMC_AddressSetupTime = 6;
118  timings.FSMC_AddressHoldTime = 0;
119  timings.FSMC_DataSetupTime = 6;
120  timings.FSMC_BusTurnAroundDuration = 1;
121  timings.FSMC_CLKDivision = 0;
122  timings.FSMC_DataLatency = 0;
123  timings.FSMC_AccessMode = FSMC_AccessMode_A;
124 
125  fscm.FSMC_Bank = FSMC_Bank1_NORSRAM2;
126  fscm.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
127  fscm.FSMC_MemoryType = FSMC_MemoryType_SRAM;
128  fscm.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
129  fscm.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
130  fscm.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
131  fscm.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
132  fscm.FSMC_WrapMode = FSMC_WrapMode_Disable;
133  fscm.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
134  fscm.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
135  fscm.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
136  fscm.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
137  fscm.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
138  fscm.FSMC_ReadWriteTimingStruct = &timings;
139  fscm.FSMC_WriteTimingStruct = &timings;
140 
141  FSMC_NORSRAMInit(&fscm);
142  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM2, ENABLE);
143 
144  return NO_ERROR;
145 }
146 
147 /**
148  * \brief Load .ext_ram_data and zero .ext_ram_bss
149  */
150 static void load_init_external_ram(void)
151 {
152  extern uint8_t __ext_ram_bss_start;
153  extern uint8_t __ext_ram_bss_end;
154 
155  extern uint8_t __ext_ram_dst_start;
156  extern uint8_t __ext_ram_dst_end;
157  extern uint8_t __ext_ram_src_start;
158 
159  memset(&__ext_ram_bss_start, 0x0, &__ext_ram_bss_end - &__ext_ram_bss_start);
160  memcpy(&__ext_ram_dst_start,&__ext_ram_src_start, &__ext_ram_dst_end - & __ext_ram_dst_start);
161 }
162 
163 /**
164  * \brief Timers for the leds
165  *
166  * In ascending LED order
167  */
168 static TIM_TypeDef *led_timers[] =
169 {
170  TIM14,
171  TIM13,
172  TIM11,
173  TIM10,
174 };
175 
176 /**
177  * \brief initialize PWM for leds
178  *
179  * \param frequency, the frequency of the PWM
180  * \param steps, the number of steps
181  * \param initial, the initial value
182  */
183 static void bsp_pwm_leds_init(uint32_t frequency, uint32_t steps, uint32_t initial)
184 {
185  size_t i;
186  const struct gpio_t pins[] =
187  {
188  GPIO_TIM14_CH1_PF9,
189  GPIO_TIM13_CH1_PF8,
190  GPIO_TIM11_CH1_PF7,
191  GPIO_TIM10_CH1_PF6,
192  };
193 
194  // Pin setup
195  gpio_setup_list(pins, ARRAY_SIZE(pins));
196 
197  // Enable clocks
198  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
199  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, ENABLE);
200  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, ENABLE);
201  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
202 
203  // Reset timers
204  RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, ENABLE);
205  RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, DISABLE);
206  RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, ENABLE);
207  RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, DISABLE);
208  RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, ENABLE);
209  RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, DISABLE);
210  RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, ENABLE);
211  RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, DISABLE);
212 
213  for (i = 0 ; i < ARRAY_SIZE(led_timers) ; i++)
214  {
215  led_timers[i]->CCER = TIM_CCER_CC1E;
216 
217  // Timer frequency = steps * input_frequency
218  led_timers[i]->PSC = (((SystemClock.timer)/steps)/frequency) - 1;
219 
220  // Count steps (from zero to steps - 1)
221  led_timers[i]->ARR = steps - 1;
222 
223  // Set the output value to initial value
224  led_timers[i]->CCR1 = initial;
225 
227 
228  // Update registers now
229  led_timers[i]->EGR |= TIM_EGR_UG;
230 
231  // Start the timer
232  led_timers[i]->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN;
233  }
234 }
235 
236 void bsp_led_set_pwm(uint32_t nr, uint32_t value)
237 {
238  if (nr < 4)
239  {
240  led_timers[nr]->CCR1 = lightness_to_pwm(value);
241  }
242 }
243 
244 void bsp_led_set(uint32_t nr, uint32_t value)
245 {
246  bsp_led_set_pwm(nr, value > 0 ? BSP_PWM_LED_STEPS : 0);
247 }
248 
249 void bsp_led_toggle(uint32_t nr)
250 {
251  if (nr < 4)
252  {
253  if (led_timers[nr]->CCR1)
254  {
255  led_timers[nr]->CCR1 = 0;
256  }
257  else
258  {
259  led_timers[nr]->CCR1 = BSP_PWM_LED_STEPS;
260  }
261  }
262 }
263 
264 /**
265  * \brief initialize PWM for the LCD backlight
266  *
267  * \param frequency, the frequency of the PWM
268  * \param steps, the number of steps
269  * \param initial, the initial value
270  */
271 static status_e bsp_lcd_backlight_init(uint32_t frequency, uint32_t steps, uint32_t initial)
272 {
273  const struct gpio_t pins[] =
274  {
275  GPIO_TIM5_CH4_PI0,
276  };
277 
278  // Pin setup
279  gpio_setup_list(pins, ARRAY_SIZE(pins));
280 
281  // Enable the timer clock
282  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
283 
284  // Reset the timer
285  RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE);
286  RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE);
287 
288  TIM5->CCER =
290  ;
291 
292  TIM5->BDTR = TIM_BDTR_MOE;
293 
294  // Timer frequency = steps * input_frequency
295  TIM5->PSC = (((SystemClock.timer)/steps)/frequency) - 1;
296 
297  //ount steps (from zero to steps - 1)
298  TIM5->ARR = steps - 1;
299 
300  // Set the intial value
301  TIM5->CCR4 = initial;
302 
304 
305  // Update registers now
306  TIM5->EGR |= TIM_EGR_UG;
307 
308  // Start the timer
309  TIM5->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN;
310 
311  return NO_ERROR;
312 }
313 
314 void bsp_lcd_backlight_set(uint32_t value)
315 {
316  TIM5->CCR4 = value;
317 }
318 
319 /**
320  * \brief Buttons
321  */
322 static const struct gpio_t bsp_buttons[BSP_BUTTON_NR] =
323 {
328 };
329 
330 /**
331  * \brief initialize buttons
332  */
333 static status_e bsp_buttons_init(void)
334 {
335  gpio_setup_list(bsp_buttons, ARRAY_SIZE(bsp_buttons));
336 
337  return NO_ERROR;
338 }
339 
340 uint32_t bsp_button_get(uint32_t nr)
341 {
342  if (nr >= BSP_BUTTON_NR)
343  {
344  return 0;
345  }
346 
347  return !gpio_get(&bsp_buttons[nr]);
348 }
349 
350 const struct gpio_t *bsp_button_gpios(void)
351 {
352  return &bsp_buttons[0];
353 }
354 
355 /**
356  * \brief OTG VBUS not enable pin
357  */
358 const struct gpio_t gpio_vbus_not = PIN_VBUS_NOT;
359 
360 /**
361  * \brief Safe pin state
362  *
363  * Safe state defined in this order :
364  * * JTAG pins in JTAG mode
365  * * External devices in reset or shutdown mode
366  * * connected pins in input mode
367  * * unconnected pins in input with pull-up
368  */
369 static const struct gpio_t all_pins_safe_values[] =
370 {
371  DEF_GPIOA( 0, GPIO_AN),
372  DEF_GPIOA( 1, GPIO_INPUT),
374  DEF_GPIOA( 3, GPIO_INPUT),
376  DEF_GPIOA( 5, GPIO_AN),
378  DEF_GPIOA( 7, GPIO_INPUT),
380  DEF_GPIOA( 9, GPIO_INPUT),
381  DEF_GPIOA(10, GPIO_INPUT),
384  // JTAG
385  GPIO_JTMS_SWDIO_PA13,
386  GPIO_JTCK_SWCLK_PA14,
387  GPIO_JTDI_PA15,
388 
392 
393  // JTAG
394  GPIO_JTDO_TRACESWO_PB3,
395  GPIO_NJTRST_PB4,
398  DEF_GPIOB( 7, GPIO_INPUT),
399  DEF_GPIOB( 8, GPIO_INPUT),
400  DEF_GPIOB( 9, GPIO_INPUT),
402  DEF_GPIOB(11, GPIO_INPUT),
407 
409  DEF_GPIOC( 1, GPIO_INPUT),
411  DEF_GPIOC( 3, GPIO_AN),
412  DEF_GPIOC( 4, GPIO_INPUT),
413  DEF_GPIOC( 5, GPIO_INPUT),
422  DEF_GPIOC(14, GPIO_INPUT),
423  DEF_GPIOC(15, GPIO_INPUT),
424 
441 
458 
469  PIN_VBUS_NOT,
475 
491  PIN_WD,
492 
493  DEF_GPIOH( 0, GPIO_INPUT),
494  DEF_GPIOH( 1, GPIO_INPUT),
495  PIN_RESET_NOT_CAMERA,
496  PIN_RESET_NOT_SCREEN,
499  PIN_RESET_NOT_ETHERNET,
509 
522 
523 };
524 
526 {
527  status_e status;
528 
529  // Set all pins to safe values
530  gpio_setup_list(all_pins_safe_values, ARRAY_SIZE(all_pins_safe_values));
531 
532  // Set OTG VBUS to off
533  gpio_setup(&gpio_vbus_not);
534 
535  // Initialize time early, it is required by many other functions
536  time_init();
537 
538  /**
539  * Unfortunately our Ethernet PHY consumes a lot of power when in reset,
540  * so put it in low power mode.
541  */
543 
544  // Initialize the LEDs
545  bsp_pwm_leds_init(10*1000, BSP_PWM_LED_STEPS, 0);
546 
547  // Initialize stdin/stdout
548  retarget_init();
549 
550  // Initialize buttons
551  status = bsp_buttons_init();
552  if (status != NO_ERROR)
553  {
554  return status;
555  }
556 
557  // Initialize the external (address/data) bus
558  status = bsp_init_FSMC();
559  if (status != NO_ERROR)
560  {
561  return status;
562  }
563 
564  /* Quick test the external RAM */
565  status = ram_test_basic((uint32_t *)EXT_RAM_BASE, EXT_RAM_SIZE);
566  if (status != NO_ERROR)
567  {
568  return status;
569  }
570 
571  // Initialize external ram sections
572  load_init_external_ram();
573 
574  /**
575  * Initialize the LCD backlight
576  * 33 KHz seems a good working frequency for the G5126TB1U.
577  */
578  status = bsp_lcd_backlight_init(33*1000, BSP_PWM_LED_STEPS, 0);
579  if (status != NO_ERROR)
580  {
581  return status;
582  }
583 
584  return NO_ERROR;
585 
586 }
587 #if (USE_STM32_USB_HOST_MODE || USE_STM32_USB_USE_DEVICE_MODE || USE_STM32_USB_OTG_MODE)
588 #include "stm32/usb/usb_core.h"
589 #include "heivs/delay.h"
590 
591 void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev, uint8_t state)
592 {
593  (void)pdev;
594  const struct gpio_t gpio_vbus_not = PIN_VBUS_NOT;
595  gpio_set(&gpio_vbus_not, !state);
596 }
597 
598 void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev)
599 {
600  const struct gpio_t gpio_vbus_not = PIN_VBUS_NOT;
601  gpio_setup(&gpio_vbus_not);
602  USB_OTG_BSP_DriveVBUS (pdev, 0);
603 
604  delay_wait_ms(200);
605 }
606 #endif /* (USE_STM32_USB_HOST_MODE || USE_STM32_USB_USE_DEVICE_MODE || USE_STM32_USB_OTG_MODE) */
607 
608 #endif
This file contains all the functions prototypes for the RCC firmware library.
BSP - Board Support Package.
#define DEF_GPIOF(__PIN, __MODE)
same as DEF_GPIOA for port F
Definition: stm32_gpio.h:364
stdio redirection
uint8_t nr
Pin number (0 for GPIOx0, ... , 3 for GPIOx3, ...)
Definition: stm32_gpio.h:99
RAM test.
#define TIM_CCMR2_OC4M_2
Definition: stm32f4xx.h:6229
void delay_wait_ms(uint32_t ms)
Wait for at least that time.
Definition: delay.c:12
Output (default 1)
Definition: stm32_gpio.h:53
#define BSP_BUTTON_NR
Number of buttons.
Definition: bsp_armebs4.h:23
pull down
Definition: stm32_gpio.h:86
Timing parameters For NOR/SRAM Banks.
simple time abstraction
void * memcpy(void *dest, const void *src, size_t n)
void * memset(void *dest, int n, size_t n)
#define DEF_GPIOB(__PIN, __MODE)
same as DEF_GPIOA for port B
Definition: stm32_gpio.h:360
#define TIM_CR1_CEN
Definition: stm32f4xx.h:6051
void bsp_lcd_backlight_set(uint32_t value)
Set the brightness of the backlight.
Definition: bsp_armebs4.c:314
#define TIM_CCER_CC1E
Definition: stm32f4xx.h:6256
FSMC NOR/SRAM Init structure definition.
__IO uint16_t EGR
Definition: stm32f4xx.h:874
uint8_t lightness_to_pwm(uint8_t percentage)
PWM value for driving a LED expressed as perceived percentage.
__IO uint16_t CCMR1
Definition: stm32f4xx.h:876
FSMC_NORSRAMTimingInitTypeDef * FSMC_WriteTimingStruct
#define DEF_GPIOD(__PIN, __MODE)
same as DEF_GPIOA for port D
Definition: stm32_gpio.h:362
static void gpio_set(const struct gpio_t *gpio, uint32_t value)
Set a gpio.
Definition: stm32_gpio.h:260
__IO uint16_t CCER
Definition: stm32f4xx.h:880
static uint32_t gpio_get(const struct gpio_t *gpio)
Get gpio level.
Definition: stm32_gpio.h:219
#define DEF_GPIOA(__PIN, __MODE)
Helper for defining a pin.
Definition: stm32_gpio.h:358
void bsp_led_set(uint32_t nr, uint32_t value)
Set a led (ON or OFF)
Definition: bsp_armebs4.c:244
#define DEF_GPIOG(__PIN, __MODE)
same as DEF_GPIOA for port G
Definition: stm32_gpio.h:365
#define TIM_CCMR2_OC4PE
Definition: stm32f4xx.h:6224
void bsp_led_toggle(uint32_t nr)
toggle a led
Definition: bsp_armebs4.c:249
#define TIM_CCMR1_OC1M_2
Definition: stm32f4xx.h:6164
#define BSP_PWM_LED_STEPS
Lightness correction.
Definition: bsp_armebs4.h:21
#define TIM_CCMR1_OC1M_1
Definition: stm32f4xx.h:6163
GPIO control structure.
Definition: stm32_gpio.h:96
Input.
Definition: stm32_gpio.h:44
FSMC_NORSRAMTimingInitTypeDef * FSMC_ReadWriteTimingStruct
__IO uint16_t CR1
Definition: stm32f4xx.h:864
#define TIM_CCER_CC4E
Definition: stm32f4xx.h:6268
#define TIM_BDTR_MOE
Definition: stm32f4xx.h:6316
This file contains all the functions prototypes for the FSMC firmware library.
simple delays
#define TIM_CR1_ARPE
Definition: stm32f4xx.h:6061
#define TIM_CCMR2_OC4M_1
Definition: stm32f4xx.h:6228
#define TIM_EGR_UG
Definition: stm32f4xx.h:6144
#define DEF_GPIOC(__PIN, __MODE)
same as DEF_GPIOA for port C
Definition: stm32_gpio.h:361
status_e ram_test_basic(uint32_t *base, size_t size)
Quickly test a RAM region.
Definition: ram_test.c:8
struct system_clock_t SystemClock
#define DEF_GPIOH(__PIN, __MODE)
same as DEF_GPIOA for port H
Definition: stm32_gpio.h:366
#define DEF_GPIOE(__PIN, __MODE)
same as DEF_GPIOA for port E
Definition: stm32_gpio.h:363
void bsp_eth_powerdown(void)
Shutdown the Ethernet interface.
status_e gpio_setup_list(const struct gpio_t gpio[], size_t len)
Setup an array of gpio.
Definition: stm32_gpio.c:47
Output speed : 2 MHz.
Definition: stm32_gpio.h:68
status_e gpio_setup(const struct gpio_t *gpio)
Setup a gpio.
Definition: stm32_gpio.c:9
status_e
Known errors.
Definition: error.h:21
#define ARRAY_SIZE(x)
Number of elements in the array.
Definition: utils.h:19
#define TIM_CCMR1_OC1PE
Definition: stm32f4xx.h:6159
__IO uint16_t PSC
Definition: stm32f4xx.h:883
No error.
Definition: error.h:28
const struct gpio_t * bsp_button_gpios(void)
get buttons gpios
Definition: bsp_armebs4.c:350
#define DEF_GPIOI(__PIN, __MODE)
same as DEF_GPIOA for port I
Definition: stm32_gpio.h:367
Pull up.
Definition: stm32_gpio.h:83
Analog.
Definition: stm32_gpio.h:59
__IO uint32_t CCR1
Definition: stm32f4xx.h:888
status_e bsp_init(void)
Initialize the whole board.
Definition: bsp_armebs4.c:525
__IO uint32_t ARR
Definition: stm32f4xx.h:885
uint32_t bsp_button_get(uint32_t nr)
Get a button.
Definition: bsp_armebs4.c:340