Only call strtoul when there is an argument that strtoul can work on
[fw/stlink] / example / 32l_lcd / main.c
1 /* this example is only for stm32l discover.
2    adapted from ST firmwares projects.
3  */
4
5 /* base headers */
6 #include "stdint.h"
7
8 /* libstm32l_discovery headers */
9 #include "stm32l1xx_gpio.h"
10 #include "stm32l1xx_adc.h"
11 #include "stm32l1xx_lcd.h"
12 #include "stm32l1xx_rcc.h"
13 #include "stm32l1xx_rtc.h"
14 #include "stm32l1xx_exti.h"
15 #include "stm32l1xx_pwr.h"
16 #include "stm32l1xx_syscfg.h"
17 #include "stm32l1xx_dbgmcu.h"
18
19 /* lcd wrapper routines header */
20 #include "stm32l_discovery_lcd.h"
21
22 /* boot mode */
23
24 #define CONFIG_BOOT_SRAM 1
25 #define CONFIG_BOOT_FLASH 0
26
27
28 /* gpios
29    refer to CD00277537.pdf, APB memory space.
30    refer to CD00240193.pdf, GPIO.
31 */
32
33 #define GPIOA_MODER (GPIOA_BASE + 0x00)
34 #define GPIOA_ODR (GPIOA_BASE + 0x14)
35
36 #define GPIOB_MODER (GPIOB_BASE + 0x00)
37 #define GPIOB_ODR (GPIOB_BASE + 0x14)
38
39 #define GPIOC_MODER (GPIOC_BASE + 0x00)
40 #define GPIOC_ODR (GPIOC_BASE + 0x14)
41
42
43 /* leds */
44
45 #define LED_BLUE (1 << 6) /* port B, pin 6 */
46 #define LED_GREEN (1 << 7) /* port B, pin 7 */
47
48 static inline void setup_leds(void)
49 {
50   /* configure port 6 and 7 as output */
51   *(volatile uint32_t*)GPIOB_MODER |= (1 << (7 * 2)) | (1 << (6 * 2));
52 }
53
54 static inline void switch_leds_on(void)
55 {
56   *(volatile uint32_t*)GPIOB_ODR = LED_BLUE | LED_GREEN;
57 }
58
59 static inline void switch_leds_off(void)
60 {
61   *(volatile uint32_t*)GPIOB_ODR = 0;
62 }
63
64
65 #define delay()                                         \
66 do {                                                    \
67   register unsigned int i;                              \
68   for (i = 0; i < 1000000; ++i)                         \
69     __asm__ __volatile__ ("nop\n\t":::"memory");        \
70 } while (0)
71
72
73 #if CONFIG_BOOT_SRAM
74
75 extern uint32_t _fstack;
76
77 static inline void setup_stack(void)
78 {
79   /* setup the stack to point to _fstack (refer to ld script) */
80
81   static const uint32_t fstack = (uint32_t)&_fstack;
82
83   __asm__ __volatile__
84     (
85      "ldr sp, %0\n\t"
86      : 
87      : "m"(fstack)
88      : "sp"
89     );
90 }
91
92 #endif /* CONFIG_BOOT_SRAM */
93
94
95 /* application related setup */
96
97 static void RCC_Configuration(void)
98 {  
99   /* Enable HSI Clock */
100   RCC_HSICmd(ENABLE);
101   
102   /*!< Wait till HSI is ready */
103   while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
104
105   /* Set HSI as sys clock*/
106   RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
107   
108   /* Set MSI clock range to ~4.194MHz*/
109   RCC_MSIRangeConfig(RCC_MSIRange_6);
110   
111   /* Enable the GPIOs clocks */
112   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC| RCC_AHBPeriph_GPIOD| RCC_AHBPeriph_GPIOE| RCC_AHBPeriph_GPIOH, ENABLE);     
113
114   /* Enable comparator, LCD and PWR mngt clocks */
115   RCC_APB1PeriphClockCmd(RCC_APB1Periph_COMP | RCC_APB1Periph_LCD | RCC_APB1Periph_PWR,ENABLE);
116     
117   /* Enable ADC & SYSCFG clocks */
118   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_SYSCFG , ENABLE);
119
120   /* Allow access to the RTC */
121   PWR_RTCAccessCmd(ENABLE);
122
123   /* Reset RTC Backup Domain */
124   RCC_RTCResetCmd(ENABLE);
125   RCC_RTCResetCmd(DISABLE);
126
127   /* LSE Enable */
128   RCC_LSEConfig(RCC_LSE_ON);
129
130   /* Wait until LSE is ready */
131   while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
132   
133    /* RTC Clock Source Selection */ 
134   RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); 
135   
136   /* Enable the RTC */
137   RCC_RTCCLKCmd(ENABLE);   
138   
139   /*Disable HSE*/
140   RCC_HSEConfig(RCC_HSE_OFF);
141   if(RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET )
142   {
143     /* Stay in infinite loop if HSE is not disabled*/
144     while(1); 
145   }
146 }
147
148 static void Init_GPIOs(void)
149 {
150 #if 0 /* fixme: GPIO_Init raises a bug in some gcc toolchains */
151
152   /* GPIO, EXTI and NVIC Init structure declaration */
153   GPIO_InitTypeDef GPIO_InitStructure;
154
155 #if 0
156   EXTI_InitTypeDef EXTI_InitStructure;
157   NVIC_InitTypeDef NVIC_InitStructure;
158 #endif
159
160 #if 0
161   /* Configure User Button pin as input */
162   GPIO_InitStructure.GPIO_Pin = USERBUTTON_GPIO_PIN;
163   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
164   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
165   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
166   GPIO_Init(USERBUTTON_GPIO_PORT, &GPIO_InitStructure);
167 #endif
168
169 #if 0
170   /* Select User Button pin as input source for EXTI Line */
171   SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
172
173   /* Configure EXT1 Line 0 in interrupt mode trigged on Rising edge */
174   EXTI_InitStructure.EXTI_Line = EXTI_Line0 ;  // PA0 for User button AND IDD_WakeUP
175   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
176   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
177   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
178   EXTI_Init(&EXTI_InitStructure);
179
180   /* Enable and set EXTI0 Interrupt to the lowest priority */
181   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ;
182   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
183   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
184   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
185   NVIC_Init(&NVIC_InitStructure); 
186 #endif
187
188 #if 0
189   /* Configure the LED_pin as output push-pull for LD3 & LD4 usage*/
190   GPIO_InitStructure.GPIO_Pin = LD_GREEN_GPIO_PIN | LD_BLUE_GPIO_PIN;
191   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
192   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
193   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
194   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
195   GPIO_Init(LD_GPIO_PORT, &GPIO_InitStructure);
196   
197   /* Force a low level on LEDs*/ 
198   GPIO_LOW(LD_GPIO_PORT,LD_GREEN_GPIO_PIN);     
199   GPIO_LOW(LD_GPIO_PORT,LD_BLUE_GPIO_PIN);
200     
201   /* Counter enable: GPIO set in output for enable the counter */
202   GPIO_InitStructure.GPIO_Pin = CTN_CNTEN_GPIO_PIN;
203   GPIO_Init( CTN_GPIO_PORT, &GPIO_InitStructure);
204   
205   /* To prepare to start counter */
206   GPIO_HIGH(CTN_GPIO_PORT,CTN_CNTEN_GPIO_PIN);
207       
208   /* Configure Port A LCD Output pins as alternate function */
209   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9 |GPIO_Pin_10 |GPIO_Pin_15;
210   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
211   GPIO_Init( GPIOA, &GPIO_InitStructure);
212   
213   /* Select LCD alternate function for Port A LCD Output pins */
214   GPIO_PinAFConfig(GPIOA, GPIO_PinSource1,GPIO_AF_LCD) ;
215   GPIO_PinAFConfig(GPIOA, GPIO_PinSource2,GPIO_AF_LCD) ;
216   GPIO_PinAFConfig(GPIOA, GPIO_PinSource3,GPIO_AF_LCD) ;
217   GPIO_PinAFConfig(GPIOA, GPIO_PinSource8,GPIO_AF_LCD) ;
218   GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_LCD) ;
219   GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_LCD) ;
220   GPIO_PinAFConfig(GPIOA, GPIO_PinSource15,GPIO_AF_LCD) ;  
221   
222   /* Configure Port B LCD Output pins as alternate function */ 
223   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 \
224                                  | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;  
225   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
226   GPIO_Init( GPIOB, &GPIO_InitStructure);
227   
228   /* Select LCD alternate function for Port B LCD Output pins */
229   GPIO_PinAFConfig(GPIOB, GPIO_PinSource3,GPIO_AF_LCD) ;
230   GPIO_PinAFConfig(GPIOB, GPIO_PinSource4,GPIO_AF_LCD) ;
231   GPIO_PinAFConfig(GPIOB, GPIO_PinSource5,GPIO_AF_LCD) ;
232   GPIO_PinAFConfig(GPIOB, GPIO_PinSource8,GPIO_AF_LCD) ;
233   GPIO_PinAFConfig(GPIOB, GPIO_PinSource9,GPIO_AF_LCD) ;
234   GPIO_PinAFConfig(GPIOB, GPIO_PinSource10,GPIO_AF_LCD) ;
235   GPIO_PinAFConfig(GPIOB, GPIO_PinSource11,GPIO_AF_LCD) ;  
236   GPIO_PinAFConfig(GPIOB, GPIO_PinSource12,GPIO_AF_LCD) ;
237   GPIO_PinAFConfig(GPIOB, GPIO_PinSource13,GPIO_AF_LCD) ;   
238   GPIO_PinAFConfig(GPIOB, GPIO_PinSource14,GPIO_AF_LCD) ;
239   GPIO_PinAFConfig(GPIOB, GPIO_PinSource15,GPIO_AF_LCD) ;   
240 #endif
241
242 #if 0  
243   /* Configure Port C LCD Output pins as alternate function */ 
244   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 \
245                                  | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |GPIO_Pin_11 ;                               
246   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
247   GPIO_Init( GPIOC, &GPIO_InitStructure);  
248
249   /* Select LCD alternate function for Port B LCD Output pins */
250   GPIO_PinAFConfig(GPIOC, GPIO_PinSource0,GPIO_AF_LCD) ;
251   GPIO_PinAFConfig(GPIOC, GPIO_PinSource1,GPIO_AF_LCD) ; 
252   GPIO_PinAFConfig(GPIOC, GPIO_PinSource2,GPIO_AF_LCD) ;
253   GPIO_PinAFConfig(GPIOC, GPIO_PinSource3,GPIO_AF_LCD) ;
254   GPIO_PinAFConfig(GPIOC, GPIO_PinSource6,GPIO_AF_LCD) ;
255   GPIO_PinAFConfig(GPIOC, GPIO_PinSource7,GPIO_AF_LCD) ;
256   GPIO_PinAFConfig(GPIOC, GPIO_PinSource8,GPIO_AF_LCD) ;
257   GPIO_PinAFConfig(GPIOC, GPIO_PinSource9,GPIO_AF_LCD) ;
258   GPIO_PinAFConfig(GPIOC, GPIO_PinSource10,GPIO_AF_LCD) ; 
259   GPIO_PinAFConfig(GPIOC, GPIO_PinSource11,GPIO_AF_LCD) ;  
260 #endif
261   
262 #if 0
263   /* Configure ADC (IDD_MEASURE) pin as Analogue */
264   GPIO_InitStructure.GPIO_Pin = IDD_MEASURE  ;
265   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
266   GPIO_Init( IDD_MEASURE_PORT, &GPIO_InitStructure);
267 #endif
268
269 #else /* fixme */
270
271   /* set every port in digital output mode  */
272
273   /* PA[1:3,8:10,15] */
274   *(volatile uint32_t*)GPIOA_MODER |=
275     (GPIO_Mode_AF << (1 * 2)) |
276     (GPIO_Mode_AF << (2 * 2)) |
277     (GPIO_Mode_AF << (3 * 2)) |
278     (GPIO_Mode_AF << (8 * 2)) |
279     (GPIO_Mode_AF << (9 * 2)) |
280     (GPIO_Mode_AF << (10 * 2)) |
281     (GPIO_Mode_AF << (15 * 2));
282
283   /* PB[3:5,8:15] */
284   *(volatile uint32_t*)GPIOB_MODER |=
285     (GPIO_Mode_AF << (3 * 2)) |
286     (GPIO_Mode_AF << (4 * 2)) |
287     (GPIO_Mode_AF << (5 * 2)) |
288     (GPIO_Mode_AF << (8 * 2)) |
289     (GPIO_Mode_AF << (9 * 2)) |
290     (GPIO_Mode_AF << (10 * 2)) |
291     (GPIO_Mode_AF << (11 * 2)) |
292     (GPIO_Mode_AF << (12 * 2)) |
293     (GPIO_Mode_AF << (13 * 2)) |
294     (GPIO_Mode_AF << (14 * 2)) |
295     (GPIO_Mode_AF << (15 * 2));
296
297   /* PC[0:3,6:11] */
298   *(volatile uint32_t*)GPIOC_MODER |=
299     (GPIO_Mode_AF << (0 * 2)) |
300     (GPIO_Mode_AF << (1 * 2)) |
301     (GPIO_Mode_AF << (2 * 2)) |
302     (GPIO_Mode_AF << (3 * 2)) |
303     (GPIO_Mode_AF << (6 * 2)) |
304     (GPIO_Mode_AF << (7 * 2)) |
305     (GPIO_Mode_AF << (8 * 2)) |
306     (GPIO_Mode_AF << (9 * 2)) |
307     (GPIO_Mode_AF << (10 * 2)) |
308     (GPIO_Mode_AF << (11 * 2));
309
310 #endif /* fixme */
311 }
312
313
314 /* main */
315
316 static void __attribute__((naked)) __attribute__((used)) main(void)
317 {
318 #if CONFIG_BOOT_SRAM
319   /* do not use previsouly setup stack, if any */
320   setup_stack();
321 #endif /* CONFIG_BOOT_SRAM */
322
323   RCC_Configuration();
324
325   Init_GPIOs();
326
327   LCD_GLASS_Init();
328
329   setup_leds();
330
331   while (1)
332   {
333     /* switch_leds_on(); */
334     GPIO_HIGH(LD_GPIO_PORT, LD_GREEN_GPIO_PIN); 
335     GPIO_HIGH(LD_GPIO_PORT, LD_BLUE_GPIO_PIN);
336
337     LCD_GLASS_Clear();
338     LCD_GLASS_DisplayString("ON   ");
339
340     delay();
341
342     /* switch_leds_off(); */
343     GPIO_LOW(LD_GPIO_PORT, LD_GREEN_GPIO_PIN);  
344     GPIO_LOW(LD_GPIO_PORT, LD_BLUE_GPIO_PIN);   
345
346     LCD_GLASS_Clear();
347     LCD_GLASS_DisplayString("  OFF");
348
349     delay();
350   }
351 }