1 /** 2 * \file 3 * 4 * \brief Getting Started Application. 5 * 6 * Copyright (c) 2011-2016 Atmel Corporation. All rights reserved. 7 * 8 * \asf_license_start 9 * 10 * \page License 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright notice, 16 * this list of conditions and the following disclaimer. 17 * 18 * 2. Redistributions in binary form must reproduce the above copyright notice, 19 * this list of conditions and the following disclaimer in the documentation 20 * and/or other materials provided with the distribution. 21 * 22 * 3. The name of Atmel may not be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * 4. This software may only be redistributed and used in connection with an 26 * Atmel microcontroller product. 27 * 28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED 29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR 32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 * 40 * \asf_license_stop 41 * 42 */ 43 44 /** 45 * \mainpage Getting Started Application 46 * 47 * \section Purpose 48 * 49 * The Getting Started example will help new users get familiar with Atmel's 50 * SAM family of microcontrollers. This basic application shows the startup 51 * sequence of a chip and how to use its core peripherals. 52 * 53 * \section Requirements 54 * 55 * This package can be used with SAM evaluation kits. 56 * 57 * \section Description 58 * 59 * The demonstration program makes the LED(s) on the board blink at a fixed rate. 60 * This rate is generated by using Time tick timer. The blinking can be stopped 61 * using the push button. 62 * 63 * \section Usage 64 * 65 * -# Build the program and download it inside the evaluation board. 66 * -# On the computer, open and configure a terminal application 67 * (e.g. HyperTerminal on Microsoft Windows) with these settings: 68 * - 115200 bauds 69 * - 8 bits of data 70 * - No parity 71 * - 1 stop bit 72 * - No flow control 73 * -# Start the application. 74 * -# The LED(s) should start blinking on the board. In the terminal window, the 75 * following text should appear (values depend on the board and chip used): 76 * \code 77 -- Getting Started Example xxx -- 78 -- xxxxxx-xx 79 -- Compiled: xxx xx xxxx xx:xx:xx -- 80 \endcode 81 * -# Pressing and release button 1 should make one LED stop & restart 82 * blinking. 83 * -# If the button 2 available, pressing button 2 should make the other LED 84 * stop & restart blinking. 85 * 86 */ 87 /* 88 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> 89 */ 90 91 #include "asf.h" 92 #include "stdio_serial.h" 93 #include "conf_board.h" 94 #include "conf_clock.h" 95 96 /** IRQ priority for PIO (The lower the value, the greater the priority) */ 97 // [main_def_pio_irq_prior] 98 #define IRQ_PRIOR_PIO 0 99 // [main_def_pio_irq_prior] 100 101 /** LED0 blink time, LED1 blink half this time, in ms */ 102 #define BLINK_PERIOD 1000 103 104 #define STRING_EOL "\r" 105 #define STRING_HEADER "-- Getting Started Example --\r\n" \ 106 "-- "BOARD_NAME" --\r\n" \ 107 "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL 108 109 /** LED0 blinking control. */ 110 // [main_var_led0_control] 111 volatile bool g_b_led0_active = true; 112 // [main_var_led0_control] 113 114 #ifdef LED1_GPIO 115 /** LED1 blinking control. */ 116 // [main_var_led1_control] 117 volatile bool g_b_led1_active = true; 118 // [main_var_led1_control] 119 #endif 120 121 /** Global g_ul_ms_ticks in milliseconds since start of application */ 122 // [main_var_ticks] 123 volatile uint32_t g_ul_ms_ticks = 0; 124 // [main_var_ticks] 125 126 /// @cond 0 127 /**INDENT-OFF**/ 128 #ifdef __cplusplus 129 extern "C" { 130 #endif 131 /**INDENT-ON**/ 132 /// @endcond 133 134 /** 135 * \brief Process Buttons Events 136 * 137 * Change active states of LEDs when corresponding button events happened. 138 */ 139 static void ProcessButtonEvt(uint8_t uc_button) 140 { 141 // [main_button1_evnt_process] 142 if (uc_button == 0) { 143 g_b_led0_active = !g_b_led0_active; 144 if (!g_b_led0_active) { 145 ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_HIGH); 146 } 147 } 148 // [main_button1_evnt_process] 149 #ifdef LED1_GPIO 150 else { 151 // [main_button2_evnt_process] 152 g_b_led1_active = !g_b_led1_active; 153 154 /* Enable LED#2 and TC if they were enabled */ 155 if (g_b_led1_active) { 156 ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_LOW); 157 tc_start(TC0, 0); 158 } 159 /* Disable LED#2 and TC if they were disabled */ 160 else { 161 ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_HIGH); 162 tc_stop(TC0, 0); 163 } 164 // [main_button2_evnt_process] 165 } 166 #endif 167 } 168 169 /** 170 * \brief Handler for System Tick interrupt. 171 * 172 * Process System Tick Event 173 * Increments the g_ul_ms_ticks counter. 174 */ 175 // [main_systick_handler] 176 void SysTick_Handler(void) 177 { 178 g_ul_ms_ticks++; 179 } 180 // [main_systick_handler] 181 182 /** 183 * \brief Handler for Button 1 rising edge interrupt. 184 * 185 * Handle process led1 status change. 186 */ 187 // [main_button1_handler] 188 static void Button1_Handler(uint32_t id, uint32_t mask) 189 { 190 if (PIN_PUSHBUTTON_1_ID == id && PIN_PUSHBUTTON_1_MASK == mask) { 191 ProcessButtonEvt(0); 192 } 193 } 194 // [main_button1_handler] 195 196 #ifndef BOARD_NO_PUSHBUTTON_2 197 /** 198 * \brief Handler for Button 2 falling edge interrupt. 199 * 200 * Handle process led2 status change. 201 */ 202 // [main_button2_handler] 203 static void Button2_Handler(uint32_t id, uint32_t mask) 204 { 205 if (PIN_PUSHBUTTON_2_ID == id && PIN_PUSHBUTTON_2_MASK == mask) { 206 ProcessButtonEvt(1); 207 } 208 } 209 // [main_button2_handler] 210 #endif 211 212 /** 213 * \brief Configure the Pushbuttons 214 * 215 * Configure the PIO as inputs and generate corresponding interrupt when 216 * pressed or released. 217 */ 218 static void configure_buttons(void) 219 { 220 // [main_button1_configure] 221 /* Configure Pushbutton 1 */ 222 pmc_enable_periph_clk(PIN_PUSHBUTTON_1_ID); 223 pio_set_debounce_filter(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK, 10); 224 /* Interrupt on rising edge */ 225 pio_handler_set(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_ID, 226 PIN_PUSHBUTTON_1_MASK, PIN_PUSHBUTTON_1_ATTR, Button1_Handler); 227 NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_1_ID); 228 pio_handler_set_priority(PIN_PUSHBUTTON_1_PIO, 229 (IRQn_Type) PIN_PUSHBUTTON_1_ID, IRQ_PRIOR_PIO); 230 pio_enable_interrupt(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK); 231 // [main_button1_configure] 232 #ifndef BOARD_NO_PUSHBUTTON_2 233 // [main_button2_configure] 234 /* Configure Pushbutton 2 */ 235 pmc_enable_periph_clk(PIN_PUSHBUTTON_2_ID); 236 pio_set_debounce_filter(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK, 10); 237 /* Interrupt on falling edge */ 238 pio_handler_set(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_ID, 239 PIN_PUSHBUTTON_2_MASK, PIN_PUSHBUTTON_2_ATTR, Button2_Handler); 240 NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_2_ID); 241 pio_handler_set_priority(PIN_PUSHBUTTON_2_PIO, 242 (IRQn_Type) PIN_PUSHBUTTON_2_ID, IRQ_PRIOR_PIO); 243 pio_enable_interrupt(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK); 244 // [main_button2_configure] 245 #endif 246 } 247 248 /** 249 * Interrupt handler for TC0 interrupt. Toggles the state of LED\#2. 250 */ 251 // [main_tc0_handler] 252 #ifndef BOARD_NO_LED_1 253 void TC0_Handler(void) 254 { 255 volatile uint32_t ul_dummy; 256 257 /* Clear status bit to acknowledge interrupt */ 258 ul_dummy = tc_get_status(TC0, 0); 259 260 /* Avoid compiler warning */ 261 UNUSED(ul_dummy); 262 263 #ifdef LED1_GPIO 264 /** Toggle LED state. */ 265 ioport_toggle_pin_level(LED1_GPIO); 266 #endif 267 268 printf("2 "); 269 } 270 // [main_tc0_handler] 271 272 /** 273 * Configure Timer Counter 0 to generate an interrupt every 250ms. 274 */ 275 // [main_tc_configure] 276 static void configure_tc(void) 277 { 278 uint32_t ul_div; 279 uint32_t ul_tcclks; 280 uint32_t ul_sysclk = sysclk_get_cpu_hz(); 281 282 /* Configure PMC */ 283 pmc_enable_periph_clk(ID_TC0); 284 #if SAMG55 285 /* Enable PCK output */ 286 pmc_disable_pck(PMC_PCK_3); 287 pmc_switch_pck_to_sclk(PMC_PCK_3, PMC_PCK_PRES(0)); 288 pmc_enable_pck(PMC_PCK_3); 289 #endif 290 291 /** Configure TC for a 4Hz frequency and trigger on RC compare. */ 292 tc_find_mck_divisor(4, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk); 293 tc_init(TC0, 0, ul_tcclks | TC_CMR_CPCTRG); 294 tc_write_rc(TC0, 0, (ul_sysclk / ul_div) / 4); 295 296 /* Configure and enable interrupt on RC compare */ 297 NVIC_EnableIRQ((IRQn_Type) ID_TC0); 298 tc_enable_interrupt(TC0, 0, TC_IER_CPCS); 299 300 #ifdef LED1_GPIO 301 /** Start the counter if LED1 is enabled. */ 302 if (g_b_led1_active) { 303 tc_start(TC0, 0); 304 } 305 #else 306 tc_start(TC0, 0); 307 #endif 308 } 309 #endif 310 // [main_tc_configure] 311 312 /** 313 * Configure UART console. 314 */ 315 // [main_console_configure] 316 static void configure_console(void) 317 { 318 const usart_serial_options_t uart_serial_options = { 319 .baudrate = CONF_UART_BAUDRATE, 320 #ifdef CONF_UART_CHAR_LENGTH 321 .charlength = CONF_UART_CHAR_LENGTH, 322 #endif 323 .paritytype = CONF_UART_PARITY, 324 #ifdef CONF_UART_STOP_BITS 325 .stopbits = CONF_UART_STOP_BITS, 326 #endif 327 }; 328 329 /* Configure console UART. */ 330 sysclk_enable_peripheral_clock(CONSOLE_UART_ID); 331 stdio_serial_init(CONF_UART, &uart_serial_options); 332 } 333 334 // [main_console_configure] 335 336 /** 337 * \brief Wait for the given number of milliseconds (using the g_ul_ms_ticks 338 * generated by the SAM's microcontrollers's system tick). 339 * 340 * \param ul_dly_ticks Delay to wait for, in milliseconds. 341 */ 342 // [main_ms_delay] 343 static void mdelay(uint32_t ul_dly_ticks) 344 { 345 uint32_t ul_cur_ticks; 346 347 ul_cur_ticks = g_ul_ms_ticks; 348 while ((g_ul_ms_ticks - ul_cur_ticks) < ul_dly_ticks); 349 } 350 // [main_ms_delay] 351 352 /** 353 * \brief getting-started Application entry point. 354 * 355 * \return Unused (ANSI-C compatibility). 356 */ 357 // [main] 358 int main(void) 359 { 360 //! [main_step_sys_init] 361 /* Initialize the SAM system */ 362 sysclk_init(); 363 board_init(); 364 //! [main_step_sys_init] 365 366 #ifndef BOARD_NO_PUSHBUTTON_2 367 #if (SAMV71 || SAMV70 || SAMS70 || SAME70) 368 if (GPIO_PUSH_BUTTON_2 == PIO_PB12_IDX) { 369 matrix_set_system_io(matrix_get_system_io() | CCFG_SYSIO_SYSIO12); 370 } 371 ioport_set_pin_dir(GPIO_PUSH_BUTTON_2, IOPORT_DIR_INPUT); 372 ioport_set_pin_mode(GPIO_PUSH_BUTTON_2, GPIO_PUSH_BUTTON_2_FLAGS); 373 ioport_set_pin_sense_mode(GPIO_PUSH_BUTTON_2, GPIO_PUSH_BUTTON_2_SENSE); 374 #endif 375 #endif 376 //! [main_step_console_init] 377 /* Initialize the console uart */ 378 configure_console(); 379 //! [main_step_console_init] 380 381 /* Output example information */ 382 puts(STRING_HEADER); 383 384 /* Configure systick for 1 ms */ 385 puts("Configure system tick to get 1ms tick period.\r"); 386 //! [main_step_systick_init] 387 if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) { 388 puts("-F- Systick configuration error\r"); 389 while (1); 390 } 391 //! [main_step_systick_init] 392 393 #ifndef BOARD_NO_LED_1 394 puts("Configure TC.\r"); 395 //! [main_step_tc_init] 396 configure_tc(); 397 //! [main_step_tc_init] 398 #endif 399 400 puts("Configure buttons with debouncing.\r"); 401 //! [main_step_btn_init] 402 configure_buttons(); 403 //! [main_step_btn_init] 404 405 printf("Press %s to Start/Stop the %s blinking.\r\n", 406 PUSHBUTTON_1_NAME, LED_0_NAME); 407 408 #ifndef BOARD_NO_PUSHBUTTON_2 409 printf("Press %s to Start/Stop the %s blinking.\r\n", 410 PUSHBUTTON_2_NAME, LED_1_NAME); 411 #endif 412 413 //! [main_step_loop] 414 while (1) { 415 /* Wait for LED to be active */ 416 while (!g_b_led0_active); 417 418 /* Toggle LED state if active */ 419 if (g_b_led0_active) { 420 ioport_toggle_pin_level(LED0_GPIO); 421 printf("1 "); 422 } 423 424 /* Wait for 500ms */ 425 mdelay(300); 426 } 427 //! [main_step_loop] 428 } 429 // [main] 430 /// @cond 0 431 /**INDENT-OFF**/ 432 #ifdef __cplusplus 433 } 434 #endif 435 /**INDENT-ON**/ 436 /// @endcond 437