move to targets dir
This commit is contained in:
752
targets/efm32/src/InitDevice.c
Normal file
752
targets/efm32/src/InitDevice.c
Normal file
@@ -0,0 +1,752 @@
|
||||
//=========================================================
|
||||
// src/InitDevice.c: generated by Hardware Configurator
|
||||
//
|
||||
// This file will be regenerated when saving a document.
|
||||
// leave the sections inside the "$[...]" comment tags alone
|
||||
// or they will be overwritten!
|
||||
//=========================================================
|
||||
|
||||
// USER INCLUDES
|
||||
#include "InitDevice.h"
|
||||
|
||||
// USER PROTOTYPES
|
||||
// USER FUNCTIONS
|
||||
|
||||
// $[Library includes]
|
||||
#include "em_system.h"
|
||||
#include "em_emu.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_device.h"
|
||||
#include "em_chip.h"
|
||||
#include "em_assert.h"
|
||||
#include "em_adc.h"
|
||||
#include "em_cryotimer.h"
|
||||
#include "em_crypto.h"
|
||||
#include "em_gpio.h"
|
||||
#include "em_timer.h"
|
||||
#include "em_usart.h"
|
||||
// [Library includes]$
|
||||
|
||||
//==============================================================================
|
||||
// enter_DefaultMode_from_RESET
|
||||
//==============================================================================
|
||||
extern void enter_DefaultMode_from_RESET(void) {
|
||||
// $[Config Calls]
|
||||
CHIP_Init();
|
||||
|
||||
EMU_enter_DefaultMode_from_RESET();
|
||||
CMU_enter_DefaultMode_from_RESET();
|
||||
ADC0_enter_DefaultMode_from_RESET();
|
||||
USART0_enter_DefaultMode_from_RESET();
|
||||
USART1_enter_DefaultMode_from_RESET();
|
||||
TIMER0_enter_DefaultMode_from_RESET();
|
||||
CRYOTIMER_enter_DefaultMode_from_RESET();
|
||||
PORTIO_enter_DefaultMode_from_RESET();
|
||||
// [Config Calls]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// EMU_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void EMU_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[EMU Initialization]
|
||||
/* External power circuit not wired for DCDC; shut down regulator */
|
||||
EMU_DCDCPowerOff();
|
||||
/* Initialize EM2/EM3 mode */
|
||||
EMU_EM23Init_TypeDef em23Init = EMU_EM23INIT_DEFAULT;
|
||||
|
||||
em23Init.em23VregFullEn = 0;
|
||||
|
||||
EMU_EM23Init(&em23Init);
|
||||
/* Initialize EM4H/S mode */
|
||||
EMU_EM4Init_TypeDef em4Init = EMU_EM4INIT_DEFAULT;
|
||||
|
||||
em4Init.retainLfrco = 0;
|
||||
em4Init.retainLfxo = 0;
|
||||
em4Init.retainUlfrco = 0;
|
||||
em4Init.em4State = emuEM4Shutoff;
|
||||
em4Init.pinRetentionMode = emuPinRetentionDisable;
|
||||
|
||||
EMU_EM4Init(&em4Init);
|
||||
// [EMU Initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LFXO_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LFXO_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// CMU_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void CMU_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[High Frequency Clock Setup]
|
||||
/* Initializing HFXO */
|
||||
CMU_HFXOInit_TypeDef hfxoInit = CMU_HFXOINIT_DEFAULT;
|
||||
|
||||
CMU_HFXOInit(&hfxoInit);
|
||||
|
||||
/* Setting system HFRCO frequency */
|
||||
CMU_HFRCOFreqSet (cmuHFRCOFreq_38M0Hz);
|
||||
|
||||
/* Using HFRCO as high frequency clock, HFCLK */
|
||||
CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO);
|
||||
// [High Frequency Clock Setup]$
|
||||
|
||||
// $[LE clocks enable]
|
||||
/* Enable ULFRCO oscillator, and wait for it to be stable */
|
||||
CMU_OscillatorEnable(cmuOsc_ULFRCO, true, true);
|
||||
|
||||
// [LE clocks enable]$
|
||||
|
||||
// $[LFACLK Setup]
|
||||
/* LFACLK is disabled */
|
||||
// [LFACLK Setup]$
|
||||
// $[LFBCLK Setup]
|
||||
/* LFBCLK is disabled */
|
||||
// [LFBCLK Setup]$
|
||||
// $[LFECLK Setup]
|
||||
/* LFECLK is disabled */
|
||||
// [LFECLK Setup]$
|
||||
// $[Peripheral Clock enables]
|
||||
/* Enable clock for HF peripherals */
|
||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||
|
||||
/* Enable clock for ADC0 */
|
||||
CMU_ClockEnable(cmuClock_ADC0, true);
|
||||
|
||||
/* Enable clock for CRYOTIMER */
|
||||
CMU_ClockEnable(cmuClock_CRYOTIMER, true);
|
||||
|
||||
/* 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]$
|
||||
|
||||
// $[Clock output]
|
||||
/* Disable CLKOUT0 output */
|
||||
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_CLKOUTSEL0_MASK)
|
||||
| CMU_CTRL_CLKOUTSEL0_DISABLED;
|
||||
/* Disable CLKOUT1 output */
|
||||
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_CLKOUTSEL1_MASK)
|
||||
| CMU_CTRL_CLKOUTSEL1_DISABLED;
|
||||
|
||||
// [Clock output]$
|
||||
|
||||
// $[CMU_IO]
|
||||
/* Disable CLKOUT0 pin */
|
||||
CMU->ROUTEPEN &= ~CMU_ROUTEPEN_CLKOUT0PEN;
|
||||
|
||||
/* Disable CLKOUT1 pin */
|
||||
CMU->ROUTEPEN &= ~CMU_ROUTEPEN_CLKOUT1PEN;
|
||||
|
||||
// [CMU_IO]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// ADC0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void ADC0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[ADC0_Init]
|
||||
ADC_Init_TypeDef ADC0_init = ADC_INIT_DEFAULT;
|
||||
|
||||
ADC0_init.ovsRateSel = adcOvsRateSel2;
|
||||
ADC0_init.warmUpMode = adcWarmupNormal;
|
||||
ADC0_init.timebase = ADC_TimebaseCalc(0);
|
||||
ADC0_init.prescale = ADC_PrescaleCalc(7000000, 0);
|
||||
ADC0_init.tailgate = 0;
|
||||
ADC0_init.em2ClockConfig = adcEm2Disabled;
|
||||
|
||||
ADC_Init(ADC0, &ADC0_init);
|
||||
// [ADC0_Init]$
|
||||
|
||||
// $[ADC0_InputConfiguration]
|
||||
// [ADC0_InputConfiguration]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// ACMP0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void ACMP0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[ACMP0_Init]
|
||||
// [ACMP0_Init]$
|
||||
|
||||
// $[ACMP0_IO]
|
||||
// [ACMP0_IO]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// ACMP1_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void ACMP1_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[ACMP1_Init]
|
||||
// [ACMP1_Init]$
|
||||
|
||||
// $[ACMP1_IO]
|
||||
// [ACMP1_IO]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// IDAC0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void IDAC0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// RTCC_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void RTCC_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[Compare/Capture Channel 0 init]
|
||||
// [Compare/Capture Channel 0 init]$
|
||||
|
||||
// $[Compare/Capture Channel 1 init]
|
||||
// [Compare/Capture Channel 1 init]$
|
||||
|
||||
// $[Compare/Capture Channel 2 init]
|
||||
// [Compare/Capture Channel 2 init]$
|
||||
|
||||
// $[RTCC init]
|
||||
// [RTCC init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// USART0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void USART0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[USART_InitAsync]
|
||||
USART_InitAsync_TypeDef initasync = USART_INITASYNC_DEFAULT;
|
||||
|
||||
initasync.enable = usartDisable;
|
||||
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(USART0, &initasync);
|
||||
// [USART_InitAsync]$
|
||||
|
||||
// $[USART_InitSync]
|
||||
// [USART_InitSync]$
|
||||
|
||||
// $[USART_InitPrsTrigger]
|
||||
USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT;
|
||||
|
||||
initprs.rxTriggerEnable = 0;
|
||||
initprs.txTriggerEnable = 0;
|
||||
initprs.prsTriggerChannel = usartPrsTriggerCh0;
|
||||
|
||||
USART_InitPrsTrigger(USART0, &initprs);
|
||||
// [USART_InitPrsTrigger]$
|
||||
|
||||
// $[USART_InitIO]
|
||||
/* Disable CLK pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_CLKLOC_MASK))
|
||||
| USART_ROUTELOC0_CLKLOC_LOC4;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CLKPEN);
|
||||
|
||||
/* Disable CS pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_CSLOC_MASK))
|
||||
| USART_ROUTELOC0_CSLOC_LOC3;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CSPEN);
|
||||
|
||||
/* Disable CTS pin */
|
||||
USART0->ROUTELOC1 = (USART0->ROUTELOC1 & (~_USART_ROUTELOC1_CTSLOC_MASK))
|
||||
| USART_ROUTELOC1_CTSLOC_LOC2;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CTSPEN);
|
||||
|
||||
/* Disable RTS pin */
|
||||
USART0->ROUTELOC1 = (USART0->ROUTELOC1 & (~_USART_ROUTELOC1_RTSLOC_MASK))
|
||||
| USART_ROUTELOC1_RTSLOC_LOC1;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_RTSPEN);
|
||||
|
||||
/* Set up RX pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK))
|
||||
| USART_ROUTELOC0_RXLOC_LOC0;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN | USART_ROUTEPEN_RXPEN;
|
||||
|
||||
/* Set up TX pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK))
|
||||
| USART_ROUTELOC0_TXLOC_LOC20;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN | USART_ROUTEPEN_TXPEN;
|
||||
|
||||
// [USART_InitIO]$
|
||||
|
||||
// $[USART_Misc]
|
||||
/* Disable CTS */
|
||||
USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_CTSEN);
|
||||
/* Set CTS active low */
|
||||
USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_CTSINV);
|
||||
/* Set RTS active low */
|
||||
USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_RTSINV);
|
||||
/* Set CS active low */
|
||||
USART0->CTRL = USART0->CTRL & (~USART_CTRL_CSINV);
|
||||
/* Set TX active high */
|
||||
USART0->CTRL = USART0->CTRL & (~USART_CTRL_TXINV);
|
||||
/* Set RX active high */
|
||||
USART0->CTRL = USART0->CTRL & (~USART_CTRL_RXINV);
|
||||
// [USART_Misc]$
|
||||
|
||||
// $[USART_Enable]
|
||||
|
||||
/* Enable USART if opted by user */
|
||||
USART_Enable(USART0, usartEnable);
|
||||
// [USART_Enable]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// USART1_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void USART1_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[USART_InitAsync]
|
||||
// [USART_InitAsync]$
|
||||
|
||||
// $[USART_InitSync]
|
||||
USART_InitSync_TypeDef initsync = USART_INITSYNC_DEFAULT;
|
||||
|
||||
initsync.enable = usartDisable;
|
||||
initsync.baudrate = 130000;
|
||||
initsync.databits = usartDatabits8;
|
||||
initsync.master = 1;
|
||||
initsync.msbf = 1;
|
||||
initsync.clockMode = usartClockMode0;
|
||||
#if defined( USART_INPUT_RXPRS ) && defined( USART_TRIGCTRL_AUTOTXTEN )
|
||||
initsync.prsRxEnable = 0;
|
||||
initsync.prsRxCh = 0;
|
||||
initsync.autoTx = 0;
|
||||
#endif
|
||||
|
||||
USART_InitSync(USART1, &initsync);
|
||||
// [USART_InitSync]$
|
||||
|
||||
// $[USART_InitPrsTrigger]
|
||||
USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT;
|
||||
|
||||
initprs.rxTriggerEnable = 0;
|
||||
initprs.txTriggerEnable = 0;
|
||||
initprs.prsTriggerChannel = usartPrsTriggerCh0;
|
||||
|
||||
USART_InitPrsTrigger(USART1, &initprs);
|
||||
// [USART_InitPrsTrigger]$
|
||||
|
||||
// $[USART_InitIO]
|
||||
/* Set up CLK pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_CLKLOC_MASK))
|
||||
| USART_ROUTELOC0_CLKLOC_LOC4;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_CLKPEN;
|
||||
|
||||
/* Disable CS pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_CSLOC_MASK))
|
||||
| USART_ROUTELOC0_CSLOC_LOC3;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_CSPEN);
|
||||
|
||||
/* Disable CTS pin */
|
||||
USART1->ROUTELOC1 = (USART1->ROUTELOC1 & (~_USART_ROUTELOC1_CTSLOC_MASK))
|
||||
| USART_ROUTELOC1_CTSLOC_LOC2;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_CTSPEN);
|
||||
|
||||
/* Disable RTS pin */
|
||||
USART1->ROUTELOC1 = (USART1->ROUTELOC1 & (~_USART_ROUTELOC1_RTSLOC_MASK))
|
||||
| USART_ROUTELOC1_RTSLOC_LOC1;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_RTSPEN);
|
||||
|
||||
/* Set up RX pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK))
|
||||
| USART_ROUTELOC0_RXLOC_LOC6;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_RXPEN;
|
||||
|
||||
/* Set up TX pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK))
|
||||
| USART_ROUTELOC0_TXLOC_LOC8;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_TXPEN;
|
||||
|
||||
// [USART_InitIO]$
|
||||
|
||||
// $[USART_Misc]
|
||||
/* Disable CTS */
|
||||
USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_CTSEN);
|
||||
/* Set CTS active low */
|
||||
USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_CTSINV);
|
||||
/* Set RTS active low */
|
||||
USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_RTSINV);
|
||||
/* Set CS active low */
|
||||
USART1->CTRL = USART1->CTRL & (~USART_CTRL_CSINV);
|
||||
/* Set TX active high */
|
||||
USART1->CTRL = USART1->CTRL & (~USART_CTRL_TXINV);
|
||||
/* Set RX active high */
|
||||
USART1->CTRL = USART1->CTRL & (~USART_CTRL_RXINV);
|
||||
// [USART_Misc]$
|
||||
|
||||
// $[USART_Enable]
|
||||
|
||||
/* Enable USART if opted by user */
|
||||
USART_Enable(USART1, usartEnable);
|
||||
// [USART_Enable]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LEUART0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LEUART0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[LEUART0 initialization]
|
||||
// [LEUART0 initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// WDOG0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void WDOG0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[WDOG Initialization]
|
||||
// [WDOG Initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// I2C0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void I2C0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[I2C0 I/O setup]
|
||||
// [I2C0 I/O setup]$
|
||||
|
||||
// $[I2C0 initialization]
|
||||
// [I2C0 initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// GPCRC_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void GPCRC_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LDMA_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LDMA_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// TIMER0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void TIMER0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[TIMER0 I/O setup]
|
||||
/* Set up CC0 */
|
||||
TIMER0->ROUTELOC0 = (TIMER0->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC0LOC_MASK))
|
||||
| TIMER_ROUTELOC0_CC0LOC_LOC18;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN | TIMER_ROUTEPEN_CC0PEN;
|
||||
/* Set up CC1 */
|
||||
TIMER0->ROUTELOC0 = (TIMER0->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC1LOC_MASK))
|
||||
| TIMER_ROUTELOC0_CC1LOC_LOC16;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN | TIMER_ROUTEPEN_CC1PEN;
|
||||
/* Set up CC2 */
|
||||
TIMER0->ROUTELOC0 = (TIMER0->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC2LOC_MASK))
|
||||
| TIMER_ROUTELOC0_CC2LOC_LOC20;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN | TIMER_ROUTEPEN_CC2PEN;
|
||||
/* Set up CDTI0 */
|
||||
TIMER0->ROUTELOC2 = (TIMER0->ROUTELOC2 & (~_TIMER_ROUTELOC2_CDTI0LOC_MASK))
|
||||
| TIMER_ROUTELOC2_CDTI0LOC_LOC3;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN & (~TIMER_ROUTEPEN_CDTI0PEN);
|
||||
/* Set up CDTI1 */
|
||||
TIMER0->ROUTELOC2 = (TIMER0->ROUTELOC2 & (~_TIMER_ROUTELOC2_CDTI1LOC_MASK))
|
||||
| TIMER_ROUTELOC2_CDTI1LOC_LOC2;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN & (~TIMER_ROUTEPEN_CDTI1PEN);
|
||||
/* Set up CDTI2 */
|
||||
TIMER0->ROUTELOC2 = (TIMER0->ROUTELOC2 & (~_TIMER_ROUTELOC2_CDTI2LOC_MASK))
|
||||
| TIMER_ROUTELOC2_CDTI2LOC_LOC1;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN & (~TIMER_ROUTEPEN_CDTI2PEN);
|
||||
// [TIMER0 I/O setup]$
|
||||
|
||||
// $[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 = timerPrescale512;
|
||||
init.fallAction = timerInputActionNone;
|
||||
init.riseAction = timerInputActionNone;
|
||||
init.mode = timerModeUp;
|
||||
init.quadModeX4 = 0;
|
||||
init.oneShot = 0;
|
||||
init.count2x = 0;
|
||||
init.ati = 0;
|
||||
TIMER_Init(TIMER0, &init);
|
||||
// [TIMER0 initialization]$
|
||||
|
||||
// $[TIMER0 CC0 init]
|
||||
TIMER_InitCC_TypeDef initCC0 = TIMER_INITCC_DEFAULT;
|
||||
|
||||
initCC0.prsInput = false;
|
||||
initCC0.prsSel = timerPRSSELCh0;
|
||||
initCC0.edge = timerEdgeRising;
|
||||
initCC0.mode = timerCCModePWM;
|
||||
initCC0.eventCtrl = timerEventEveryEdge;
|
||||
initCC0.filter = 0;
|
||||
initCC0.cofoa = timerOutputActionNone;
|
||||
initCC0.cufoa = timerOutputActionNone;
|
||||
initCC0.cmoa = timerOutputActionToggle;
|
||||
initCC0.coist = 0;
|
||||
initCC0.outInvert = 0;
|
||||
TIMER_InitCC(TIMER0, 0, &initCC0);
|
||||
// [TIMER0 CC0 init]$
|
||||
|
||||
// $[TIMER0 CC1 init]
|
||||
TIMER_InitCC_TypeDef initCC1 = TIMER_INITCC_DEFAULT;
|
||||
|
||||
initCC1.prsInput = false;
|
||||
initCC1.prsSel = timerPRSSELCh0;
|
||||
initCC1.edge = timerEdgeRising;
|
||||
initCC1.mode = timerCCModePWM;
|
||||
initCC1.eventCtrl = timerEventEveryEdge;
|
||||
initCC1.filter = 0;
|
||||
initCC1.cofoa = timerOutputActionNone;
|
||||
initCC1.cufoa = timerOutputActionNone;
|
||||
initCC1.cmoa = timerOutputActionToggle;
|
||||
initCC1.coist = 0;
|
||||
initCC1.outInvert = 0;
|
||||
TIMER_InitCC(TIMER0, 1, &initCC1);
|
||||
// [TIMER0 CC1 init]$
|
||||
|
||||
// $[TIMER0 CC2 init]
|
||||
TIMER_InitCC_TypeDef initCC2 = TIMER_INITCC_DEFAULT;
|
||||
|
||||
initCC2.prsInput = false;
|
||||
initCC2.prsSel = timerPRSSELCh0;
|
||||
initCC2.edge = timerEdgeRising;
|
||||
initCC2.mode = timerCCModePWM;
|
||||
initCC2.eventCtrl = timerEventEveryEdge;
|
||||
initCC2.filter = 0;
|
||||
initCC2.cofoa = timerOutputActionNone;
|
||||
initCC2.cufoa = timerOutputActionNone;
|
||||
initCC2.cmoa = timerOutputActionToggle;
|
||||
initCC2.coist = 0;
|
||||
initCC2.outInvert = 0;
|
||||
TIMER_InitCC(TIMER0, 2, &initCC2);
|
||||
// [TIMER0 CC2 init]$
|
||||
|
||||
// $[TIMER0 DTI init]
|
||||
TIMER_InitDTI_TypeDef initDTI = TIMER_INITDTI_DEFAULT;
|
||||
|
||||
initDTI.enable = 0;
|
||||
initDTI.activeLowOut = 0;
|
||||
initDTI.invertComplementaryOut = 0;
|
||||
initDTI.autoRestart = 0;
|
||||
initDTI.enablePrsSource = 0;
|
||||
initDTI.prsSel = timerPRSSELCh0;
|
||||
initDTI.prescale = timerPrescale1;
|
||||
initDTI.riseTime = 1;
|
||||
initDTI.fallTime = 1;
|
||||
initDTI.enableFaultSourceCoreLockup = 1;
|
||||
initDTI.enableFaultSourceDebugger = 1;
|
||||
initDTI.faultSourcePrsSel0 = 0;
|
||||
initDTI.faultSourcePrsSel0 = timerPRSSELCh0;
|
||||
initDTI.faultSourcePrsSel1 = 0;
|
||||
initDTI.faultSourcePrsSel1 = timerPRSSELCh0;
|
||||
initDTI.faultAction = timerDtiFaultActionInactive;
|
||||
initDTI.outputsEnableMask = 0 | TIMER_DTOGEN_DTOGCC0EN
|
||||
| TIMER_DTOGEN_DTOGCC1EN | TIMER_DTOGEN_DTOGCC2EN;
|
||||
TIMER_InitDTI(TIMER0, &initDTI);
|
||||
// [TIMER0 DTI init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// TIMER1_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void TIMER1_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[TIMER1 I/O setup]
|
||||
// [TIMER1 I/O setup]$
|
||||
|
||||
// $[TIMER1 initialization]
|
||||
// [TIMER1 initialization]$
|
||||
|
||||
// $[TIMER1 CC0 init]
|
||||
// [TIMER1 CC0 init]$
|
||||
|
||||
// $[TIMER1 CC1 init]
|
||||
// [TIMER1 CC1 init]$
|
||||
|
||||
// $[TIMER1 CC2 init]
|
||||
// [TIMER1 CC2 init]$
|
||||
|
||||
// $[TIMER1 CC3 init]
|
||||
// [TIMER1 CC3 init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LETIMER0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LETIMER0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[LETIMER0 Compare Values]
|
||||
// [LETIMER0 Compare Values]$
|
||||
|
||||
// $[LETIMER0 Repeat Values]
|
||||
// [LETIMER0 Repeat Values]$
|
||||
|
||||
// $[LETIMER0 Initialization]
|
||||
// [LETIMER0 Initialization]$
|
||||
|
||||
// $[LETIMER0 PRS Input Triggers]
|
||||
// [LETIMER0 PRS Input Triggers]$
|
||||
|
||||
// $[LETIMER0 I/O setup]
|
||||
// [LETIMER0 I/O setup]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// CRYOTIMER_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void CRYOTIMER_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[CRYOTIMER_Init]
|
||||
CRYOTIMER_Init_TypeDef cryoInit = CRYOTIMER_INIT_DEFAULT;
|
||||
|
||||
/* General settings */
|
||||
cryoInit.enable = 1;
|
||||
cryoInit.debugRun = 0;
|
||||
cryoInit.em4Wakeup = 0;
|
||||
|
||||
/* Clocking settings */
|
||||
/* With a frequency of 1000Hz on ULFRCO, this will result in a 1.00 ms timeout */
|
||||
cryoInit.osc = cryotimerOscULFRCO;
|
||||
cryoInit.presc = cryotimerPresc_1;
|
||||
cryoInit.period = cryotimerPeriod_1;
|
||||
CRYOTIMER_Init(&cryoInit);
|
||||
// [CRYOTIMER_Init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PCNT0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void PCNT0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[PCNT0 I/O setup]
|
||||
// [PCNT0 I/O setup]$
|
||||
|
||||
// $[PCNT0 initialization]
|
||||
// [PCNT0 initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PRS_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void PRS_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[PRS initialization]
|
||||
// [PRS initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PORTIO_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void PORTIO_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[Port A Configuration]
|
||||
|
||||
/* Pin PA0 is configured to Input enabled */
|
||||
GPIO_PinModeSet(gpioPortA, 0, gpioModeInput, 0);
|
||||
|
||||
/* Pin PA1 is configured to Input enabled */
|
||||
GPIO_PinModeSet(gpioPortA, 1, gpioModeInput, 0);
|
||||
// [Port A Configuration]$
|
||||
|
||||
// $[Port B Configuration]
|
||||
|
||||
/* Pin PB11 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortB, 11, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PB12 is configured to Input enabled with pull-up */
|
||||
GPIO_PinModeSet(gpioPortB, 12, gpioModeInputPull, 1);
|
||||
|
||||
/* Pin PB13 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortB, 13, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PB15 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 1);
|
||||
// [Port B Configuration]$
|
||||
|
||||
// $[Port C Configuration]
|
||||
// [Port C Configuration]$
|
||||
|
||||
// $[Port D Configuration]
|
||||
|
||||
/* Pin PD9 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 9, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD10 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 10, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD11 is configured to Input enabled with pull-up */
|
||||
GPIO_PinModeSet(gpioPortD, 11, gpioModeInputPull, 1);
|
||||
|
||||
/* Pin PD12 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 12, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD13 is configured to Input enabled with pull-up */
|
||||
GPIO_PinModeSet(gpioPortD, 13, gpioModeInputPull, 1);
|
||||
|
||||
/* Pin PD14 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 14, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD15 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 1);
|
||||
// [Port D Configuration]$
|
||||
|
||||
// $[Port E Configuration]
|
||||
// [Port E Configuration]$
|
||||
|
||||
// $[Port F Configuration]
|
||||
// [Port F Configuration]$
|
||||
|
||||
}
|
||||
|
668
targets/efm32/src/crypto.c
Normal file
668
targets/efm32/src/crypto.c
Normal file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
* Wrapper for crypto implementation on device
|
||||
*
|
||||
* */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "em_adc.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "crypto.h"
|
||||
#include "device.h"
|
||||
|
||||
|
||||
#include "sha256.h"
|
||||
#include "uECC.h"
|
||||
#include "aes.h"
|
||||
#include "ctap.h"
|
||||
#include "log.h"
|
||||
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#include "sha256_alt.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/ecdsa.h"
|
||||
|
||||
const uint8_t attestation_cert_der[];
|
||||
const uint16_t attestation_cert_der_size;
|
||||
const uint8_t attestation_key[];
|
||||
const uint16_t attestation_key_size;
|
||||
|
||||
|
||||
static mbedtls_sha256_context embed_sha256_ctx;
|
||||
static mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
static const struct uECC_Curve_t * _es256_curve = NULL;
|
||||
static const uint8_t * _signing_key = NULL;
|
||||
static int _key_len = 0;
|
||||
|
||||
// Secrets for testing only
|
||||
static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
|
||||
"\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00";
|
||||
|
||||
static uint8_t transport_secret[32] = "\x10\x01\x22\x33\x44\x55\x66\x77\x87\x90\x0a\xbb\x3c\xd8\xee\xff"
|
||||
"\xff\xee\x8d\x1c\x3b\xfa\x99\x88\x77\x86\x55\x44\xd3\xff\x33\x00";
|
||||
|
||||
|
||||
|
||||
void crypto_sha256_init()
|
||||
{
|
||||
mbedtls_sha256_init( &embed_sha256_ctx );
|
||||
mbedtls_sha256_starts(&embed_sha256_ctx,0);
|
||||
// sha256_init(&sha256_ctx);
|
||||
}
|
||||
|
||||
void crypto_reset_master_secret()
|
||||
{
|
||||
ctap_generate_rng(master_secret, 32);
|
||||
}
|
||||
|
||||
|
||||
void crypto_sha256_update(uint8_t * data, size_t len)
|
||||
{
|
||||
mbedtls_sha256_update(&embed_sha256_ctx,data,len);
|
||||
// sha256_update(&sha256_ctx, data, len);
|
||||
}
|
||||
|
||||
void crypto_sha256_update_secret()
|
||||
{
|
||||
mbedtls_sha256_update(&embed_sha256_ctx,master_secret,32);
|
||||
// sha256_update(&sha256_ctx, master_secret, 32);
|
||||
}
|
||||
|
||||
void crypto_sha256_final(uint8_t * hash)
|
||||
{
|
||||
mbedtls_sha256_finish( &embed_sha256_ctx, hash );
|
||||
// sha256_final(&sha256_ctx, hash);
|
||||
}
|
||||
|
||||
void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
||||
{
|
||||
uint8_t buf[64];
|
||||
int i;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (key == CRYPTO_MASTER_KEY)
|
||||
{
|
||||
key = master_secret;
|
||||
klen = sizeof(master_secret);
|
||||
}
|
||||
|
||||
if(klen > 64)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, key size must be <= 64\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memmove(buf, key, klen);
|
||||
|
||||
for (i = 0; i < sizeof(buf); i++)
|
||||
{
|
||||
buf[i] = buf[i] ^ 0x36;
|
||||
}
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(buf, 64);
|
||||
}
|
||||
|
||||
void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
||||
{
|
||||
uint8_t buf[64];
|
||||
int i;
|
||||
crypto_sha256_final(hmac);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (key == CRYPTO_MASTER_KEY)
|
||||
{
|
||||
key = master_secret;
|
||||
klen = sizeof(master_secret);
|
||||
}
|
||||
|
||||
|
||||
if(klen > 64)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, key size must be <= 64\n");
|
||||
exit(1);
|
||||
}
|
||||
memmove(buf, key, klen);
|
||||
|
||||
for (i = 0; i < sizeof(buf); i++)
|
||||
{
|
||||
buf[i] = buf[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(buf, 64);
|
||||
crypto_sha256_update(hmac, 32);
|
||||
crypto_sha256_final(hmac);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t adc_rng(void)
|
||||
{
|
||||
int i;
|
||||
uint8_t random = 0;
|
||||
|
||||
/* Random number generation */
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
ADC_Start(ADC0, adcStartSingle);
|
||||
while ((ADC0->IF & ADC_IF_SINGLE) == 0);
|
||||
random |= ((ADC_DataSingleGet(ADC0) & 0x07) << (i * 3));
|
||||
}
|
||||
|
||||
return random;
|
||||
}
|
||||
|
||||
// Generate @num bytes of random numbers to @dest
|
||||
// return 1 if success, error otherwise
|
||||
int ctap_generate_rng(uint8_t * dst, size_t num)
|
||||
{
|
||||
return mbedtls_ctr_drbg_random(&ctr_drbg,dst,num) == 0;
|
||||
}
|
||||
|
||||
int adc_entropy_func( void *data, unsigned char *output, size_t len )
|
||||
{
|
||||
while(len--)
|
||||
*output++ = adc_rng();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypto_ecc256_init()
|
||||
{
|
||||
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
||||
_es256_curve = uECC_secp256r1();
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
if ( mbedtls_ctr_drbg_seed(&ctr_drbg, adc_entropy_func, NULL,
|
||||
master_secret,32 ) != 0 ) {
|
||||
printf2(TAG_ERR, "mbedtls_ctr_drbg_seed failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void crypto_load_external_key(uint8_t * key, int len)
|
||||
{
|
||||
_signing_key = key;
|
||||
_key_len = len;
|
||||
}
|
||||
void crypto_ecc256_load_attestation_key()
|
||||
{
|
||||
_signing_key = attestation_key;
|
||||
_key_len = 32;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Import a point from unsigned binary data
|
||||
*
|
||||
* \param grp Group to which the point should belong
|
||||
* \param P Point to import
|
||||
* \param buf Input buffer
|
||||
* \param ilen Actual length of input
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
|
||||
* MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
|
||||
* is not implemented.
|
||||
*
|
||||
* \note This function does NOT check that the point actually
|
||||
* belongs to the given group, see mbedtls_ecp_check_pubkey() for
|
||||
* that.
|
||||
*/
|
||||
//int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
|
||||
// const unsigned char *buf, size_t ilen );
|
||||
|
||||
/**
|
||||
* \brief Import X from unsigned binary data, big endian
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param buf Input buffer
|
||||
* \param buflen Input buffer size
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
|
||||
*/
|
||||
//int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen );
|
||||
|
||||
/*
|
||||
* Set context from an mbedtls_ecp_keypair
|
||||
*/
|
||||
//int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key );
|
||||
|
||||
|
||||
|
||||
void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
|
||||
{
|
||||
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
mbedtls_mpi d; /*!< our secret value */
|
||||
//#define CRYPTO_ENABLE CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_CRYPTO; \
|
||||
// CRYPTO->IFC = _CRYPTO_IFC_MASK; \
|
||||
// CRYPTO->CMD = CRYPTO_CMD_SEQSTOP; \
|
||||
// CRYPTO->CTRL = CRYPTO_CTRL_DMA0RSEL_DDATA0; \
|
||||
// CRYPTO->SEQCTRL = 0; \
|
||||
// CRYPTO->SEQCTRLB = 0
|
||||
//
|
||||
//#define CRYPTO_DISABLE \
|
||||
// CRYPTO->IEN = 0; \
|
||||
// CMU->HFBUSCLKEN0 &= ~CMU_HFBUSCLKEN0_CRYPTO;
|
||||
// CRYPTO_DISABLE;
|
||||
// CRYPTO_ENABLE;
|
||||
// mbedtls_ecp_group_init( &grp );
|
||||
// mbedtls_mpi_init( &d );
|
||||
// mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
// mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
//
|
||||
// mbedtls_mpi r,s;
|
||||
// mbedtls_mpi_init(&r);
|
||||
// mbedtls_mpi_init(&s);
|
||||
//
|
||||
// printf("signing..\n");
|
||||
// dump_hex(data,len);
|
||||
// mbedtls_ecdsa_sign_det( &grp, &r, &s, &d,
|
||||
// data, 32, MBEDTLS_MD_SHA256 );// Issue: this will freeze on 13th iteration..
|
||||
// printf("signed\n");
|
||||
//
|
||||
// mbedtls_mpi_write_binary(&r,sig,32);
|
||||
// mbedtls_mpi_write_binary(&s,sig+32,32);
|
||||
|
||||
if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0)
|
||||
{
|
||||
printf2(TAG_ERR,"error, uECC failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 1
|
||||
void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID)
|
||||
{
|
||||
|
||||
const struct uECC_Curve_t * curve = NULL;
|
||||
|
||||
switch(MBEDTLS_ECP_ID)
|
||||
{
|
||||
case MBEDTLS_ECP_DP_SECP192R1:
|
||||
curve = uECC_secp192r1();
|
||||
if (_key_len != 24) goto fail;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP224R1:
|
||||
curve = uECC_secp224r1();
|
||||
if (_key_len != 28) goto fail;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP256R1:
|
||||
curve = uECC_secp256r1();
|
||||
if (_key_len != 32) goto fail;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP256K1:
|
||||
curve = uECC_secp256k1();
|
||||
if (_key_len != 32) goto fail;
|
||||
break;
|
||||
default:
|
||||
printf2(TAG_ERR,"error, invalid ECDSA alg specifier\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( uECC_sign(_signing_key, data, len, sig, curve) == 0)
|
||||
{
|
||||
printf2(TAG_ERR,"error, uECC failed\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
|
||||
fail:
|
||||
printf2(TAG_ERR,"error, invalid key length: %d\n", _key_len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#else
|
||||
void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID)
|
||||
{
|
||||
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
mbedtls_mpi d; /*!< our secret value */
|
||||
|
||||
mbedtls_ecp_group_init( &grp );
|
||||
mbedtls_mpi_init( &d );
|
||||
mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_ID);
|
||||
mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
|
||||
mbedtls_mpi r,s;
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
printf("signing..\n");
|
||||
dump_hex(data,len);
|
||||
mbedtls_ecdsa_sign_det( &grp, &r, &s, &d,
|
||||
data, 32, MBEDTLS_MD_SHA256 );// Issue: this will freeze on 13th iteration..
|
||||
printf("signed\n");
|
||||
|
||||
mbedtls_mpi_write_binary(&r,sig,32);
|
||||
mbedtls_mpi_write_binary(&s,sig+32,32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Generate a keypair with configurable base point
|
||||
*/
|
||||
// mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng )
|
||||
// mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng )
|
||||
/*
|
||||
* Curve types: internal for now, might be exposed later
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECP_TYPE_NONE = 0,
|
||||
ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
|
||||
ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
|
||||
} ecp_curve_type;
|
||||
/*
|
||||
* Get the type of a curve
|
||||
*/
|
||||
static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
|
||||
{
|
||||
if( grp->G.X.p == NULL )
|
||||
return( ECP_TYPE_NONE );
|
||||
|
||||
if( grp->G.Y.p == NULL )
|
||||
return( ECP_TYPE_MONTGOMERY );
|
||||
else
|
||||
return( ECP_TYPE_SHORT_WEIERSTRASS );
|
||||
}
|
||||
static int mbedtls_ecp_gen_privkey( mbedtls_ecp_group *grp,
|
||||
const mbedtls_ecp_point *G,
|
||||
mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
size_t n_size = ( grp->nbits + 7 ) / 8;
|
||||
|
||||
#if defined(ECP_MONTGOMERY)
|
||||
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
|
||||
{
|
||||
/* [M225] page 5 */
|
||||
size_t b;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
|
||||
|
||||
/* Make sure the most significant bit is nbits */
|
||||
b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
|
||||
if( b > grp->nbits )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
|
||||
else
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
|
||||
|
||||
/* Make sure the last three bits are unset */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
|
||||
}
|
||||
else
|
||||
#endif /* ECP_MONTGOMERY */
|
||||
#if defined(ECP_SHORTWEIERSTRASS)
|
||||
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
|
||||
{
|
||||
/* SEC1 3.2.1: Generate d such that 1 <= n < N */
|
||||
int count = 0;
|
||||
unsigned char rnd[MBEDTLS_ECP_MAX_BYTES];
|
||||
|
||||
/*
|
||||
* Match the procedure given in RFC 6979 (deterministic ECDSA):
|
||||
* - use the same byte ordering;
|
||||
* - keep the leftmost nbits bits of the generated octet string;
|
||||
* - try until result is in the desired range.
|
||||
* This also avoids any biais, which is especially important for ECDSA.
|
||||
*/
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
|
||||
|
||||
/*
|
||||
* Each try has at worst a probability 1/2 of failing (the msb has
|
||||
* a probability 1/2 of being 0, and then the result will be < N),
|
||||
* so after 30 tries failure probability is a most 2**(-30).
|
||||
*
|
||||
* For most curves, 1 try is enough with overwhelming probability,
|
||||
* since N starts with a lot of 1s in binary, but some curves
|
||||
* such as secp224k1 are actually very close to the worst case.
|
||||
*/
|
||||
if( ++count > 30 )
|
||||
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
|
||||
mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
|
||||
}
|
||||
else
|
||||
#endif /* ECP_SHORTWEIERSTRASS */
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
|
||||
cleanup:
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mbedtls_ecp_derive_pubkey( mbedtls_ecp_group *grp,
|
||||
const mbedtls_ecp_point *G,
|
||||
mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
|
||||
}
|
||||
|
||||
|
||||
static int hmac_vector_func(uint8_t * hmac, uint8_t * dst, int len)
|
||||
{
|
||||
static int hmac_ptr = 0;
|
||||
if (hmac==NULL)
|
||||
{
|
||||
hmac_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
int i;
|
||||
while(len--)
|
||||
{
|
||||
*dst++ = hmac[hmac_ptr++ % 32];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, uint8_t * privkey)
|
||||
{
|
||||
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
crypto_sha256_update(data, len);
|
||||
crypto_sha256_update(data2, len2);
|
||||
crypto_sha256_update(master_secret, 32);
|
||||
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
|
||||
// mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
// mbedtls_mpi d; /*!< our secret value */
|
||||
// mbedtls_ecp_point Q;
|
||||
//
|
||||
// mbedtls_ecp_group_init( &grp );
|
||||
// mbedtls_mpi_init( &d );
|
||||
// mbedtls_ecp_point_init(&Q);
|
||||
//
|
||||
// mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
//
|
||||
//// mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
// hmac_vector_func(NULL, NULL, 0);
|
||||
// mbedtls_ecp_gen_privkey(&grp, &grp.G, &d, &Q, hmac_vector_func, privkey);
|
||||
// mbedtls_mpi_write_binary(&d,privkey,32);
|
||||
}
|
||||
|
||||
|
||||
/*int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);*/
|
||||
void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y)
|
||||
{
|
||||
int ret;
|
||||
uint8_t privkey[32];
|
||||
uint8_t pubkey[64];
|
||||
|
||||
// generate_private_key(data,len,NULL,0,privkey);
|
||||
|
||||
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
crypto_sha256_update(data, len);
|
||||
crypto_sha256_update(NULL, 0);
|
||||
crypto_sha256_update(master_secret, 32);
|
||||
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
|
||||
// mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
// mbedtls_mpi d; /*!< our secret value */
|
||||
// mbedtls_ecp_point Q;
|
||||
//
|
||||
// mbedtls_ecp_group_init( &grp );
|
||||
// mbedtls_mpi_init( &d );
|
||||
// mbedtls_ecp_point_init(&Q);
|
||||
//
|
||||
// mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
//
|
||||
//// mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
// hmac_vector_func(NULL, NULL, 0);
|
||||
// ret= mbedtls_ecp_gen_privkey(&grp, &grp.G, &d, &Q, hmac_vector_func, privkey);
|
||||
// if (ret != 0)
|
||||
// {
|
||||
// printf("error with priv key -0x04%x\n", -ret);
|
||||
// }
|
||||
//// mbedtls_mpi_write_binary(&d,privkey,32);
|
||||
//
|
||||
// memset(pubkey,0,sizeof(pubkey));
|
||||
//
|
||||
// ret = mbedtls_ecp_derive_pubkey( &grp, &grp.G,
|
||||
// &d, &Q, hmac_vector_func, privkey);
|
||||
//
|
||||
// if (ret != 0)
|
||||
// {
|
||||
// printf("error with public key\n");
|
||||
// }
|
||||
//
|
||||
// mbedtls_mpi_write_binary(&Q.X,x,32);
|
||||
// mbedtls_mpi_write_binary(&Q.Y,y,32);
|
||||
|
||||
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
||||
memmove(x,pubkey,32);
|
||||
memmove(y,pubkey+32,32);
|
||||
}
|
||||
|
||||
void crypto_ecc256_load_key(uint8_t * data, int len, uint8_t * data2, int len2)
|
||||
{
|
||||
static uint8_t privkey[32];
|
||||
generate_private_key(data,len,data2,len2,privkey);
|
||||
_signing_key = privkey;
|
||||
_key_len = 32;
|
||||
}
|
||||
|
||||
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey)
|
||||
{
|
||||
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, uECC_make_key failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret)
|
||||
{
|
||||
if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, uECC_shared_secret failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct AES_ctx aes_ctx;
|
||||
void crypto_aes256_init(uint8_t * key, uint8_t * nonce)
|
||||
{
|
||||
if (key == CRYPTO_TRANSPORT_KEY)
|
||||
{
|
||||
AES_init_ctx(&aes_ctx, transport_secret);
|
||||
}
|
||||
else
|
||||
{
|
||||
AES_init_ctx(&aes_ctx, key);
|
||||
}
|
||||
if (nonce == NULL)
|
||||
{
|
||||
memset(aes_ctx.Iv, 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(aes_ctx.Iv, nonce, 16);
|
||||
}
|
||||
}
|
||||
|
||||
// prevent round key recomputation
|
||||
void crypto_aes256_reset_iv(uint8_t * nonce)
|
||||
{
|
||||
if (nonce == NULL)
|
||||
{
|
||||
memset(aes_ctx.Iv, 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(aes_ctx.Iv, nonce, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void crypto_aes256_decrypt(uint8_t * buf, int length)
|
||||
{
|
||||
AES_CBC_decrypt_buffer(&aes_ctx, buf, length);
|
||||
}
|
||||
|
||||
void crypto_aes256_encrypt(uint8_t * buf, int length)
|
||||
{
|
||||
AES_CBC_encrypt_buffer(&aes_ctx, buf, length);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const uint8_t attestation_cert_der[] =
|
||||
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"
|
||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
|
||||
"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e"
|
||||
"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38"
|
||||
"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32"
|
||||
"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
|
||||
"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x0f\x30\x0d"
|
||||
"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55"
|
||||
"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20"
|
||||
"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72"
|
||||
"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04"
|
||||
"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07"
|
||||
"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00"
|
||||
"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf"
|
||||
"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83"
|
||||
"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca"
|
||||
"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d"
|
||||
"\xa1\x30\xa4\x2e\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31"
|
||||
"\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e\x06\x03\x55\x04"
|
||||
"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94"
|
||||
"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04"
|
||||
"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00"
|
||||
"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e"
|
||||
"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd"
|
||||
"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7"
|
||||
"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7";
|
||||
|
||||
|
||||
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1;
|
||||
|
||||
|
||||
const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30";
|
||||
const uint16_t attestation_key_size = sizeof(attestation_key)-1;
|
||||
|
||||
|
||||
|
692
targets/efm32/src/device.c
Normal file
692
targets/efm32/src/device.c
Normal file
@@ -0,0 +1,692 @@
|
||||
/*
|
||||
* device.c
|
||||
*
|
||||
* Created on: Jun 27, 2018
|
||||
* Author: conor
|
||||
*/
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "em_chip.h"
|
||||
#include "em_gpio.h"
|
||||
#include "em_usart.h"
|
||||
#include "em_adc.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_msc.h"
|
||||
#include "em_i2c.h"
|
||||
#include "em_timer.h"
|
||||
|
||||
#include "InitDevice.h"
|
||||
#include "cbor.h"
|
||||
#include "log.h"
|
||||
#include "ctaphid.h"
|
||||
#include "util.h"
|
||||
#include "app.h"
|
||||
#include "uECC.h"
|
||||
#include "crypto.h"
|
||||
#include "nfc.h"
|
||||
|
||||
#ifdef USING_DEV_BOARD
|
||||
|
||||
#define MSG_AVAIL_PIN gpioPortC,9
|
||||
#define RDY_PIN gpioPortC,10
|
||||
#define RW_PIN gpioPortD,11
|
||||
#define RESET_PIN gpioPortB,13
|
||||
#define LED_RED_PIN gpioPortF,4
|
||||
#define LED_GREEN_PIN gpioPortF,5
|
||||
|
||||
#else
|
||||
|
||||
#define MSG_AVAIL_PIN gpioPortA,1
|
||||
#define RDY_PIN gpioPortA,0
|
||||
#define RW_PIN gpioPortD,15
|
||||
#define RESET_PIN gpioPortB,15
|
||||
#define LED_RED_PIN gpioPortD,10
|
||||
#define LED_GREEN_PIN gpioPortD,14
|
||||
#define LED_BLUE_PIN gpioPortD,9
|
||||
#define BUTTON_PIN gpioPortD,13
|
||||
|
||||
#define RED_CHANNEL 0
|
||||
#define GREEN_CHANNEL 2
|
||||
#define BLUE_CHANNEL 1
|
||||
|
||||
#endif
|
||||
|
||||
#define PAGE_SIZE 2048
|
||||
#define PAGES 64
|
||||
#define COUNTER_PAGE (PAGES - 3)
|
||||
#define STATE1_PAGE (PAGES - 2)
|
||||
#define STATE2_PAGE (PAGES - 1)
|
||||
|
||||
#define APPLICATION_START_ADDR 0x4000
|
||||
#define APPLICATION_START_PAGE (0x4000/PAGE_SIZE)
|
||||
|
||||
#define APPLICATION_END_ADDR (PAGE_SIZE*(PAGES - 3)-4) // NOT included in application
|
||||
#define APPLICATION_END_PAGE ((PAGES - 3)) // 125 is NOT included in application
|
||||
|
||||
#define AUTH_WORD_ADDR (PAGE_SIZE*(PAGES - 3)-4)
|
||||
|
||||
|
||||
|
||||
static void init_atomic_counter()
|
||||
{
|
||||
int offset = 0;
|
||||
uint32_t count;
|
||||
uint32_t one = 1;
|
||||
uint32_t * ptr = PAGE_SIZE * COUNTER_PAGE;
|
||||
|
||||
for (offset = 0; offset < PAGE_SIZE/4; offset += 1)
|
||||
{
|
||||
count = *(ptr+offset);
|
||||
if (count != 0xffffffff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
MSC_WriteWordFast(ptr,&one,4);
|
||||
}
|
||||
|
||||
|
||||
uint32_t ctap_atomic_count(int sel)
|
||||
{
|
||||
int offset = 0;
|
||||
uint32_t count;
|
||||
uint32_t zero = 0;
|
||||
uint32_t * ptr = PAGE_SIZE * COUNTER_PAGE;
|
||||
|
||||
if (sel != 0)
|
||||
{
|
||||
printf2(TAG_ERR,"counter2 not imple\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (offset = 0; offset < PAGE_SIZE/4; offset += 1) // wear-level the flash
|
||||
{
|
||||
count = *(ptr+offset);
|
||||
if (count != 0)
|
||||
{
|
||||
count++;
|
||||
offset++;
|
||||
if (offset == PAGE_SIZE/4)
|
||||
{
|
||||
offset = 0;
|
||||
MSC_ErasePage(ptr);
|
||||
/*printf("RESET page counter\n");*/
|
||||
}
|
||||
else
|
||||
{
|
||||
MSC_WriteWordFast(ptr+offset-1,&zero,4);
|
||||
}
|
||||
MSC_WriteWordFast(ptr+offset,&count,4);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static uint32_t _color;
|
||||
uint32_t get_RBG()
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
void RGB(uint32_t hex)
|
||||
{
|
||||
uint16_t r = 256 - ((hex & 0xff0000) >> 16);
|
||||
uint16_t g = 256 - ((hex & 0xff00) >> 8);
|
||||
uint16_t b = 256 - ((hex & 0xff) >> 0);
|
||||
|
||||
TIMER_CompareBufSet(TIMER0, GREEN_CHANNEL, g); // green
|
||||
TIMER_CompareBufSet(TIMER0, RED_CHANNEL, r); // red
|
||||
TIMER_CompareBufSet(TIMER0, BLUE_CHANNEL, b); // blue
|
||||
_color = hex;
|
||||
}
|
||||
|
||||
|
||||
#define IS_BUTTON_PRESSED() (GPIO_PinInGet(BUTTON_PIN) == 0)
|
||||
|
||||
// Verify the user
|
||||
// return 1 if user is verified, 0 if not
|
||||
int ctap_user_verification(uint8_t arg)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test for user presence
|
||||
// Return 1 for user is present, 0 user not present
|
||||
int ctap_user_presence_test()
|
||||
{
|
||||
#ifdef SKIP_BUTTON_CHECK
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t t1 = millis();
|
||||
RGB(0x304010);
|
||||
|
||||
#ifdef USE_BUTTON_DELAY
|
||||
delay(3000);
|
||||
RGB(0x001040);
|
||||
delay(50);
|
||||
return 1;
|
||||
#endif
|
||||
while (IS_BUTTON_PRESSED())
|
||||
{
|
||||
if (t1 + 5000 < millis())
|
||||
{
|
||||
printf1(TAG_GEN,"Button not pressed\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
t1 = millis();
|
||||
|
||||
do
|
||||
{
|
||||
if (t1 + 5000 < millis())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (! IS_BUTTON_PRESSED())
|
||||
continue;
|
||||
delay(1);
|
||||
}
|
||||
while (! IS_BUTTON_PRESSED());
|
||||
|
||||
RGB(0x001040);
|
||||
|
||||
delay(50);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Must be implemented by application
|
||||
// data is HID_MESSAGE_SIZE long in bytes
|
||||
#ifndef TEST_POWER
|
||||
void ctaphid_write_block(uint8_t * data)
|
||||
{
|
||||
printf1(TAG_DUMP,"<< "); dump_hex1(TAG_DUMP, data, HID_MESSAGE_SIZE);
|
||||
usbhid_send(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IS_BOOTLOADER // two different colors between bootloader and app
|
||||
void heartbeat()
|
||||
{
|
||||
static int state = 0;
|
||||
static uint32_t val = (LED_INIT_VALUE >> 8) & 0xff;
|
||||
int but = IS_BUTTON_PRESSED();
|
||||
|
||||
|
||||
if (state)
|
||||
{
|
||||
val--;
|
||||
}
|
||||
else
|
||||
{
|
||||
val++;
|
||||
}
|
||||
|
||||
if (val > 30 || val < 1)
|
||||
{
|
||||
state = !state;
|
||||
}
|
||||
|
||||
// if (but) RGB(val * 2);
|
||||
// else
|
||||
RGB((val << 16) | (val*2 << 8));
|
||||
|
||||
}
|
||||
#else
|
||||
void heartbeat()
|
||||
{
|
||||
static int state = 0;
|
||||
static uint32_t val = (LED_INIT_VALUE >> 8) & 0xff;
|
||||
int but = IS_BUTTON_PRESSED();
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
RGB(0x100000); // bright ass light
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (state)
|
||||
{
|
||||
val--;
|
||||
}
|
||||
else
|
||||
{
|
||||
val++;
|
||||
}
|
||||
|
||||
if (val >120/3 || val < 1)
|
||||
{
|
||||
state = !state;
|
||||
}
|
||||
|
||||
if (but) RGB(val * 2);
|
||||
else RGB(val*3 | ((val*3) << 8) | (val << 16) );
|
||||
// else RGB((val*3) << 8);
|
||||
|
||||
}
|
||||
#endif
|
||||
uint32_t millis()
|
||||
{
|
||||
return CRYOTIMER->CNT;
|
||||
}
|
||||
|
||||
|
||||
void usbhid_init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int msgs_to_recv = 0;
|
||||
|
||||
static void wait_for_efm8_ready()
|
||||
{
|
||||
// Wait for efm8 to be ready
|
||||
while (GPIO_PinInGet(RDY_PIN) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
static void wait_for_efm8_busy()
|
||||
{
|
||||
// Wait for efm8 to be ready
|
||||
while (GPIO_PinInGet(RDY_PIN) != 0)
|
||||
;
|
||||
}
|
||||
|
||||
#ifndef TEST_POWER
|
||||
int usbhid_recv(uint8_t * msg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (GPIO_PinInGet(MSG_AVAIL_PIN) == 0)
|
||||
{
|
||||
GPIO_PinOutClear(RW_PIN); // Drive low to indicate READ
|
||||
wait_for_efm8_ready();
|
||||
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
msg[i] = USART_SpiTransfer(USART1, 'A');
|
||||
// delay(1);
|
||||
}
|
||||
|
||||
GPIO_PinOutSet(RW_PIN);
|
||||
|
||||
wait_for_efm8_busy();
|
||||
|
||||
|
||||
// // msgs_to_recv--;
|
||||
// printf(">> ");
|
||||
// dump_hex(msg,64);
|
||||
return 64;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void usbhid_send(uint8_t * msg)
|
||||
{
|
||||
int i;
|
||||
// uint32_t t1 = millis();
|
||||
USART_SpiTransfer(USART1, *msg++); // Send 1 byte
|
||||
wait_for_efm8_ready();
|
||||
|
||||
for (i = 1; i < HID_MESSAGE_SIZE; i++)
|
||||
{
|
||||
USART_SpiTransfer(USART1, *msg++);
|
||||
}
|
||||
wait_for_efm8_busy();
|
||||
|
||||
delay(10);
|
||||
// uint32_t t2 = millis();
|
||||
// printf("wait time: %u\n", (uint32_t)(t2-t1));
|
||||
|
||||
}
|
||||
|
||||
void usbhid_close()
|
||||
{
|
||||
}
|
||||
|
||||
void main_loop_delay()
|
||||
{
|
||||
}
|
||||
|
||||
void delay(int ms)
|
||||
{
|
||||
int t1 = millis();
|
||||
while(millis() - t1 < ms)
|
||||
;
|
||||
}
|
||||
|
||||
void GPIO_ODD_IRQHandler()
|
||||
{
|
||||
uint32_t flag = GPIO->IF;
|
||||
GPIO->IFC = flag;
|
||||
if (flag & (1<<9))
|
||||
{
|
||||
// printf("pin 9 interrupt\r\n");
|
||||
msgs_to_recv++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_ERR,"wrong pin int %x\r\n",flag);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void init_adc()
|
||||
{
|
||||
/* Enable ADC Clock */
|
||||
CMU_ClockEnable(cmuClock_ADC0, true);
|
||||
ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
|
||||
ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
|
||||
|
||||
/* Initialize the ADC with the required values */
|
||||
init.timebase = ADC_TimebaseCalc(0);
|
||||
init.prescale = ADC_PrescaleCalc(7000000, 0);
|
||||
ADC_Init(ADC0, &init);
|
||||
|
||||
/* Initialize for single conversion specific to RNG */
|
||||
singleInit.reference = adcRefVEntropy;
|
||||
singleInit.diff = true;
|
||||
singleInit.posSel = adcPosSelVSS;
|
||||
singleInit.negSel = adcNegSelVSS;
|
||||
ADC_InitSingle(ADC0, &singleInit);
|
||||
|
||||
/* Set VINATT to maximum value and clear FIFO */
|
||||
ADC0->SINGLECTRLX |= _ADC_SINGLECTRLX_VINATT_MASK;
|
||||
ADC0->SINGLEFIFOCLEAR = ADC_SINGLEFIFOCLEAR_SINGLEFIFOCLEAR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void authenticator_read_state(AuthenticatorState * state)
|
||||
{
|
||||
uint32_t * ptr = PAGE_SIZE*STATE1_PAGE;
|
||||
memmove(state,ptr,sizeof(AuthenticatorState));
|
||||
}
|
||||
|
||||
void authenticator_read_backup_state(AuthenticatorState * state )
|
||||
{
|
||||
uint32_t * ptr = PAGE_SIZE*STATE2_PAGE;
|
||||
memmove(state,ptr,sizeof(AuthenticatorState));
|
||||
}
|
||||
|
||||
void authenticator_write_state(AuthenticatorState * state, int backup)
|
||||
{
|
||||
uint32_t * ptr;
|
||||
if (! backup)
|
||||
{
|
||||
ptr = PAGE_SIZE*STATE1_PAGE;
|
||||
MSC_ErasePage(ptr);
|
||||
// for (i = 0; i < sizeof(AuthenticatorState)/4; i++ )
|
||||
MSC_WriteWordFast(ptr,state,sizeof(AuthenticatorState) + (sizeof(AuthenticatorState)%4));
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = PAGE_SIZE*STATE2_PAGE;
|
||||
MSC_ErasePage(ptr);
|
||||
// for (i = 0; i < sizeof(AuthenticatorState)/4; i++ )
|
||||
MSC_WriteWordFast(ptr,state,sizeof(AuthenticatorState) + (sizeof(AuthenticatorState)%4));
|
||||
}
|
||||
}
|
||||
|
||||
// Return 1 yes backup is init'd, else 0
|
||||
int authenticator_is_backup_initialized()
|
||||
{
|
||||
uint8_t header[16];
|
||||
uint32_t * ptr = PAGE_SIZE*STATE2_PAGE;
|
||||
memmove(header,ptr,16);
|
||||
AuthenticatorState * state = (AuthenticatorState*)header;
|
||||
return state->is_initialized == INITIALIZED_MARKER;
|
||||
}
|
||||
|
||||
|
||||
uint8_t adc_rng(void);
|
||||
|
||||
void reset_efm8()
|
||||
{
|
||||
// Reset EFM8
|
||||
GPIO_PinOutClear(RESET_PIN);
|
||||
delay(2);
|
||||
GPIO_PinOutSet(RESET_PIN);
|
||||
}
|
||||
|
||||
void bootloader_init(void)
|
||||
{
|
||||
/* Chip errata */
|
||||
|
||||
// Reset EFM8
|
||||
GPIO_PinModeSet(RESET_PIN, gpioModePushPull, 1);
|
||||
|
||||
// status LEDS
|
||||
GPIO_PinModeSet(LED_RED_PIN,
|
||||
gpioModePushPull,
|
||||
1); // red
|
||||
|
||||
GPIO_PinModeSet(LED_GREEN_PIN,
|
||||
gpioModePushPull,
|
||||
1); // green
|
||||
GPIO_PinModeSet(LED_BLUE_PIN,
|
||||
gpioModePushPull,
|
||||
1); // blue
|
||||
|
||||
// EFM8 RDY/BUSY
|
||||
GPIO_PinModeSet(RDY_PIN, gpioModeInput, 0);
|
||||
|
||||
// EFM8 MSG Available
|
||||
GPIO_PinModeSet(MSG_AVAIL_PIN, gpioModeInput, 0);
|
||||
|
||||
// SPI R/w Indicator
|
||||
GPIO_PinModeSet(RW_PIN, gpioModePushPull, 1);
|
||||
|
||||
|
||||
printing_init();
|
||||
|
||||
|
||||
MSC_Init();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void device_init(void)
|
||||
{
|
||||
/* Chip errata */
|
||||
|
||||
CHIP_Init();
|
||||
enter_DefaultMode_from_RESET();
|
||||
|
||||
// status LEDS
|
||||
GPIO_PinModeSet(LED_RED_PIN,
|
||||
gpioModePushPull,
|
||||
1); // red
|
||||
|
||||
GPIO_PinModeSet(LED_GREEN_PIN,
|
||||
gpioModePushPull,
|
||||
1); // green
|
||||
GPIO_PinModeSet(LED_BLUE_PIN,
|
||||
gpioModePushPull,
|
||||
1); // blue
|
||||
|
||||
// EFM8 RDY/BUSY
|
||||
GPIO_PinModeSet(RDY_PIN, gpioModeInput, 0);
|
||||
|
||||
// EFM8 MSG Available
|
||||
GPIO_PinModeSet(MSG_AVAIL_PIN, gpioModeInput, 0);
|
||||
|
||||
// SPI R/w Indicator
|
||||
GPIO_PinModeSet(RW_PIN, gpioModePushPull, 1);
|
||||
|
||||
// Reset EFM8
|
||||
GPIO_PinModeSet(RESET_PIN, gpioModePushPull, 1);
|
||||
|
||||
TIMER_TopSet(TIMER0, 255);
|
||||
|
||||
RGB(LED_INIT_VALUE);
|
||||
|
||||
printing_init();
|
||||
|
||||
init_adc();
|
||||
|
||||
MSC_Init();
|
||||
|
||||
init_atomic_counter();
|
||||
if (sizeof(AuthenticatorState) > PAGE_SIZE)
|
||||
{
|
||||
printf2(TAG_ERR, "not enough room in page\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
CborEncoder test;
|
||||
uint8_t buf[64];
|
||||
cbor_encoder_init(&test, buf, 20, 0);
|
||||
|
||||
reset_efm8();
|
||||
|
||||
printf1(TAG_GEN,"Device init\r\n");
|
||||
int i=0;
|
||||
|
||||
for (i = 0; i < sizeof(buf); i++)
|
||||
{
|
||||
buf[i] = adc_rng();
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef IS_BOOTLOADER
|
||||
typedef enum
|
||||
{
|
||||
BootWrite = 0x40,
|
||||
BootDone = 0x41,
|
||||
BootCheck = 0x42,
|
||||
BootErase = 0x43,
|
||||
} WalletOperation;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t op;
|
||||
uint8_t addr[3];
|
||||
uint8_t tag[4];
|
||||
uint8_t len;
|
||||
uint8_t payload[255 - 9];
|
||||
} __attribute__((packed)) BootloaderReq;
|
||||
|
||||
//#define APPLICATION_START_ADDR 0x8000
|
||||
//#define APPLICATION_START_PAGE (0x8000/PAGE_SIZE)
|
||||
|
||||
//#define APPLICATION_END_ADDR (PAGE_SIZE*125-4) // NOT included in application
|
||||
|
||||
static void erase_application()
|
||||
{
|
||||
int page;
|
||||
uint32_t * ptrpage;
|
||||
for(page = APPLICATION_START_PAGE; page < APPLICATION_END_PAGE; page++)
|
||||
{
|
||||
ptrpage = page * PAGE_SIZE;
|
||||
MSC_ErasePage(ptrpage);
|
||||
}
|
||||
}
|
||||
|
||||
static void authorize_application()
|
||||
{
|
||||
uint32_t zero = 0;
|
||||
uint32_t * ptr;
|
||||
ptr = AUTH_WORD_ADDR;
|
||||
MSC_WriteWordFast(ptr,&zero, 4);
|
||||
}
|
||||
int bootloader_bridge(uint8_t klen, uint8_t * keyh)
|
||||
{
|
||||
static int has_erased = 0;
|
||||
BootloaderReq * req = (BootloaderReq * )keyh;
|
||||
uint8_t payload[256];
|
||||
uint8_t hash[32];
|
||||
uint8_t * pubkey = (uint8_t*)"\x57\xe6\x80\x39\x56\x46\x2f\x0c\x95\xac\x72\x71\xf0\xbc\xe8\x2d\x67\xd0\x59\x29\x2e\x15\x22\x89\x6a\xbd\x3f\x7f\x27\xf3\xc0\xc6\xe2\xd7\x7d\x8a\x9f\xcc\x53\xc5\x91\xb2\x0c\x9c\x3b\x4e\xa4\x87\x31\x67\xb4\xa9\x4b\x0e\x8d\x06\x67\xd8\xc5\xef\x2c\x50\x4a\x55";
|
||||
const struct uECC_Curve_t * curve = NULL;
|
||||
|
||||
/*printf("bootloader_bridge\n");*/
|
||||
if (req->len > 255-9)
|
||||
{
|
||||
return CTAP1_ERR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
memset(payload, 0xff, sizeof(payload));
|
||||
memmove(payload, req->payload, req->len);
|
||||
|
||||
uint32_t addr = (*((uint32_t*)req->addr)) & 0xffffff;
|
||||
|
||||
uint32_t * ptr = addr;
|
||||
|
||||
switch(req->op){
|
||||
case BootWrite:
|
||||
/*printf("BootWrite 0x%08x\n", addr);*/
|
||||
if (ptr < APPLICATION_START_ADDR || ptr >= APPLICATION_END_ADDR)
|
||||
{
|
||||
return CTAP2_ERR_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
if (!has_erased)
|
||||
{
|
||||
erase_application();
|
||||
has_erased = 1;
|
||||
}
|
||||
if (is_authorized_to_boot())
|
||||
{
|
||||
printf2(TAG_ERR, "Error, boot check bypassed\n");
|
||||
exit(1);
|
||||
}
|
||||
MSC_WriteWordFast(ptr,payload, req->len + (req->len%4));
|
||||
break;
|
||||
case BootDone:
|
||||
// printf("BootDone\n");
|
||||
ptr = APPLICATION_START_ADDR;
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(ptr, APPLICATION_END_ADDR-APPLICATION_START_ADDR);
|
||||
crypto_sha256_final(hash);
|
||||
// printf("hash: "); dump_hex(hash, 32);
|
||||
// printf("sig: "); dump_hex(payload, 64);
|
||||
curve = uECC_secp256r1();
|
||||
|
||||
if (! uECC_verify(pubkey,
|
||||
hash,
|
||||
32,
|
||||
payload,
|
||||
curve))
|
||||
{
|
||||
return CTAP2_ERR_OPERATION_DENIED;
|
||||
}
|
||||
authorize_application();
|
||||
REBOOT_FLAG = 1;
|
||||
break;
|
||||
case BootCheck:
|
||||
/*printf("BootCheck\n");*/
|
||||
return 0;
|
||||
break;
|
||||
case BootErase:
|
||||
/*printf("BootErase\n");*/
|
||||
erase_application();
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return CTAP1_ERR_INVALID_COMMAND;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_authorized_to_boot()
|
||||
{
|
||||
uint32_t * auth = AUTH_WORD_ADDR;
|
||||
return *auth == 0;
|
||||
}
|
||||
|
||||
#endif
|
13
targets/efm32/src/main.c
Normal file
13
targets/efm32/src/main.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "em_chip.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_emu.h"
|
||||
#include "em_core.h"
|
||||
#include "em_gpio.h"
|
||||
|
||||
#include "InitDevice.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "cbor.h"
|
361
targets/efm32/src/nfc.c
Normal file
361
targets/efm32/src/nfc.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* nfc.c
|
||||
*
|
||||
* Created on: Jul 22, 2018
|
||||
* Author: conor
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "em_chip.h"
|
||||
#include "em_gpio.h"
|
||||
#include "em_i2c.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include "nfc.h"
|
||||
#include "app.h"
|
||||
|
||||
#define NFC_DEV_ADDR (0xa0|(0x0<<1))
|
||||
#define NFC_DEV_USART USART1
|
||||
#ifndef IS_BOOTLOADER
|
||||
I2C_TransferReturn_TypeDef I2CSPM_Transfer(I2C_TypeDef *i2c, I2C_TransferSeq_TypeDef *seq)
|
||||
{
|
||||
I2C_TransferReturn_TypeDef ret;
|
||||
uint32_t timeout = 10000;
|
||||
/* Do a polled transfer */
|
||||
ret = I2C_TransferInit(i2c, seq);
|
||||
|
||||
while (ret == i2cTransferInProgress && timeout--)
|
||||
{
|
||||
ret = I2C_Transfer(i2c);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// data must be 16 bytes
|
||||
void read_block(uint8_t block, uint8_t * data)
|
||||
{
|
||||
uint8_t addr = NFC_DEV_ADDR;
|
||||
I2C_TransferSeq_TypeDef seq;
|
||||
I2C_TransferReturn_TypeDef ret;
|
||||
uint8_t i2c_read_data[16];
|
||||
uint8_t i2c_write_data[1];
|
||||
|
||||
seq.addr = addr;
|
||||
seq.flags = I2C_FLAG_WRITE_READ;
|
||||
/* Select command to issue */
|
||||
i2c_write_data[0] = block;
|
||||
seq.buf[0].data = i2c_write_data;
|
||||
seq.buf[0].len = 1;
|
||||
/* Select location/length of data to be read */
|
||||
seq.buf[1].data = i2c_read_data;
|
||||
seq.buf[1].len = 16;
|
||||
|
||||
ret = I2CSPM_Transfer(I2C0, &seq);
|
||||
|
||||
if (ret != i2cTransferDone) {
|
||||
printf("I2C fail %04x\r\n",ret);
|
||||
exit(1);
|
||||
}
|
||||
memmove(data, i2c_read_data, 16);
|
||||
}
|
||||
|
||||
// data must be 16 bytes
|
||||
void write_block(uint8_t block, uint8_t * data)
|
||||
{
|
||||
uint8_t addr = NFC_DEV_ADDR;
|
||||
I2C_TransferSeq_TypeDef seq;
|
||||
I2C_TransferReturn_TypeDef ret;
|
||||
uint8_t i2c_write_data[1 + 16];
|
||||
|
||||
seq.addr = addr;
|
||||
seq.flags = I2C_FLAG_WRITE;
|
||||
/* Select command to issue */
|
||||
i2c_write_data[0] = block;
|
||||
memmove(i2c_write_data + 1, data, 16);
|
||||
seq.buf[0].data = i2c_write_data;
|
||||
seq.buf[0].len = 17;
|
||||
/* Select location/length of data to be read */
|
||||
seq.buf[1].data = NULL;
|
||||
seq.buf[1].len = 0;
|
||||
|
||||
ret = I2CSPM_Transfer(I2C0, &seq);
|
||||
|
||||
if (ret != i2cTransferDone) {
|
||||
printf("I2C fail %04x\r\n",ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_reg_flash(uint8_t reg_addr, uint8_t mask,uint8_t data)
|
||||
{
|
||||
uint8_t addr = NFC_DEV_ADDR;
|
||||
I2C_TransferSeq_TypeDef seq;
|
||||
I2C_TransferReturn_TypeDef ret;
|
||||
uint8_t i2c_write_data[4];
|
||||
|
||||
seq.addr = addr;
|
||||
seq.flags = I2C_FLAG_WRITE;
|
||||
i2c_write_data[0] = 0x3a;
|
||||
i2c_write_data[1] = reg_addr;
|
||||
i2c_write_data[2] = mask;
|
||||
i2c_write_data[3] = data;
|
||||
|
||||
seq.buf[0].data = i2c_write_data;
|
||||
seq.buf[0].len = 4;
|
||||
seq.buf[1].data = NULL;
|
||||
seq.buf[1].len = 0;
|
||||
|
||||
ret = I2CSPM_Transfer(I2C0, &seq);
|
||||
|
||||
if (ret != i2cTransferDone) {
|
||||
printf("I2C fail %04x\r\n",ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_reg(uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
|
||||
uint8_t mode = 0x00 | (reg_addr & 0x1f);
|
||||
// delay(10);
|
||||
|
||||
// delay(10);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(1);
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
mode = USART_SpiTransfer(NFC_DEV_USART, data);
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
}
|
||||
|
||||
void write_command(uint8_t cmd)
|
||||
{
|
||||
|
||||
uint8_t mode = cmd;
|
||||
// delay(10);
|
||||
|
||||
// delay(10);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(1);
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
|
||||
}
|
||||
|
||||
void write_eeprom(uint8_t block, uint8_t * data)
|
||||
{
|
||||
|
||||
uint8_t mode = 0x40;
|
||||
// delay(10);
|
||||
|
||||
// delay(10);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(1);
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
mode = block << 1;
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
USART_SpiTransfer(NFC_DEV_USART, *data++);
|
||||
USART_SpiTransfer(NFC_DEV_USART, *data++);
|
||||
USART_SpiTransfer(NFC_DEV_USART, *data++);
|
||||
USART_SpiTransfer(NFC_DEV_USART, *data++);
|
||||
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
|
||||
}
|
||||
|
||||
void read_eeprom(uint8_t block, uint8_t * data)
|
||||
{
|
||||
|
||||
uint8_t mode = 0x7f;
|
||||
// delay(10);
|
||||
|
||||
// delay(10);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(1);
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
mode = block << 1;
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
*data++ = USART_SpiTransfer(NFC_DEV_USART, 0);
|
||||
*data++ = USART_SpiTransfer(NFC_DEV_USART, 0);
|
||||
*data++ = USART_SpiTransfer(NFC_DEV_USART, 0);
|
||||
*data++ = USART_SpiTransfer(NFC_DEV_USART, 0);
|
||||
|
||||
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
|
||||
}
|
||||
|
||||
uint8_t read_reg(uint8_t reg_addr)
|
||||
{
|
||||
|
||||
uint8_t mode = 0x20 | (reg_addr & 0x1f);
|
||||
// delay(10);
|
||||
|
||||
// delay(10);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(1);
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
mode = USART_SpiTransfer(NFC_DEV_USART, 0);
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
|
||||
// printf("%02x: %x\n",(reg_addr),(int)mode);
|
||||
return mode;
|
||||
}
|
||||
|
||||
void read_buffer(uint8_t * data, int len)
|
||||
{
|
||||
|
||||
uint8_t mode = 0xC0;
|
||||
int i;
|
||||
if (len > 32)
|
||||
{
|
||||
printf("warning, max len is 32\n");
|
||||
len = 32;
|
||||
}
|
||||
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(1);
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
*data++ = USART_SpiTransfer(NFC_DEV_USART, 0);
|
||||
}
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
|
||||
}
|
||||
|
||||
// data must be 14 bytes long
|
||||
void read_reg_block(uint8_t * data)
|
||||
{
|
||||
int i;
|
||||
uint8_t mode = 0x20 | (0 & 0x1f);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(1);
|
||||
USART_SpiTransfer(NFC_DEV_USART, mode);
|
||||
for (i = 0; i < 0x20; i++)
|
||||
{
|
||||
mode = USART_SpiTransfer(NFC_DEV_USART, 0);
|
||||
if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e))
|
||||
{
|
||||
*data = mode;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t header;
|
||||
uint8_t tlen;
|
||||
uint8_t plen;
|
||||
uint8_t ilen;
|
||||
uint8_t rtype;
|
||||
} NDEF;
|
||||
|
||||
typedef struct {
|
||||
uint8_t io;
|
||||
uint8_t conf0;
|
||||
uint8_t conf1;
|
||||
uint8_t conf2;
|
||||
uint8_t rfid_status;
|
||||
uint8_t ic_status;
|
||||
uint8_t mask0;
|
||||
uint8_t mask1;
|
||||
uint8_t int0;
|
||||
uint8_t int1;
|
||||
uint8_t buf_status2;
|
||||
uint8_t buf_status1;
|
||||
uint8_t last_nfc_address;
|
||||
uint8_t maj;
|
||||
uint8_t minor;
|
||||
} __attribute__((packed)) AMS_REGS;
|
||||
|
||||
void nfc_test()
|
||||
{
|
||||
uint8_t data[32];
|
||||
uint8_t ns_reg;
|
||||
uint8_t last_ns_reg;
|
||||
// magic-number,
|
||||
uint8_t cc[] = {0xE1,0x10,0x08, 0x00};
|
||||
|
||||
uint8_t ndef[32] = "\x03\x11\xD1\x01\x0D\x55\x01adafruit.com";
|
||||
|
||||
AMS_REGS * regs;
|
||||
|
||||
return ;
|
||||
|
||||
|
||||
|
||||
delay(10);
|
||||
GPIO_PinOutSet(NFC_DEV_SS);
|
||||
delay(10);
|
||||
GPIO_PinOutClear(NFC_DEV_SS);
|
||||
delay(10);
|
||||
|
||||
// uint8_t reg = read_reg(0);
|
||||
write_command(0xC2); // Set to default state
|
||||
write_command(0xC4); // Clear buffer
|
||||
|
||||
write_reg(0x3, 0x80 | 0x40); // enable tunneling mode and RF configuration
|
||||
|
||||
|
||||
|
||||
read_reg_block(data);
|
||||
|
||||
printf("regs: "); dump_hex(data,15);
|
||||
|
||||
delay(100);
|
||||
|
||||
|
||||
read_reg_block(data);
|
||||
|
||||
printf("regs: "); dump_hex(data,15);
|
||||
|
||||
|
||||
|
||||
if (0)
|
||||
{
|
||||
read_eeprom(0x7F, data);
|
||||
printf("initial config: "); dump_hex(data,4);
|
||||
|
||||
data[0] = (1<<2) | 0x03; // save cfg1 setting for energy harvesting
|
||||
data[1] = 0x80 | 0x40; // save cfg2 setting for tunneling
|
||||
write_eeprom(0x7F, data);
|
||||
|
||||
printf("updated config: "); dump_hex(data,4);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
// delay(100);
|
||||
// read_reg_block(data);
|
||||
// regs = (AMS_REGS *)data;
|
||||
//
|
||||
// if ((regs->buf_status2 & 0x3f) && !(regs->buf_status2 & 0x80))
|
||||
// {
|
||||
// read_buffer(data, regs->buf_status2 & 0x3f);
|
||||
// printf("data: ");
|
||||
//
|
||||
// dump_hex(data, regs->buf_status2 & 0x3f);
|
||||
// }
|
||||
|
||||
// dump_hex(data,15);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
84
targets/efm32/src/printing.c
Normal file
84
targets/efm32/src/printing.c
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "em_chip.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_emu.h"
|
||||
#include "em_core.h"
|
||||
#include "em_usart.h"
|
||||
#include "em_gpio.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "app.h"
|
||||
#ifndef PRINTING_USE_VCOM
|
||||
int RETARGET_WriteChar(char c)
|
||||
{
|
||||
return ITM_SendChar(c);
|
||||
}
|
||||
|
||||
int RETARGET_ReadChar(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setupSWOForPrint(void)
|
||||
{
|
||||
/* Enable GPIO clock. */
|
||||
CMU_ClockEnable(cmuClock_GPIO, true);
|
||||
|
||||
/* Enable Serial wire output pin */
|
||||
GPIO->ROUTEPEN |= GPIO_ROUTEPEN_SWVPEN;
|
||||
|
||||
/* Set location 0 */
|
||||
GPIO->ROUTELOC0 = GPIO_ROUTELOC0_SWVLOC_LOC0;
|
||||
|
||||
/* Enable output on pin - GPIO Port F, Pin 2 */
|
||||
GPIO->P[5].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK);
|
||||
GPIO->P[5].MODEL |= GPIO_P_MODEL_MODE2_PUSHPULL;
|
||||
|
||||
/* Enable debug clock AUXHFRCO */
|
||||
CMU_OscillatorEnable(cmuOsc_AUXHFRCO, true, true);
|
||||
CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
|
||||
|
||||
/* Wait until clock is ready */
|
||||
while (!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY));
|
||||
|
||||
/* Enable trace in core debug */
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
ITM->LAR = 0xC5ACCE55;
|
||||
ITM->TER = 0x0;
|
||||
ITM->TCR = 0x0;
|
||||
TPI->SPPR = 2;
|
||||
TPI->ACPR = 0x15; // changed from 0x0F on Giant, etc. to account for 19 MHz default AUXHFRCO frequency
|
||||
ITM->TPR = 0x0;
|
||||
DWT->CTRL = 0x400003FE;
|
||||
ITM->TCR = 0x0001000D;
|
||||
TPI->FFCR = 0x00000100;
|
||||
ITM->TER = 0x1;
|
||||
}
|
||||
|
||||
|
||||
void printing_init()
|
||||
{
|
||||
setupSWOForPrint();
|
||||
}
|
||||
#else
|
||||
|
||||
int RETARGET_WriteChar(char c)
|
||||
{
|
||||
USART_Tx(USART0,c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RETARGET_ReadChar(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void printing_init()
|
||||
{
|
||||
#ifdef USING_DEV_BOARD
|
||||
// GPIO_PinModeSet(gpioPortA,5,gpioModePushPull,1); // VCOM enable
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
475
targets/efm32/src/retargetio.c
Normal file
475
targets/efm32/src/retargetio.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/***************************************************************************//**
|
||||
* @file
|
||||
* @brief Provide stdio retargeting for all supported toolchains.
|
||||
* @version 5.5.0
|
||||
*******************************************************************************
|
||||
* # License
|
||||
* <b>Copyright 2015 Silicon Labs, Inc. http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* This file is licensed under the Silabs License Agreement. See the file
|
||||
* "Silabs_License_Agreement.txt" for details. Before using this software for
|
||||
* any purpose, you must agree to the terms of that agreement.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup RetargetIo
|
||||
* @{ This module provide low-level stubs for retargetting stdio for all
|
||||
* supported toolchains.
|
||||
* The stubs are minimal yet sufficient implementations.
|
||||
* Refer to chapter 12 in the reference manual for newlib 1.17.0
|
||||
* for details on implementing newlib stubs.
|
||||
******************************************************************************/
|
||||
|
||||
extern int RETARGET_ReadChar(void);
|
||||
extern int RETARGET_WriteChar(char c);
|
||||
|
||||
#if !defined(__CROSSWORKS_ARM) && defined(__GNUC__)
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "em_device.h"
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
int fileno(FILE *);
|
||||
/** @endcond */
|
||||
|
||||
int _close(int file);
|
||||
int _fstat(int file, struct stat *st);
|
||||
int _isatty(int file);
|
||||
int _lseek(int file, int ptr, int dir);
|
||||
int _read(int file, char *ptr, int len);
|
||||
caddr_t _sbrk(int incr);
|
||||
int _write(int file, const char *ptr, int len);
|
||||
|
||||
extern char _end; /**< Defined by the linker */
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Close a file.
|
||||
*
|
||||
* @param[in] file
|
||||
* File you want to close.
|
||||
*
|
||||
* @return
|
||||
* Returns 0 when the file is closed.
|
||||
*****************************************************************************/
|
||||
int _close(int file)
|
||||
{
|
||||
(void) file;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief Exit the program.
|
||||
* @param[in] status The value to return to the parent process as the
|
||||
* exit status (not used).
|
||||
*****************************************************************************/
|
||||
void _exit(int status)
|
||||
{
|
||||
(void) status;
|
||||
while (1) {
|
||||
} /* Hang here forever... */
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Status of an open file.
|
||||
*
|
||||
* @param[in] file
|
||||
* Check status for this file.
|
||||
*
|
||||
* @param[in] st
|
||||
* Status information.
|
||||
*
|
||||
* @return
|
||||
* Returns 0 when st_mode is set to character special.
|
||||
*****************************************************************************/
|
||||
int _fstat(int file, struct stat *st)
|
||||
{
|
||||
(void) file;
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief Get process ID.
|
||||
*****************************************************************************/
|
||||
int _getpid(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Query whether output stream is a terminal.
|
||||
*
|
||||
* @param[in] file
|
||||
* Descriptor for the file.
|
||||
*
|
||||
* @return
|
||||
* Returns 1 when query is done.
|
||||
*****************************************************************************/
|
||||
int _isatty(int file)
|
||||
{
|
||||
(void) file;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief Send signal to process.
|
||||
* @param[in] pid Process id (not used).
|
||||
* @param[in] sig Signal to send (not used).
|
||||
*****************************************************************************/
|
||||
int _kill(int pid, int sig)
|
||||
{
|
||||
(void)pid;
|
||||
(void)sig;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Set position in a file.
|
||||
*
|
||||
* @param[in] file
|
||||
* Descriptor for the file.
|
||||
*
|
||||
* @param[in] ptr
|
||||
* Poiter to the argument offset.
|
||||
*
|
||||
* @param[in] dir
|
||||
* Directory whence.
|
||||
*
|
||||
* @return
|
||||
* Returns 0 when position is set.
|
||||
*****************************************************************************/
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
(void) file;
|
||||
(void) ptr;
|
||||
(void) dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Read from a file.
|
||||
*
|
||||
* @param[in] file
|
||||
* Descriptor for the file you want to read from.
|
||||
*
|
||||
* @param[in] ptr
|
||||
* Pointer to the chacaters that are beeing read.
|
||||
*
|
||||
* @param[in] len
|
||||
* Number of characters to be read.
|
||||
*
|
||||
* @return
|
||||
* Number of characters that have been read.
|
||||
*****************************************************************************/
|
||||
int _read(int file, char *ptr, int len)
|
||||
{
|
||||
int c, rxCount = 0;
|
||||
|
||||
(void) file;
|
||||
|
||||
while (len--) {
|
||||
if ((c = RETARGET_ReadChar()) != -1) {
|
||||
*ptr++ = c;
|
||||
rxCount++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rxCount <= 0) {
|
||||
return -1; /* Error exit */
|
||||
}
|
||||
|
||||
return rxCount;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Increase heap.
|
||||
*
|
||||
* @param[in] incr
|
||||
* Number of bytes you want increment the program's data space.
|
||||
*
|
||||
* @return
|
||||
* Rsturns a pointer to the start of the new area.
|
||||
*****************************************************************************/
|
||||
caddr_t _sbrk(int incr)
|
||||
{
|
||||
static char *heap_end;
|
||||
char *prev_heap_end;
|
||||
|
||||
if (heap_end == 0) {
|
||||
heap_end = &_end;
|
||||
}
|
||||
|
||||
prev_heap_end = heap_end;
|
||||
heap_end += incr;
|
||||
|
||||
return (caddr_t) prev_heap_end;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Write to a file.
|
||||
*
|
||||
* @param[in] file
|
||||
* Descriptor for the file you want to write to.
|
||||
*
|
||||
* @param[in] ptr
|
||||
* Pointer to the text you want to write
|
||||
*
|
||||
* @param[in] len
|
||||
* Number of characters to be written.
|
||||
*
|
||||
* @return
|
||||
* Number of characters that have been written.
|
||||
*****************************************************************************/
|
||||
int _write(int file, const char *ptr, int len)
|
||||
{
|
||||
int txCount;
|
||||
|
||||
(void) file;
|
||||
|
||||
for (txCount = 0; txCount < len; txCount++) {
|
||||
RETARGET_WriteChar(*ptr++);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif /* !defined( __CROSSWORKS_ARM ) && defined( __GNUC__ ) */
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
/*******************
|
||||
*
|
||||
* Copyright 1998-2003 IAR Systems. All rights reserved.
|
||||
*
|
||||
* $Revision: 38614 $
|
||||
*
|
||||
* This is a template implementation of the "__write" function used by
|
||||
* the standard library. Replace it with a system-specific
|
||||
* implementation.
|
||||
*
|
||||
* The "__write" function should output "size" number of bytes from
|
||||
* "buffer" in some application-specific way. It should return the
|
||||
* number of characters written, or _LLIO_ERROR on failure.
|
||||
*
|
||||
* If "buffer" is zero then __write should perform flushing of
|
||||
* internal buffers, if any. In this case "handle" can be -1 to
|
||||
* indicate that all handles should be flushed.
|
||||
*
|
||||
* The template implementation below assumes that the application
|
||||
* provides the function "MyLowLevelPutchar". It should return the
|
||||
* character written, or -1 on failure.
|
||||
*
|
||||
********************/
|
||||
|
||||
#include <yfuns.h>
|
||||
#include <stdint.h>
|
||||
#include "em_common.h"
|
||||
|
||||
_STD_BEGIN
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief Transmit buffer to USART1
|
||||
* @param buffer Array of characters to send
|
||||
* @param nbytes Number of bytes to transmit
|
||||
* @return Number of bytes sent
|
||||
*****************************************************************************/
|
||||
static int TxBuf(uint8_t *buffer, int nbytes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
RETARGET_WriteChar(*buffer++);
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the __write implementation uses internal buffering, uncomment
|
||||
* the following line to ensure that we are called with "buffer" as 0
|
||||
* (i.e. flush) when the application terminates.
|
||||
*/
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size)
|
||||
{
|
||||
/* Remove the #if #endif pair to enable the implementation */
|
||||
|
||||
size_t nChars = 0;
|
||||
|
||||
if (buffer == 0) {
|
||||
/*
|
||||
* This means that we should flush internal buffers. Since we
|
||||
* don't we just return. (Remember, "handle" == -1 means that all
|
||||
* handles should be flushed.)
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This template only writes to "standard out" and "standard err",
|
||||
* for all other file handles it returns failure. */
|
||||
if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) {
|
||||
return _LLIO_ERROR;
|
||||
}
|
||||
|
||||
/* Hook into USART1 transmit function here */
|
||||
if (TxBuf((uint8_t *) buffer, size) != size) {
|
||||
return _LLIO_ERROR;
|
||||
} else {
|
||||
nChars = size;
|
||||
}
|
||||
|
||||
return nChars;
|
||||
}
|
||||
|
||||
size_t __read(int handle, unsigned char * buffer, size_t size)
|
||||
{
|
||||
/* Remove the #if #endif pair to enable the implementation */
|
||||
int nChars = 0;
|
||||
|
||||
/* This template only reads from "standard in", for all other file
|
||||
* handles it returns failure. */
|
||||
if (handle != _LLIO_STDIN) {
|
||||
return _LLIO_ERROR;
|
||||
}
|
||||
|
||||
for (/* Empty */; size > 0; --size) {
|
||||
int c = RETARGET_ReadChar();
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
*buffer++ = c;
|
||||
++nChars;
|
||||
}
|
||||
|
||||
return nChars;
|
||||
}
|
||||
|
||||
_STD_END
|
||||
|
||||
#endif /* defined( __ICCARM__ ) */
|
||||
|
||||
#if defined(__CROSSWORKS_ARM)
|
||||
|
||||
/* Pass each of these function straight to the USART */
|
||||
int __putchar(int ch)
|
||||
{
|
||||
return(RETARGET_WriteChar(ch));
|
||||
}
|
||||
|
||||
int __getchar(void)
|
||||
{
|
||||
return(RETARGET_ReadChar());
|
||||
}
|
||||
|
||||
#endif /* defined( __CROSSWORKS_ARM ) */
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
/******************************************************************************/
|
||||
/* RETARGET.C: 'Retarget' layer for target-dependent low level functions */
|
||||
/******************************************************************************/
|
||||
/* This file is part of the uVision/ARM development tools. */
|
||||
/* Copyright (c) 2005-2006 Keil Software. All rights reserved. */
|
||||
/* This software may only be used under the terms of a valid, current, */
|
||||
/* end user licence from KEIL for a compatible version of KEIL software */
|
||||
/* development tools. Nothing else gives you the right to use this software. */
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* #pragma import(__use_no_semihosting_swi) */
|
||||
|
||||
struct __FILE{
|
||||
int handle;
|
||||
};
|
||||
|
||||
/**Standard output stream*/
|
||||
FILE __stdout;
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Writes character to file
|
||||
*
|
||||
* @param[in] f
|
||||
* File
|
||||
*
|
||||
* @param[in] ch
|
||||
* Character
|
||||
*
|
||||
* @return
|
||||
* Written character
|
||||
*****************************************************************************/
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
return(RETARGET_WriteChar(ch));
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Reads character from file
|
||||
*
|
||||
* @param[in] f
|
||||
* File
|
||||
*
|
||||
* @return
|
||||
* Character
|
||||
*****************************************************************************/
|
||||
int fgetc(FILE *f)
|
||||
{
|
||||
return(RETARGET_ReadChar());
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Tests the error indicator for the stream pointed
|
||||
* to by file
|
||||
*
|
||||
* @param[in] f
|
||||
* File
|
||||
*
|
||||
* @return
|
||||
* Returns non-zero if it is set
|
||||
*****************************************************************************/
|
||||
int ferror(FILE *f)
|
||||
{
|
||||
/* Your implementation of ferror */
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Writes a character to the console
|
||||
*
|
||||
* @param[in] ch
|
||||
* Character
|
||||
*****************************************************************************/
|
||||
void _ttywrch(int ch)
|
||||
{
|
||||
RETARGET_WriteChar(ch);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Library exit function. This function is called if stack
|
||||
* overflow occurs.
|
||||
*
|
||||
* @param[in] return_code
|
||||
* Return code
|
||||
*****************************************************************************/
|
||||
void _sys_exit(int return_code)
|
||||
{
|
||||
label: goto label;/* endless loop */
|
||||
}
|
||||
#endif /* defined( __CC_ARM ) */
|
||||
|
||||
/** @} (end group RetargetIo) */
|
Reference in New Issue
Block a user