Skip to content

Instantly share code, notes, and snippets.

@monpetit
Last active July 6, 2016 06:04
Show Gist options
  • Save monpetit/7f38cedb9d757dbfb7169b47f96ac85f to your computer and use it in GitHub Desktop.
Save monpetit/7f38cedb9d757dbfb7169b47f96ac85f to your computer and use it in GitHub Desktop.
#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"
#include "em_int.h"
#include "em_timer.h"
#define LED_PIN (0)
#define LED_PORT (gpioPortA)
#define USART0_CS_PIN (13)
#define USART0_CS_PORT (gpioPortE)
#define LED_OFF() GPIO_PinOutSet(LED_PORT, LED_PIN)
#define LED_ON() GPIO_PinOutClear(LED_PORT, LED_PIN)
#define LED_TOGGLE() GPIO_PinOutToggle(LED_PORT, LED_PIN)
#define CS_HIGH() GPIO_PinOutSet(USART0_CS_PORT, USART0_CS_PIN)
#define CS_LOW() GPIO_PinOutClear(USART0_CS_PORT, USART0_CS_PIN)
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_timer0(void);
void init_usart0(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)
volatile uint8_t timer0_ready = 0;
__STATIC_INLINE uint8_t bcd2bin(uint8_t value)
{
return ((value / 0x10) * 10 + value % 0x10);
}
__STATIC_INLINE uint8_t bin2bcd(uint8_t value)
{
return (value / 10 * 0x10 + value % 10);
}
void set_datetime(uint16_t y, uint8_t mo, uint8_t d, uint8_t h, uint8_t mi, uint8_t s)
{
uint8_t buf[8];
buf[0] = 0x80;
buf[1] = bin2bcd(s);
buf[2] = bin2bcd(mi);
buf[3] = bin2bcd(h & 0x3f);
buf[5] = bin2bcd(d);
buf[6] = bin2bcd(mo & 0x1f);
buf[7] = bin2bcd((y - 2000) & 0xff);
CS_LOW();
for (int i = 0; i < 8; i++)
USART_SpiTransfer(USART0, buf[i]);
CS_HIGH();
}
void get_datetime(void)
{
uint8_t buf[7];
CS_LOW();
USART_SpiTransfer(USART0, 0x00);
for (int i = 0; i < 7; i++)
buf[i] = USART_SpiTransfer(USART0, 0x00);
CS_HIGH();
printf("%04d-%02d-%02d %02d:%02d:%02d\r\n",
bcd2bin(buf[6] & 0xff) + 2000,
bcd2bin(buf[5] & 0x1f),
bcd2bin(buf[4]),
bcd2bin(buf[2] & 0x3f),
bcd2bin(buf[1]),
bcd2bin(buf[0]));
}
/**************************************************************************//**
* @brief Main function
*****************************************************************************/
int main(void)
{
/* Chip errata */
CHIP_Init();
/* Enter default mode */
init_clocks();
init_usart0();
init_usart1();
init_portio();
/* Ensure core frequency has been updated */
SystemCoreClockUpdate();
/* Start Systick Timer */
setup_systick_timer();
/* Setup TIMER0 */
init_timer0();
// set_datetime(2016, 7, 6, 12, 54, 30);
reset_blink(30);
__delay_ms(3000);
printf("\r\n**********************************\r\n");
printf("*** EFM32 GECKO FIRMWARE START ***\r\n");
printf("**********************************\r\n\r\n");
/* Infinite loop */
while (1) {
if (timer0_ready) {
timer0_ready = 0;
get_datetime();
// printf("system tick = %u\r\n", get_systick());
LED_ON();
__delay_ms(20);;
LED_OFF();
}
EMU_EnterEM1(); // CPU OFF
}
}
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--) {
LED_TOGGLE();
__delay_ms(20);
}
LED_OFF();
}
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 TIMER0 */
CMU_ClockEnable(cmuClock_TIMER0, true);
/* Enable clock for USART0 */
CMU_ClockEnable(cmuClock_USART0, true);
/* Enable clock for USART1 */
CMU_ClockEnable(cmuClock_USART1, true);
/* Enable clock for GPIO by default */
CMU_ClockEnable(cmuClock_GPIO, true);
// [Peripheral Clock enables]$
}
/* SPI */
void init_usart0(void)
{
// $[USART_InitSync]
USART_InitSync_TypeDef initsync = USART_INITSYNC_DEFAULT;
initsync.baudrate = 1000000;
initsync.databits = usartDatabits8;
initsync.master = 1;
initsync.msbf = 1;
initsync.clockMode = usartClockMode3;
#if defined( USART_INPUT_RXPRS ) && defined( USART_TRIGCTRL_AUTOTXTEN )
initsync.prsRxEnable = 0;
initsync.prsRxCh = 0;
initsync.autoTx = 0;
#endif
USART_InitSync(USART0, &initsync);
// [USART_InitSync]$
}
/* UART */
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]$
}
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]$
// $[Port E Configuration]
/* Pin PE10 is configured to Push-pull */
GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE10_MASK)
| GPIO_P_MODEH_MODE10_PUSHPULL;
/* Pin PE11 is configured to Input enabled */
GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE11_MASK)
| GPIO_P_MODEH_MODE11_INPUT;
/* Pin PE12 is configured to Push-pull */
GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE12_MASK)
| GPIO_P_MODEH_MODE12_PUSHPULL;
/* Pin PE13 is configured to Push-pull */
GPIO->P[4].DOUT |= (1 << 13);
GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE13_MASK)
| GPIO_P_MODEH_MODE13_PUSHPULL;
// [Port E Configuration]$
// $[Route Configuration]
/* Enable signals CLK, RX, TX */
USART0->ROUTE |= USART_ROUTE_CLKPEN | USART_ROUTE_RXPEN | USART_ROUTE_TXPEN;
/* Enable signals RX, TX */
USART1->ROUTE |= USART_ROUTE_RXPEN | USART_ROUTE_TXPEN;
// [Route Configuration]$
}
void init_timer0(void)
{
// $[TIMER0 initialization]
TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT;
init.enable = 1;
init.debugRun = 0;
init.dmaClrAct = 0;
init.sync = 0;
init.clkSel = timerClkSelHFPerClk;
init.prescale = timerPrescale1024;
init.fallAction = timerInputActionNone;
init.riseAction = timerInputActionNone;
init.mode = timerModeUp;
init.quadModeX4 = 0;
init.oneShot = 0;
TIMER_Init(TIMER0, &init);
// Enable TIMER0 overflow interrupt
TIMER_IntEnable(TIMER0, TIMER_IEN_OF);
TIMER_TopSet(TIMER0, (CMU_ClockFreqGet(cmuClock_CORE) / 1024) - 1);
NVIC_SetPriority(TIMER0_IRQn, 3);
NVIC_EnableIRQ(TIMER0_IRQn);
}
__STATIC_INLINE void uart1_putstr(uint8_t* buffer, size_t length)
{
while (length--) {
putch(*buffer++);
}
}
void TIMER0_IRQHandler(void)
{
TIMER_IntClear(TIMER0, TIMER_IF_OF);
timer0_ready = 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment