Last active
June 22, 2016 06:02
-
-
Save monpetit/0e729d5e76edb580f9be791d9d02134e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <string.h> | |
| #include <inttypes.h> | |
| #include "em_device.h" | |
| #include "em_chip.h" | |
| #include "em_usart.h" | |
| #include "em_cmu.h" | |
| #include "em_emu.h" | |
| static uint32_t system_count = 0; | |
| volatile uint32_t systick_count = 0; | |
| uint32_t clock_freq; | |
| __STATIC_INLINE void __delay_tick(volatile uint32_t n); | |
| __STATIC_INLINE uint32_t get_systick(void); | |
| void __delay_ms(uint32_t milliseconds); | |
| void setup_systick_timer(void); | |
| void reset_blink(volatile uint8_t countdown); | |
| void init_clocks(void); | |
| void init_usart1(void); | |
| void init_portio(void); | |
| __STATIC_INLINE void uart1_putstr(uint8_t* buffer, size_t length); | |
| char txbuffer[128]; | |
| #define printf(...) do { \ | |
| sprintf(txbuffer, __VA_ARGS__); \ | |
| uart1_putstr((uint8_t*)txbuffer, strlen(txbuffer)); \ | |
| } while (0) | |
| #define putch(CH) USART_Tx(USART1, CH) | |
| /**************************************************************************//** | |
| * @brief Main function | |
| *****************************************************************************/ | |
| int main(void) | |
| { | |
| /* Chip errata */ | |
| CHIP_Init(); | |
| /* Enter default mode: prepare all... */ | |
| init_clocks(); | |
| init_usart1(); | |
| init_portio(); | |
| /* Ensure core frequency has been updated */ | |
| SystemCoreClockUpdate(); | |
| /* Start Systick Timer */ | |
| setup_systick_timer(); | |
| reset_blink(30); | |
| printf("** EFM32 GECKO FIRMWARE START **\r\n"); | |
| __delay_ms(1000); | |
| /* Infinite loop */ | |
| while (1) { | |
| GPIO_PinOutClear(gpioPortA, 0); | |
| __delay_ms(10); | |
| GPIO_PinOutSet(gpioPortA, 0); | |
| printf("count = %u\r\n", system_count++); | |
| __delay_ms(1000 - (get_systick() % 1000)); | |
| } | |
| } | |
| void SysTick_Handler(void) | |
| { | |
| systick_count++; | |
| } | |
| __STATIC_INLINE uint32_t get_systick(void) | |
| { | |
| return systick_count; | |
| } | |
| /****************************************************************************** | |
| * @brief Delay function | |
| *****************************************************************************/ | |
| void __delay_ms(uint32_t milliseconds) | |
| { | |
| uint32_t start_tick = get_systick(); | |
| while ((get_systick() - start_tick) < milliseconds) { | |
| } | |
| } | |
| void setup_systick_timer(void) | |
| { | |
| clock_freq = CMU_ClockFreqGet(cmuClock_CORE); | |
| /* Enable SysTick interrupt, necessary for __delay_ms() */ | |
| if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ; | |
| NVIC_EnableIRQ(SysTick_IRQn); | |
| } | |
| void reset_blink(volatile uint8_t countdown) | |
| { | |
| while (countdown--) { | |
| GPIO_PinOutToggle(gpioPortA, 0); | |
| __delay_ms(20); | |
| } | |
| } | |
| void init_clocks(void) | |
| { | |
| // $[HFXO] | |
| CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOMODE_MASK) | CMU_CTRL_HFXOMODE_XTAL; | |
| CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBOOST_MASK) | |
| | CMU_CTRL_HFXOBOOST_50PCENT; | |
| SystemHFXOClockSet(32000000); | |
| // $[Use oscillator source] | |
| CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOMODE_MASK) | CMU_CTRL_LFXOMODE_XTAL; | |
| // [Use oscillator source]$ | |
| // $[LFXO Boost Percent] | |
| CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOBOOST_MASK) | |
| | CMU_CTRL_LFXOBOOST_100PCENT; | |
| // [LFXO Boost Percent]$ | |
| // $[LFXO enable] | |
| CMU_OscillatorEnable(cmuOsc_LFXO, true, true); | |
| // [LFXO enable]$ | |
| // $[HFXO enable] | |
| CMU_OscillatorEnable(cmuOsc_HFXO, true, true); | |
| // [HFXO enable]$ | |
| // $[High Frequency Clock select] | |
| /* Using HFXO as high frequency clock, HFCLK */ | |
| CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); | |
| /* Enable peripheral clock */ | |
| CMU_ClockEnable(cmuClock_HFPER, true); | |
| // [High Frequency Clock select]$ | |
| // $[Peripheral Clock enables] | |
| /* Enable clock for USART1 */ | |
| CMU_ClockEnable(cmuClock_USART1, true); | |
| /* Enable clock for GPIO by default */ | |
| CMU_ClockEnable(cmuClock_GPIO, true); | |
| // [Peripheral Clock enables]$ | |
| } | |
| void init_usart1(void) | |
| { | |
| // $[USART_InitAsync] | |
| USART_InitAsync_TypeDef initasync = USART_INITASYNC_DEFAULT; | |
| initasync.baudrate = 115200; | |
| initasync.databits = usartDatabits8; | |
| initasync.parity = usartNoParity; | |
| initasync.stopbits = usartStopbits1; | |
| initasync.oversampling = usartOVS16; | |
| #if defined( USART_INPUT_RXPRS ) && defined( USART_CTRL_MVDIS ) | |
| initasync.mvdis = 0; | |
| initasync.prsRxEnable = 0; | |
| initasync.prsRxCh = 0; | |
| #endif | |
| USART_InitAsync(USART1, &initasync); | |
| // [USART_InitAsync]$ | |
| // $[USART_InitPrsTrigger] | |
| USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT; | |
| initprs.rxTriggerEnable = 0; | |
| initprs.txTriggerEnable = 0; | |
| initprs.prsTriggerChannel = usartPrsTriggerCh0; | |
| USART_InitPrsTrigger(USART1, &initprs); | |
| // [USART_InitPrsTrigger]$ | |
| /* Prepare UART Rx interrupt */ | |
| USART_IntClear(USART1, _USART_IF_MASK); | |
| USART_IntEnable(USART1, USART_IF_RXDATAV); | |
| NVIC_ClearPendingIRQ(USART1_RX_IRQn); | |
| NVIC_EnableIRQ(USART1_RX_IRQn); | |
| } | |
| void init_portio(void) | |
| { | |
| // $[Port A Configuration] | |
| /* Pin PA0 is configured to Push-pull */ | |
| GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | |
| | GPIO_P_MODEL_MODE0_PUSHPULL; | |
| /* Pin PA1 is configured to Input enabled with pull-up */ | |
| GPIO->P[0].DOUT |= (1 << 1); | |
| GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE1_MASK) | |
| | GPIO_P_MODEL_MODE1_INPUTPULL; | |
| // [Port A Configuration]$ | |
| // $[Port C Configuration] | |
| /* Pin PC0 is configured to Push-pull */ | |
| GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | |
| | GPIO_P_MODEL_MODE0_PUSHPULL; | |
| /* Pin PC1 is configured to Input enabled */ | |
| GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE1_MASK) | |
| | GPIO_P_MODEL_MODE1_INPUT; | |
| // [Port C Configuration]$ | |
| // $[Route Configuration] | |
| /* Enable signals RX, TX */ | |
| USART1->ROUTE |= USART_ROUTE_RXPEN | USART_ROUTE_TXPEN; | |
| // [Route Configuration]$ | |
| } | |
| __STATIC_INLINE void uart1_putstr(uint8_t* buffer, size_t length) | |
| { | |
| while (length--) { | |
| putch(*buffer++); | |
| } | |
| } | |
| /**************************************************************************//** | |
| * @brief UART1 RX IRQ Handler | |
| * | |
| * Set up the interrupt prior to use | |
| * | |
| * Note that this function handles overflows in a very simple way. | |
| * | |
| *****************************************************************************/ | |
| void USART1_RX_IRQHandler(void) | |
| { | |
| /* Check for RX data valid interrupt */ | |
| if (USART1->STATUS & USART_STATUS_RXDATAV) { | |
| /* Clear RXDATAV interrupt */ | |
| USART_IntClear(USART1, USART_IF_RXDATAV); | |
| /* Echo back RX data */ | |
| USART_Tx(USART1, USART_Rx(USART1)); | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment