Explorar o código

*** EFM32 branch ***
1. Add EFM32 development kit support
2. Add USART sync mode (SPI) support
3. Add SPI Flash device (ST M25PX16) driver and demo application

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1401 bbd45198-f89e-11dd-88c7-29a3b14d5316

onelife.real %!s(int64=14) %!d(string=hai) anos
pai
achega
169c31fc4f

+ 62 - 0
bsp/efm32/EFM32_Gxxx_DK/dvk.c

@@ -0,0 +1,62 @@
+/**************************************************************************//**
+ * @file
+ * @brief DVK board support package, initialization
+ * @author Energy Micro AS
+ * @version 1.6.0
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
+ ******************************************************************************
+ *
+ * This source code is the property of Energy Micro AS. The source and compiled
+ * code may only be used on Energy Micro "EFM32" microcontrollers.
+ *
+ * This copyright notice may not be removed from the source code nor changed.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
+ * obligation to support this Software. Energy Micro AS is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Energy Micro AS will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ *****************************************************************************/
+
+#include "efm32.h"
+#include "dvk.h"
+
+/**************************************************************************//**
+ * @brief  Initializes DVK, configures board control access
+ *****************************************************************************/
+void DVK_init(void)
+{
+#ifdef DVK_EBI_CONTROL
+  DVK_EBI_init();
+#endif
+#ifdef DVK_SPI_CONTROL
+  DVK_SPI_init();
+#endif
+  /* Inform AEM application that we are in Energy Mode 0 by default */
+  DVK_setEnergyMode(0);
+}
+
+/**************************************************************************//**
+ * @brief  Disables DVK, free up resources
+ *****************************************************************************/
+void DVK_disable(void)
+{
+#ifdef DVK_EBI_CONTROL
+  /* Handover bus control */
+  DVK_disableBus();
+  /* Disable EBI interface */
+  DVK_EBI_disable();
+#endif
+
+#ifdef DVK_SPI_CONTROL
+  DVK_SPI_disable();
+#endif
+}

+ 125 - 0
bsp/efm32/EFM32_Gxxx_DK/dvk.h

@@ -0,0 +1,125 @@
+/**************************************************************************//**
+ * @file
+ * @brief DVK Board Support, master header file
+ * @author Energy Micro AS
+ * @version 1.6.0
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
+ ******************************************************************************
+ *
+ * This source code is the property of Energy Micro AS. The source and compiled
+ * code may only be used on Energy Micro "EFM32" microcontrollers.
+ *
+ * This copyright notice may not be removed from the source code nor changed.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
+ * obligation to support this Software. Energy Micro AS is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Energy Micro AS will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ *****************************************************************************/
+
+#ifndef __DVK_H
+#define __DVK_H
+
+#include <stdint.h>
+#include "dvk_boardcontrol.h"
+#include "dvk_bcregisters.h"
+
+/* onelife: Add missing define */
+#define NULL ((void *)0)
+
+/* IF not user overrides default, try to decide DVK access interface based on
+ * part number */
+#ifndef DVK_SPI_CONTROL
+#ifndef DVK_EBI_CONTROL
+
+#if defined(EFM32G200F16)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G200F32)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G200F64)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G210F128)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G230F128)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G230F32)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G230F64)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G280F128)
+#define DVK_EBI_CONTROL
+#elif defined(EFM32G280F32)
+#define DVK_EBI_CONTROL
+#elif defined(EFM32G280F64)
+#define DVK_EBI_CONTROL
+#elif defined(EFM32G290F128)
+#define DVK_EBI_CONTROL
+#elif defined(EFM32G290F32)
+#define DVK_EBI_CONTROL
+#elif defined(EFM32G290F64)
+#define DVK_EBI_CONTROL
+#elif defined(EFM32G840F128)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G840F32)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G840F64)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G880F128)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G880F32)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G880F64)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G890F128)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G890F32)
+#define DVK_SPI_CONTROL
+#elif defined(EFM32G890F64)
+#define DVK_SPI_CONTROL
+#else
+#define DVK_SPI_CONTROL
+#endif
+
+#endif
+#endif
+
+/* EBI access */
+void DVK_EBI_init(void);
+void DVK_EBI_disable(void);
+
+void DVK_EBI_writeRegister(volatile uint16_t *addr, uint16_t data);
+uint16_t DVK_EBI_readRegister(volatile uint16_t *addr);
+
+/* SPI access */
+void DVK_SPI_init(void);
+void DVK_SPI_disable(void);
+
+void DVK_SPI_writeRegister(volatile uint16_t *addr, uint16_t data);
+uint16_t DVK_SPI_readRegister(volatile uint16_t *addr);
+
+
+/* Accodring to configuration, use either SPI or EBI */
+#ifdef DVK_EBI_CONTROL
+#define DVK_writeRegister(A, B)    DVK_EBI_writeRegister(A, B)
+#define DVK_readRegister(A)        DVK_EBI_readRegister(A)
+#endif
+
+#ifdef DVK_SPI_CONTROL
+#define DVK_writeRegister(A, B)    DVK_SPI_writeRegister(A, B)
+#define DVK_readRegister(A)        DVK_SPI_readRegister(A)
+#endif
+
+/* General initialization routines */
+void DVK_init(void);
+void DVK_disable(void);
+
+#endif

+ 174 - 0
bsp/efm32/EFM32_Gxxx_DK/dvk_bcregisters.h

@@ -0,0 +1,174 @@
+/**************************************************************************//**
+ * @file
+ * @brief Board Control register definitions
+ * @author Energy Micro AS
+ * @version 1.6.0
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
+ ******************************************************************************
+ *
+ * This source code is the property of Energy Micro AS. The source and compiled
+ * code may only be used on Energy Micro "EFM32" microcontrollers.
+ *
+ * This copyright notice may not be removed from the source code nor changed.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
+ * obligation to support this Software. Energy Micro AS is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Energy Micro AS will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ *****************************************************************************/
+
+#ifndef __DVK_BCREGISTERS_H
+#define __DVK_BCREGISTERS_H
+
+#include <stdint.h>
+
+/**************************************************************************//**
+ * Defines FPGA register bank for Energy Micro Development Kit (DVK) board,
+ * i.e. board control registers
+ *****************************************************************************/
+#define BC_FLASH_BASE        0x80000000 /**< FLASH memory base address */
+#define BC_SRAM_BASE         0x84000000 /**< SRAM base address */
+#define BC_SSD2119_BASE      0x88000000 /**< TFT Controller base address */
+#define BC_REGISTER_BASE     0x8c000000 /**< Board Controller registers base address */
+
+#define BC_CFG               ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x00)) /**< CFG */
+#define BC_EM                ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x01)) /**< EM */
+#define BC_MAGIC             ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x02)) /**< MAGIC */
+#define BC_LED               ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x03)) /**< LEDs */
+#define BC_PUSHBUTTON        ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x04)) /**< Push Buttons */
+#define BC_DIPSWITCH         ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x05)) /**< Dip switches */
+#define BC_JOYSTICK          ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x06)) /**< Joystick */
+#define BC_AEM               ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x07)) /**< AEM push button status */
+#define BC_DISPLAY_CTRL      ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x08)) /**< Display Control */
+#define BC_EBI_CFG           ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x09)) /**< EBI config */
+#define BC_BUS_CFG           ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x0a)) /**< BUS config */
+#define BC_PERCTRL           ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x0c)) /**< Peripheral Control */
+#define BC_AEMSTATE          ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x0d)) /**< AEM state of push button switch */
+#define BC_SPI_CFG           ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x0e)) /**< SPI config */
+#define BC_RESET             ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x0f)) /**< Reset */
+#define BC_ADC_START         ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x10)) /**< ADC start */
+#define BC_ADC_STATUS        ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x11)) /**< ADC status */
+#define BC_ADC_DATA          ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x12)) /**< ADC data */
+#define BC_HW_VERSION        ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x14)) /**< HW version */
+#define BC_FW_BUILDNO        ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x15)) /**< FW build number */
+#define BC_FW_VERSION        ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x16)) /**< FW version */
+#define BC_SCRATCH_COMMON    ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x17)) /**< Scratch common */ 
+#define BC_SCRATCH_EFM0      ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x18)) /**< Scratch EFM0 */
+#define BC_SCRATCH_EFM1      ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x19)) /**< Scratch EFM1 */
+#define BC_SCRATCH_EFM2      ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x1A)) /**< Scratch EFM2 */
+#define BC_SCRATCH_EFM3      ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x1B)) /**< Scratch EFM3 */
+#define BC_SCRATCH_BC0       ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x1C)) /**< Scratch BC0 */
+#define BC_SCRATCH_BC1       ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x1D)) /**< Scratch BC1 */
+#define BC_SCRATCH_BC2       ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x1E)) /**< Scratch BC2 */
+#define BC_SCRATCH_BC3       ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x1f)) /**< Scratch BC3 */
+#define BC_INTFLAG           ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x20)) /**< Interrupt flag */
+#define BC_INTEN             ((volatile uint16_t *)(BC_REGISTER_BASE + sizeof(uint16_t) * 0x21)) /**< Interrupt enable */
+
+/**************************************************************************//**
+ * Defines bit fields for board control registers
+ *****************************************************************************/
+
+#define BC_CFG_SPI                           (0) /**< SPI mode */
+#define BC_CFG_EBI                           (1) /**< EBI mode */
+
+#define BC_EM_EM0                            (0) /**< Indicate EM0 */
+#define BC_EM_EM1                            (1) /**< Indicate EM1 */
+#define BC_EM_EM2                            (2) /**< Indicate EM2 */
+#define BC_EM_EM3                            (3) /**< Indicate EM3 */
+#define BC_EM_EM4                            (4) /**< Indicate EM4 */
+
+#define BC_MAGIC_VALUE                       (0xef32) /**< Magic */
+
+#define BC_PUSHBUTTON_MASK                   (0x000f) /**< Push button mask */
+#define BC_PUSHBUTTON_SW1                    (1 << 0) /**< Push button SW1 */
+#define BC_PUSHBUTTON_SW2                    (1 << 1) /**< Push button SW2 */
+#define BC_PUSHBUTTON_SW3                    (1 << 2) /**< Push button SW3 */
+#define BC_PUSHBUTTON_SW4                    (1 << 3) /**< Push button SW4 */
+
+#define BC_DIPSWITCH_MASK                    (0x00ff) /**< Dip switch mask */
+
+#define BC_JOYSTICK_MASK                     (0x001f) /**< Joystick mask */
+#define BC_JOYSTICK_DOWN                     (1 << 0) /**< Joystick down */
+#define BC_JOYSTICK_RIGHT                    (1 << 1) /**< Joystick right */
+#define BC_JOYSTICK_UP                       (1 << 2) /**< Joystick up */
+#define BC_JOYSTICK_LEFT                     (1 << 3) /**< Joystick left */
+#define BC_JOYSTICK_CENTER                   (1 << 4) /**< Joystick center button */
+
+#define BC_DISPCTRL_RESET                    (1 << 0) /**< Reset */
+#define BC_DISPCTRL_POWER_ENABLE             (1 << 1) /**< Display Control Power Enable */
+
+#define BC_EBI_CFG_MASK                      (0x0003) /**< EBI Config */
+#define BC_EBI_CFG_16X16                     (0) /**< 16x16 address/data mode */
+#define BC_EBI_CFG_8X8                       (1) /**< 8x8 address/data mode */
+#define BC_EBI_CFG_24X8                      (2) /**< 24x8 address/data mode */
+
+#define BC_BUS_CFG_MASK                      (0x0003) /**< Bus config */
+#define BC_BUS_CFG_FSMC                      (0) /**< Kit Board Controller owns bus */
+#define BC_BUS_CFG_EBI                       (1) /**< EBI drives bus */
+#define BC_BUS_CFG_SPI                       (2) /**< SPI drives bus */
+
+#define BC_PERCTRL_ACCEL                     (1 << 0) /**< Accelerometer enable */
+#define BC_PERCTRL_AMBIENT                   (1 << 1) /**< Ambient light sensor enable */
+#define BC_PERCTRL_POTMETER                  (1 << 2) /**< Potentiometer enable */
+#define BC_PERCTRL_RS232A                    (1 << 3) /**< RS232A enable */
+#define BC_PERCTRL_RS232B                    (1 << 4) /**< RS232B enable */
+#define BC_PERCTRL_SPI                       (1 << 5) /**< SPI enable */
+#define BC_PERCTRL_I2C                       (1 << 6) /**< I2C enable */
+#define BC_PERCTRL_IRDA                      (1 << 7) /**< IRDA enable */
+#define BC_PERCTRL_ANALOG_SE                 (1 << 8) /**< Analog SE enable */
+#define BC_PERCTRL_ANALOG_DIFF               (1 << 9) /**< Analog Diff enable */
+#define BC_PERCTRL_AUDIO_OUT                 (1 << 10) /**< Audio Out enable */
+#define BC_PERCTRL_AUDIO_IN                  (1 << 11) /**< Audio In enable */
+#define BC_PERCTRL_ACCEL_GSEL                (1 << 12) /**< Accel Gsel enable */
+#define BC_PERCTRL_ACCEL_SELFTEST            (1 << 13) /**< Accel Self test enable */
+#define BC_PERCTRL_RS232_SHUTDOWN            (1 << 14) /**< RS232 shutdown */
+#define BC_PERCTRL_IRDA_SHUTDOWN             (1 << 15) /**< IRDA shutdown */
+
+#define BC_AEMSTATE_BC                       (0) /**< AEM button state, BC controls buttons */
+#define BC_AEMSTATE_EFM                      (1) /**< AEM button state, EFM32 controls buttons */
+
+#define BC_SPI_CFG_FLASH                     (0) /**< SPI Flash config */
+#define BC_SPI_CFG_MICROSD                   (1) /**< SPI MicroSD config */
+
+#define BC_RESET_FLASH                       (1 << 0) /**< Reset Flash */
+#define BC_RESET_EFM                         (1 << 1) /**< Reset EFM */
+
+#define BC_ADC_START_MASK                    (0x00ff) /**< ADC Start mask */
+
+#define BC_ADC_STATUS_DONE                   (0) /**< ADC Status Done */
+#define BC_ADC_STATUS_BUSY                   (1) /**< ADC Status Busy */
+
+#define BC_HW_VERSION_PCB_MASK               (0x07f0) /**< PCB Version mask */
+#define BC_HW_VERSION_PCB_SHIFT              (4) /**< PCB Version shift */
+#define BC_HW_VERSION_BOARD_MASK             (0x000f) /**< Board version mask */
+#define BC_HW_VERSION_BOARD_SHIFT            (0) /**< Board version shift  */
+
+#define BC_HW_FW_VERSION_MAJOR_MASK          (0xf000) /**< FW Version major mask */
+#define BC_HW_FW_VERSION_MAJOR_SHIFT         (12) /**< FW version major shift */
+#define BC_HW_FW_VERSION_MINOR_MASK          (0x0f00) /**< FW version minor mask */
+#define BC_HW_FW_VERSION_MINOR_SHIFT         (8) /**< FW version minor shift */
+#define BC_HW_FW_VERSION_PATCHLEVEL_MASK     (0x00ff) /**< FW Patchlevel mask */
+#define BC_HW_FW_VERSION_PATCHLEVEL_SHIFT    (0) /**< FW Patchlevel shift */
+
+#define BC_INTEN_MASK                        (0x000f) /**< Interrupt enable mask */
+#define BC_INTEN_PB                          (1 << 0) /**< Push Button Interrupt enable */
+#define BC_INTEN_DIP                         (1 << 1) /**< DIP Switch Interrupt enable */
+#define BC_INTEN_JOYSTICK                    (1 << 2) /**< Joystick Interrupt enable */
+#define BC_INTEN_AEM                         (1 << 3) /**< AEM Interrupt enable */
+
+#define BC_INTFLAG_MASK                      (0x000f) /**< Interrupt flag mask */
+#define BC_INTFLAG_PB                        (1 << 0) /**< Push Button interrupt triggered */
+#define BC_INTFLAG_DIP                       (1 << 1) /**< DIP interrupt triggered */
+#define BC_INTFLAG_JOYSTICK                  (1 << 2) /**< Joystick interrupt triggered */
+#define BC_INTFLAG_AEM                       (1 << 3) /**< AEM interrupt triggered */
+
+#endif

+ 248 - 0
bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.c

@@ -0,0 +1,248 @@
+/**************************************************************************//**
+ * @file
+ * @brief DVK Peripheral Board Control API implementation
+ * @author Energy Micro AS
+ * @version 1.6.0
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
+ ******************************************************************************
+ *
+ * This source code is the property of Energy Micro AS. The source and compiled
+ * code may only be used on Energy Micro "EFM32" microcontrollers.
+ *
+ * This copyright notice may not be removed from the source code nor changed.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
+ * obligation to support this Software. Energy Micro AS is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Energy Micro AS will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ *****************************************************************************/
+
+#include "efm32.h"
+#include "dvk.h"
+#include "dvk_boardcontrol.h"
+#include "dvk_bcregisters.h"
+
+/**************************************************************************//**
+ * @brief Enable EFM32 access to periheral on DVK board
+ * @param peri Peripheral to enable
+ *****************************************************************************/
+void DVK_enablePeripheral(DVKPeripheral peri)
+{
+  uint16_t bit;
+  uint16_t tmp;
+
+  /* Calculate which bit to set */
+  bit = (uint16_t) peri;
+
+  /* Read peripheral control register */
+  tmp = DVK_readRegister(BC_PERCTRL);
+
+  /* Enable peripheral */
+  tmp |= bit;
+
+  /* Special case for RS232, if enabled disable shutdown */
+  if ((peri == DVK_RS232A) || (peri == DVK_RS232B))
+  {
+    /* clear shutdown bit */
+    tmp &= ~(BC_PERCTRL_RS232_SHUTDOWN);
+  }
+
+  /* Special case for IRDA if enabled disable shutdown */
+  if (peri == DVK_IRDA)
+  {
+    /* clear shutdown bit */
+    tmp &= ~(BC_PERCTRL_IRDA_SHUTDOWN);
+  }
+
+  DVK_writeRegister(BC_PERCTRL, tmp);
+}
+
+/**************************************************************************//**
+ * @brief Disable EFM32 access to peripheral on DVK board
+ * @param peri Peripheral to disable
+ *****************************************************************************/
+void DVK_disablePeripheral(DVKPeripheral peri)
+{
+  uint16_t bit;
+  uint16_t tmp;
+
+  /* Calculate which bit to set */
+  bit = (uint16_t) peri;
+
+  /* Read peripheral control register */
+  tmp = DVK_readRegister(BC_PERCTRL);
+
+  /* Disable peripheral */
+  tmp &= ~(bit);
+
+  /* Special case for RS232, if enabled disable shutdown */
+  if ((peri == DVK_RS232A) || (peri == DVK_RS232B))
+  {
+    /* Set shutdown bit */
+    tmp |= (BC_PERCTRL_RS232_SHUTDOWN);
+  }
+
+  /* Special case for IRDA */
+  if (peri == DVK_IRDA)
+  {
+    /* Set shutdown bit */
+    tmp |= (BC_PERCTRL_IRDA_SHUTDOWN);
+  }
+
+  DVK_writeRegister(BC_PERCTRL, tmp);
+}
+
+
+/**************************************************************************//**
+ * @brief Enable BUS access
+ *****************************************************************************/
+void DVK_enableBus(void)
+{
+  /* Enable bus access */
+  DVK_writeRegister(BC_BUS_CFG, 1);
+}
+
+
+/**************************************************************************//**
+ * @brief Disable BUS access
+ *****************************************************************************/
+void DVK_disableBus(void)
+{
+  DVK_writeRegister(BC_BUS_CFG, 0);
+}
+
+
+/**************************************************************************//**
+ * @brief Inform AEM about current energy mode
+ * @param energyMode What energy mode we are going to use next
+ *****************************************************************************/
+void DVK_setEnergyMode(uint16_t energyMode)
+{
+  DVK_writeRegister(BC_EM, energyMode);
+}
+
+
+/**************************************************************************//**
+ * @brief Get status of bush buttons
+ * @return Status of push buttons
+ *****************************************************************************/
+uint16_t DVK_getPushButtons(void)
+{
+  uint16_t pb = 0;
+  uint16_t aemState;
+
+  /* Check state */
+  aemState = DVK_readRegister(BC_AEMSTATE);
+  /* Read pushbutton status */
+  if ( aemState == BC_AEMSTATE_EFM ) 
+  {
+    pb = (~(DVK_readRegister(BC_PUSHBUTTON))) & 0x000f;
+  }
+  return pb;
+}
+
+/**************************************************************************//**
+ * @brief Get joystick button status
+ * @return Joystick controller status
+ *****************************************************************************/
+uint16_t DVK_getJoystick(void)
+{
+  uint16_t joyStick = 0;
+  uint16_t aemState;
+
+  /* Check state */
+  aemState = DVK_readRegister(BC_AEMSTATE);
+  /* Read pushbutton status */
+  if ( aemState == BC_AEMSTATE_EFM ) 
+  {
+    joyStick = (~(DVK_readRegister(BC_JOYSTICK))) & 0x001f;
+  }
+  return joyStick;
+}
+
+/**************************************************************************//**
+ * @brief Get dipswitch status
+ *        The DIP switches are free for user programmable purposes
+ * @return Joystick controller status
+ *****************************************************************************/
+uint16_t DVK_getDipSwitch(void)
+{
+  uint16_t tmp;
+
+  tmp = (~(DVK_readRegister(BC_DIPSWITCH))) & 0x00ff;
+  return tmp;
+}
+
+/**************************************************************************//**
+ * @brief Sets user leds
+ * @param leds 16-bits which enables or disables the board "User leds"
+ *****************************************************************************/
+void DVK_setLEDs(uint16_t leds)
+{
+  DVK_writeRegister(BC_LED, leds);
+}
+
+/**************************************************************************//**
+ * @brief Get status of user LEDs
+ * @return Status of 16 user leds, bit 1 = on, bit 0 = off
+ *****************************************************************************/
+uint16_t DVK_getLEDs(void)
+{
+  return DVK_readRegister(BC_LED);
+}
+
+/**************************************************************************//**
+ * @brief Enable "Control" buttons/joystick/dip switch interrupts
+ * @param flags Board control interrupt flags, BC_INTEN_<something>
+ *****************************************************************************/
+void DVK_enableInterrupt(uint16_t flags)
+{
+  uint16_t tmp;
+
+  /* Add flags to interrupt enable register */
+  tmp  = DVK_readRegister(BC_INTEN);
+  tmp |= flags;
+  DVK_writeRegister(BC_INTEN, tmp);
+}
+
+/**************************************************************************//**
+ * @brief Disable "Control" buttons/joystick/dip switch interrupts
+ * @param flags Board control interrupt flags, BC_INTEN_<something>
+ *****************************************************************************/
+void DVK_disableInterrupt(uint16_t flags)
+{
+  uint16_t tmp;
+
+  /* Clear flags from interrupt enable register */
+  tmp   = DVK_readRegister(BC_INTEN);
+  flags = ~(flags);
+  tmp  &= flags;
+  DVK_writeRegister(BC_INTEN, tmp);
+}
+
+/**************************************************************************//**
+ * @brief Clear interrupts
+ * @param flags Board control interrupt flags, BC_INTEN_<something>
+ *****************************************************************************/
+void DVK_clearInterruptFlags(uint16_t flags)
+{
+  DVK_writeRegister(BC_INTFLAG, flags);
+}
+
+/**************************************************************************//**
+ * @brief Read interrupt flags
+ * @return Returns currently triggered interrupts
+ *****************************************************************************/
+uint16_t DVK_getInterruptFlags(void)
+{
+  return DVK_readRegister(BC_INTFLAG);
+}

+ 81 - 0
bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.h

@@ -0,0 +1,81 @@
+/**************************************************************************//**
+ * @file
+ * @brief DVK Peripheral Board Control, prototypes and definitions
+ * @author Energy Micro AS
+ * @version 1.6.0
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
+ ******************************************************************************
+ *
+ * This source code is the property of Energy Micro AS. The source and compiled
+ * code may only be used on Energy Micro "EFM32" microcontrollers.
+ *
+ * This copyright notice may not be removed from the source code nor changed.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
+ * obligation to support this Software. Energy Micro AS is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Energy Micro AS will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ *****************************************************************************/
+
+#ifndef __DVK_BOARDCONTROL_H
+#define __DVK_BOARDCONTROL_H
+
+#include <stdint.h>
+#include "dvk_bcregisters.h"
+
+/** Periperhal access switches */
+typedef enum
+{
+  DVK_ACCEL          = BC_PERCTRL_ACCEL,
+  DVK_AMBIENT        = BC_PERCTRL_AMBIENT,
+  DVK_POTMETER       = BC_PERCTRL_POTMETER,
+  DVK_RS232A         = BC_PERCTRL_RS232A,
+  DVK_RS232B         = BC_PERCTRL_RS232B,
+  DVK_SPI            = BC_PERCTRL_SPI,
+  DVK_I2C            = BC_PERCTRL_I2C,
+  DVK_IRDA           = BC_PERCTRL_IRDA,
+  DVK_ANALOG_SE      = BC_PERCTRL_ANALOG_SE,
+  DVK_ANALOG_DIFF    = BC_PERCTRL_ANALOG_DIFF,
+  DVK_AUDIO_OUT      = BC_PERCTRL_AUDIO_OUT,
+  DVK_AUDIO_IN       = BC_PERCTRL_AUDIO_IN,
+  DVK_ACCEL_GSEL     = BC_PERCTRL_ACCEL_GSEL,
+  DVK_ACCEL_SELFTEST = BC_PERCTRL_ACCEL_SELFTEST,
+  DVK_RS232_SHUTDOWN = BC_PERCTRL_RS232_SHUTDOWN,
+  DVK_IRDA_SHUTDOWN  = BC_PERCTRL_IRDA_SHUTDOWN
+} DVKPeripheral;
+
+/* Peripheral Control */
+void DVK_enablePeripheral(DVKPeripheral peri);
+void DVK_disablePeripheral(DVKPeripheral peri);
+void DVK_enableBus(void);
+void DVK_disableBus(void);
+
+/* Read board controllers */
+uint16_t DVK_getPushButtons(void);
+uint16_t DVK_getJoystick(void);
+uint16_t DVK_getDipSwitch(void);
+
+/* Report AEM status */
+void DVK_setEnergyMode(uint16_t energyMode);
+
+/* User LEDs */
+void DVK_setLEDs(uint16_t leds);
+uint16_t DVK_getLEDs(void);
+
+/* Interrupt callback */
+void DVK_enableInterrupt(uint16_t flags);
+void DVK_disableInterrupt(uint16_t flags);
+
+uint16_t DVK_getInterruptFlags(void);
+void DVK_clearInterruptFlags(uint16_t flags);
+
+#endif

+ 237 - 0
bsp/efm32/EFM32_Gxxx_DK/dvk_ebi.c

@@ -0,0 +1,237 @@
+/**************************************************************************//**
+ * @file
+ * @brief EBI implementation of Board Control interface
+ *        This implementation works for devices w/o LCD display on the
+ *        MCU module, specifically the EFM32_G2xx_DK development board
+ * @author Energy Micro AS
+ * @version 1.6.0
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
+ ******************************************************************************
+ *
+ * This source code is the property of Energy Micro AS. The source and compiled
+ * code may only be used on Energy Micro "EFM32" microcontrollers.
+ *
+ * This copyright notice may not be removed from the source code nor changed.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
+ * obligation to support this Software. Energy Micro AS is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Energy Micro AS will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ *****************************************************************************/
+#include "efm32.h"
+#include "efm32_ebi.h"
+#include "efm32_cmu.h"
+#include "efm32_gpio.h"
+#include "dvk.h"
+#include "dvk_bcregisters.h"
+
+
+/**************************************************************************//**
+ * @brief Configure EBI (external bus interface) for Board Control register
+ * access
+ *****************************************************************************/
+void DVK_EBI_configure(void)
+{
+  EBI_Init_TypeDef ebiConfig = EBI_INIT_DEFAULT;
+
+  /* Run time check if we have EBI on-chip capability on this device */
+  switch ((DEVINFO->PART & _DEVINFO_PART_DEVICE_NUMBER_MASK) >>
+          _DEVINFO_PART_DEVICE_NUMBER_SHIFT)
+  {
+  /* Only device types EFM32G 280/290/880 and 890 have EBI capability */
+  case 280:
+  case 290:
+  case 880:
+  case 890:
+    break;
+  default:
+    /* This device do not have EBI capability - use SPI to interface DVK */
+    /* With high probability your project has been configured for an */
+    /* incorrect part number. */
+    while (1) ;
+  }
+
+  /* Enable clocks */
+  CMU_ClockEnable(cmuClock_EBI, true);
+  CMU_ClockEnable(cmuClock_GPIO, true);
+
+  /* Configure bus connect PC bit 12 active low */
+  GPIO_PinModeSet(gpioPortC, 12, gpioModePushPull, 0);
+
+  /* Configure GPIO pins as push pull */
+  /* EBI AD9..15 */
+  GPIO_PinModeSet(gpioPortA, 0, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortA, 1, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortA, 2, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortA, 3, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortA, 4, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortA, 5, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortA, 6, gpioModePushPull, 0);
+
+  /* EBI AD8 */
+  GPIO_PinModeSet(gpioPortA, 15, gpioModePushPull, 0);
+
+  /* EBI CS0-CS3 */
+  GPIO_PinModeSet(gpioPortD, 9, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortD, 10, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortD, 11, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortD, 12, gpioModePushPull, 0);
+
+  /* EBI AD0..7 */
+  GPIO_PinModeSet(gpioPortE, 8, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortE, 9, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortE, 10, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortE, 11, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortE, 12, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortE, 13, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortE, 14, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortE, 15, gpioModePushPull, 0);
+
+  /* EBI ARDY/ALEN/Wen/Ren */
+  GPIO_PinModeSet(gpioPortF, 2, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortF, 3, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortF, 4, gpioModePushPull, 0);
+  GPIO_PinModeSet(gpioPortF, 5, gpioModePushPull, 0);
+
+  /* Configure EBI controller, changing default values */
+  ebiConfig.mode = ebiModeD16A16ALE;
+  /* Enable bank 0 address map 0x80000000, FPGA Flash */
+  /* Enable bank 1 address map 0x84000000, FPGA SRAM */
+  /* Enable bank 2 address map 0x88000000, FPGA TFT Display (SSD2119) */
+  /* Enable bank 3 address map 0x8c000000, FPGA Board Control Registers */
+  ebiConfig.banks = EBI_BANK0|EBI_BANK1|EBI_BANK2|EBI_BANK3;
+  ebiConfig.csLines = EBI_CS0|EBI_CS1|EBI_CS2|EBI_CS3;
+
+  /* Address Setup and hold time */
+  ebiConfig.addrHoldCycles = 3;
+  ebiConfig.addrSetupCycles = 3;
+
+  /* Read cycle times */
+  ebiConfig.readStrobeCycles = 7;
+  ebiConfig.readHoldCycles = 3;
+  ebiConfig.readSetupCycles = 3;
+
+  /* Write cycle times */
+  ebiConfig.writeStrobeCycles = 7;
+  ebiConfig.writeHoldCycles = 3;
+  ebiConfig.writeSetupCycles = 3;
+
+  /* Polarity values are default */
+
+  /* Configure EBI */
+  EBI_Init(&ebiConfig);
+}
+
+
+/**************************************************************************//**
+ * @brief Initialize EBI
+ * access
+ *****************************************************************************/
+void DVK_EBI_init(void)
+{
+  uint16_t     ebiMagic;
+  int          ctr;
+
+  /* Disable all GPIO pins and register  */
+  DVK_EBI_disable();
+  /* Configure EBI */
+  DVK_EBI_configure();
+  /* Verify that EBI access is working, if not kit is in SPI mode and needs to
+   * be configured for EBI access */
+  ebiMagic = DVK_EBI_readRegister(BC_MAGIC);
+  if (ebiMagic != BC_MAGIC_VALUE)
+  {
+    /* Disable EBI */
+    DVK_EBI_disable();
+    /* Enable SPI interface */
+    DVK_SPI_init();
+    /* Set EBI mode - after this SPI access will no longer be available */
+    DVK_SPI_writeRegister(BC_CFG, BC_CFG_EBI);
+    /* Disable SPI */
+    DVK_SPI_disable();
+    /* Now setup EBI again */
+    DVK_EBI_configure();
+    /* Wait until ready */
+    ctr = 0;
+    do
+    {
+      /* Check if FPGA responds */
+      ebiMagic = DVK_EBI_readRegister(BC_MAGIC);
+      ctr++;
+      DVK_EBI_writeRegister(BC_LED, ctr);
+    } while (ebiMagic != BC_MAGIC_VALUE);
+  }
+}
+
+/**************************************************************************//**
+ * @brief Disable EBI interface, free all GPIO pins
+ *****************************************************************************/
+void DVK_EBI_disable(void)
+{
+  /* Disable EBI controller */
+  EBI_Disable();
+
+  /* Disable EBI clock in CMU */
+  CMU_ClockEnable(cmuClock_EBI, false);
+
+  /* Disable EBI _BC_BUS_CONNECT */
+  GPIO_PinModeSet(gpioPortC, 12, gpioModeDisabled, 0);
+
+  /* Configure GPIO pins as disabled */
+  GPIO_PinModeSet(gpioPortA, 0, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortA, 1, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortA, 2, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortA, 3, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortA, 4, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortA, 5, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortA, 6, gpioModeDisabled, 0);
+
+  GPIO_PinModeSet(gpioPortA, 15, gpioModeDisabled, 0);
+
+  GPIO_PinModeSet(gpioPortD, 9, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortD, 10, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortD, 11, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortD, 12, gpioModeDisabled, 0);
+
+  GPIO_PinModeSet(gpioPortE, 8, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortE, 9, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortE, 10, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortE, 11, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortE, 12, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortE, 13, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortE, 14, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortE, 15, gpioModeDisabled, 0);
+
+  GPIO_PinModeSet(gpioPortF, 2, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortF, 3, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortF, 4, gpioModeDisabled, 0);
+  GPIO_PinModeSet(gpioPortF, 5, gpioModeDisabled, 0);
+}
+
+/**************************************************************************//**
+ * @brief Write data into 16-bit board control register
+ * @param addr Address to board control register
+ * @param data Data to write into register
+ *****************************************************************************/
+void DVK_EBI_writeRegister(volatile uint16_t *addr, uint16_t data)
+{
+  *addr = data;
+}
+
+/**************************************************************************//**
+ * @brief Write data into 16-bit board control register
+ * @param addr Register to read from
+ *****************************************************************************/
+uint16_t DVK_EBI_readRegister(volatile uint16_t *addr)
+{
+  return *addr;
+}

+ 230 - 0
bsp/efm32/EFM32_Gxxx_DK/dvk_spi.c

@@ -0,0 +1,230 @@
+/**************************************************************************//**
+ * @file
+ * @brief SPI implementation of Board Control interface
+ *        This implementation use the USART2 SPI interface to control board
+ *        control registers. It works
+ * @author Energy Micro AS
+ * @version 1.6.0
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
+ ******************************************************************************
+ *
+ * This source code is the property of Energy Micro AS. The source and compiled
+ * code may only be used on Energy Micro "EFM32" microcontrollers.
+ *
+ * This copyright notice may not be removed from the source code nor changed.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
+ * obligation to support this Software. Energy Micro AS is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Energy Micro AS will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ *****************************************************************************/
+
+#include <stdio.h>
+#include "efm32.h"
+#include "efm32_usart.h"
+#include "efm32_gpio.h"
+#include "efm32_cmu.h"
+#include "dvk.h"
+#include "dvk_bcregisters.h"
+
+/* USART used for SPI access */
+#define USART_USED                USART2
+#define USART_CLK                 cmuClock_USART2
+
+/* GPIO pins used, please refer to DVK user guide. */
+#define PIN_SPIBUS_CONNECT        13
+#define PORT_SPIBUS_CONNECT       gpioPortC
+#define PIN_SPI_TX                2
+#define PORT_SPI_TX               gpioPortC
+#define PIN_SPI_RX                3
+#define PORT_SPI_RX               gpioPortC
+#define PIN_SPI_CLK               4
+#define PORT_SPI_CLK              gpioPortC
+#define PIN_SPI_CS                5
+#define PORT_SPI_CS               gpioPortC
+
+static volatile uint16_t *lastAddr = NULL;
+
+/**************************************************************************//**
+ * @brief  Initializes SPI interface for access to FPGA registers
+ *         for board control
+ *****************************************************************************/
+static void spiInit(void)
+{
+  USART_InitSync_TypeDef init = USART_INITSYNC_DEFAULT;
+
+  /* Enable module clocks */
+  CMU_ClockEnable(cmuClock_GPIO, true);
+  CMU_ClockEnable(cmuClock_HFPER, true);
+  CMU_ClockEnable(USART_CLK, true);
+
+  /* Configure SPI bus connect pins, DOUT set to 0 */
+  GPIO_PinModeSet(PORT_SPIBUS_CONNECT, PIN_SPIBUS_CONNECT, gpioModePushPull, 0);
+
+  /* Configure SPI pins */
+  GPIO_PinModeSet(PORT_SPI_TX, PIN_SPI_TX, gpioModePushPull, 0);
+  GPIO_PinModeSet(PORT_SPI_RX, PIN_SPI_RX, gpioModePushPull, 0);
+  GPIO_PinModeSet(PORT_SPI_CLK, PIN_SPI_CLK, gpioModePushPull, 0);
+  /* Keep CS high to not activate slave */
+  GPIO_PinModeSet(PORT_SPI_CS, PIN_SPI_CS, gpioModePushPull, 1);
+
+  /* Enable pins at default location */
+  USART_USED->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN;
+
+  /* Reset USART just in case */
+  USART_Reset(USART_USED);
+
+  /* Configure to use SPI master with manual CS */
+  /* For now, configure SPI for worst case 32MHz clock in order to work for all */
+  /* configurations. */
+  init.refFreq = 32000000;
+  init.baudrate = 7000000;
+  USART_InitSync(USART_USED, &init);
+}
+
+/**************************************************************************//**
+ * @brief  Disables GPIO pins and USART from FPGA register access
+ *****************************************************************************/
+static void spiDisable(void)
+{
+  USART_Reset(USART_USED);
+
+  /* Route setup must be reset separately */
+  USART_USED->ROUTE = _USART_ROUTE_RESETVALUE;
+
+  /* Disable SPI pins */
+  GPIO_PinModeSet(PORT_SPIBUS_CONNECT, PIN_SPIBUS_CONNECT, gpioModeDisabled, 0);
+  GPIO_PinModeSet(PORT_SPI_TX, PIN_SPI_TX, gpioModeDisabled, 0);
+  GPIO_PinModeSet(PORT_SPI_RX, PIN_SPI_RX, gpioModeDisabled, 0);
+  GPIO_PinModeSet(PORT_SPI_CLK, PIN_SPI_CLK, gpioModeDisabled, 0);
+  GPIO_PinModeSet(PORT_SPI_CS, PIN_SPI_CS, gpioModeDisabled, 0);
+
+  /* Disable USART clock - we can't disable GPIO or HFPER as we don't know who else
+   * might be using it */
+  CMU_ClockEnable(USART_CLK, false);
+}
+
+/**************************************************************************//**
+ * @brief  Perform SPI Transfer
+ *****************************************************************************/
+static uint16_t spiAccess(uint8_t spiaddr, uint8_t rw, uint16_t spidata)
+{
+  uint16_t      tmp;
+
+  GPIO_PinOutClear(PORT_SPI_CS, PIN_SPI_CS);
+
+  /* For every byte sent, one is received */
+
+  /* Write SPI address */
+  USART_Tx(USART_USED, (spiaddr & 0x3) | rw << 3);
+  /* Just ignore data read back */
+  USART_Rx(USART_USED);
+
+  /* SPI data LSB */ 
+  USART_Tx(USART_USED, spidata & 0xFF);
+  tmp = (uint16_t)USART_Rx(USART_USED);
+
+  /* SPI data MSB */ 
+  USART_Tx(USART_USED, spidata >> 8);
+  tmp |= (uint16_t)USART_Rx(USART_USED) << 8;
+
+  GPIO_PinOutSet(PORT_SPI_CS, PIN_SPI_CS);
+
+  return tmp;
+}
+
+/**************************************************************************//**
+ * @brief  Performs SPI write to FPGA register
+ * @param spiadr Address of register
+ * @param spidata Data to write
+ *****************************************************************************/
+static void spiWrite(uint8_t spiadr, uint16_t spidata)
+{
+  spiAccess(spiadr, 0, spidata);
+}
+
+/**************************************************************************//**
+ * @brief  Performs SPI read from FPGA register
+ * @param spiadr Address of register
+ * @param spidata Dummy data
+ *****************************************************************************/
+static uint16_t spiRead(uint8_t spiadr, uint16_t spidata)
+{
+  return spiAccess(spiadr, 1, spidata);
+}
+
+/**************************************************************************//**
+ * @brief  Initializes DVK register access
+ *****************************************************************************/
+void DVK_SPI_init(void)
+{
+  uint16_t spiMagic;
+
+  spiInit();
+  /* Read "board control Magic" register to verify SPI is up and running */
+  /*  if not FPGA is configured to be in EBI mode  */
+
+  spiMagic = DVK_SPI_readRegister(BC_MAGIC);
+  if (spiMagic != BC_MAGIC_VALUE)
+  {
+    /* Development Kit is configured to use EBI mode, restart of kit required */
+    /* to use SPI for configuration */
+    spiDisable();
+    while (1) ;
+  }
+}
+
+/**************************************************************************//**
+ * @brief  Disable and free up resources used by SPI board control access
+ *****************************************************************************/
+void DVK_SPI_disable(void)
+{
+  spiDisable();
+}
+
+/**************************************************************************//**
+ * @brief  Perform read from DVK board control register
+ * @param  addr Address of register to read from
+ *****************************************************************************/
+uint16_t DVK_SPI_readRegister(volatile uint16_t *addr)
+{
+  uint16_t data;
+
+  if (addr != lastAddr)
+  {
+    spiWrite(0x00, 0xFFFF & ((uint32_t) addr));             /*LSBs of address*/
+    spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16));         /*MSBs of address*/
+    spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26);   /*Chip select*/
+  }
+  /* Read twice */
+  data     = spiRead(0x03, 0);
+  data     = spiRead(0x03, 0);
+  lastAddr = addr;
+  return data;
+}
+
+/**************************************************************************//**
+ * @brief  Perform write to DVK board control register
+ * @param addr Address of register to write to
+ * @param data 16-bit to  write into register
+ *****************************************************************************/
+void DVK_SPI_writeRegister(volatile uint16_t *addr, uint16_t data)
+{
+  if (addr != lastAddr)
+  {
+    spiWrite(0x00, 0xFFFF & ((uint32_t) addr));             /*LSBs of address*/
+    spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16));         /*MSBs of address*/
+    spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26);   /*Chip select*/
+  }
+  spiWrite(0x03, data);                                     /*Data*/
+  lastAddr = addr;
+}

+ 10 - 3
bsp/efm32/SConscript

@@ -2,13 +2,20 @@ import rtconfig
 Import('RTT_ROOT')
 from building import *
 
+if rtconfig.EFM32_BOARD == 'EFM32_G290_DK':
+  src_kit = Glob('EFM32_Gxxx_DK/*.c')
+  CPPPATH = [RTT_ROOT + '/bsp/efm32/EFM32_Gxxx_DK']
+else:
+  src_kit = []
+  CPPPATH = []
+
 src_bsp = ['application.c', 'startup.c', 'board.c']
 src_drv = ['drv_dma.c', 'drv_rtc.c', 'drv_adc.c', 'drv_acmp.c', 'drv_usart.c', 'drv_iic.c', 'drv_timer.c']
-src_dev = ['dev_misc.c', 'dev_led.c']
+src_dev = ['dev_misc.c', 'dev_led.c', 'dev_sflash.c']
 src_hdl = ['hdl_interrupt.c']
 
-src = src_bsp + src_drv + src_dev + src_hdl
-CPPPATH = [RTT_ROOT + '/bsp/efm32']
+src = src_kit + src_bsp + src_drv + src_dev + src_hdl
+CPPPATH.append(RTT_ROOT + '/bsp/efm32')
 CPPDEFINES = ['USE_STDPERIPH_DRIVER', rtconfig.EFM32_BOARD, rtconfig.EFM32_TYPE]
 group = DefineGroup('Startup', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
 

+ 77 - 18
bsp/efm32/application.c

@@ -13,6 +13,7 @@
  * Date			Author		Notes
  * 2009-01-05 	Bernard 		first version
  * 2010-12-29	onelife		Modify for EFM32
+ * 2011-05-06	onelife		Add SPI Flash DEMO
  *********************************************************************/
  
 /******************************************************************//**
@@ -32,10 +33,9 @@
 #include <dfs_fs.h>
 #endif
 
-#ifdef RT_USING_LWIP
-#include <lwip/sys.h>
-#include <lwip/api.h>
-#include <netif/ethernetif.h>
+#include "dev_led.h"
+#ifdef EFM32_USING_SFLASH
+#include "dev_sflash.h"
 #endif
 
 /* Private typedef -------------------------------------------------------------*/
@@ -46,28 +46,74 @@ rt_uint32_t	rt_system_status = 0;
 
 /* Private function prototypes ---------------------------------------------------*/
 /* Private functions ------------------------------------------------------------*/
+void rt_demo_thread_entry(void* parameter)
+{
+#ifdef EFM32_USING_SFLASH
+	rt_uint8_t i;
+	rt_uint8_t test[] = "123456789ABCDEF";
+	rt_uint8_t buf[30], buf2[30];
+
+	efm_spiFash_cmd(sflash_inst_rdid_l, EFM32_NO_DATA, buf, sizeof(buf));
+	rt_kprintf("Manuf ID: %x\n", buf[0]);
+	rt_kprintf("Memory type: %x\n", buf[1]);
+	rt_kprintf("Memory capacity: %x\n", buf[2]);
+	rt_kprintf("CFD length: %x\n", buf[3]);
+	rt_kprintf("CFD: %x%x%x...%x%x\n", buf[4], buf[5], buf[6], buf[18], buf[19]);
+
+	efm_spiFash_cmd(sflash_inst_wren, EFM32_NO_DATA, EFM32_NO_POINTER, EFM32_NO_DATA);
+	do
+	{
+		efm_spiFash_cmd(sflash_inst_rdsr, EFM32_NO_DATA, buf2, sizeof(buf2));
+		rt_kprintf("Status: %x\n", buf2[0]);
+	} while (buf2[0] == 0xFF);
+	rt_kprintf("Status: %x\n", buf2[0]);
+
+	//efm_spiFash_cmd(sflash_inst_pp, 0x000003F8, test, sizeof(test) - 1);
+
+	efm_spiFash_cmd(sflash_inst_rdsr, EFM32_NO_DATA, buf2, sizeof(buf2));
+	rt_kprintf("Status: %x\n", buf2[0]);
+	
+	efm_spiFash_cmd(sflash_inst_read, 0x00000300, buf, sizeof(buf));
+	rt_kprintf("READ: \n");
+	for (i = 0; i < sizeof(buf); i++)
+	{
+		rt_kprintf("%c\n", buf[i]);
+	}
+
+	//efm_spiFash_deinit();
+#endif
+}
+
 void rt_led_thread_entry(void* parameter)
 {
-//	rt_uint8_t n = 0;
-		
+	rt_uint8_t n = 0;
+
 	rt_hw_led_on(0);
 	rt_hw_led_on(1);
 	rt_hw_led_on(2);
 	rt_hw_led_on(3);
-	
-//	while(1)
-//	{
-		/* light on leds for one second */
-//		rt_hw_led_toggle(n++);
-//		if (n == 4)
-//			n =0;
-//		rt_thread_delay(200);
-//	}
+
+	while(1)
+	{
+		/* Toggle a led per second */
+		rt_hw_led_toggle(n++);
+		if (n == LEDS_MAX_NUMBER)
+		{
+			n =0;
+		}
+		rt_thread_delay(100);
+	}
 }
 
 int rt_application_init()
 {
-	rt_thread_t led_thread;
+	rt_thread_t demo_thread, led_thread;
+
+#if (defined(EFM32_G290_DK) && defined(EFM32_USING_SFLASH))
+	/* Enable SPI access to Flash */
+	DVK_writeRegister(BC_SPI_CFG, 0);
+	efm_spiFash_init();
+#endif
 
 	/* Initialize all device drivers (dev_?.c) */
 	if (rt_hw_led_init() != RT_EOK)
@@ -82,19 +128,32 @@ int rt_application_init()
 	}
 
 #if (RT_THREAD_PRIORITY_MAX == 32)
+	demo_thread = rt_thread_create(
+		"demo",
+		rt_demo_thread_entry, 
+		RT_NULL,
+		2048, 
+		3, 
+		20);
+
 	led_thread = rt_thread_create(
 		"led",
 		rt_led_thread_entry, 
 		RT_NULL,
-		256, 
+		256,
 		3, 
 		20);
 #else
 #endif
 
+	if(demo_thread != RT_NULL)
+	{
+		rt_kprintf("demo sp:%x\n", demo_thread->sp);
+		rt_thread_startup(demo_thread);
+	}
+
 	if(led_thread != RT_NULL)
 	{
-		rt_kprintf("led sp:%x\n", led_thread->sp);
 		rt_thread_startup(led_thread);
 	}
 

+ 10 - 0
bsp/efm32/board.c

@@ -12,6 +12,7 @@
  * @section Change Logs
  * Date			Author		Notes
  * 2010-12-21	onelife		Initial creation for EFM32
+ * 2011-05-06	onelife		Add EFM32 development kit and SPI Flash support
  *********************************************************************/
  
 /******************************************************************//**
@@ -189,6 +190,11 @@ void rt_hw_board_init(void)
 	/* Chip errata */
 	CHIP_Init();
 
+#if defined(EFM32_G290_DK)
+	/* Initialize DVK board register access */
+	DVK_init();
+#endif
+
 	/* NVIC Configuration */
 	NVIC_Configuration();
 
@@ -222,6 +228,10 @@ void rt_hw_driver_init(void)
 	rt_hw_dma_init();
 
 	/* Initialize USART */
+#if defined(EFM32_G290_DK)
+	DVK_enablePeripheral(DVK_RS232A);
+	DVK_enablePeripheral(DVK_SPI);
+#endif
 	rt_hw_usart_init();
 
 	/* Initialize Timer */

+ 35 - 18
bsp/efm32/board.h

@@ -12,6 +12,7 @@
  * @section Change Logs
  * Date			Author		Notes
  * 2010-12-21	onelife		Initial creation for EFM32
+ * 2011-05-06	onelife		Add EFM32 development kit and SPI Flash support
  *********************************************************************/
 #ifndef __BOARD_H__
 #define __BOARD_H__
@@ -39,6 +40,10 @@
 
 #include <rtthread.h>
 
+#if defined(EFM32_G290_DK)
+#include <dvk.h>
+#endif
+
 /* Exported types -------------------------------------------------------------*/
 /* Exported constants ---------------------------------------------------------*/
 /* Exported variables ----------------------------------------------------------*/
@@ -48,40 +53,52 @@ extern rt_uint32_t rt_system_status;
 #define DEBUG_EFM
 #define DEBUG_EFM_USER
 
-#define EFM32_NO_DATA			(0)
-#define EFM32_NO_OFFSET			(-1)
-#define EFM32_NO_POINTER		(RT_NULL)
+#define EFM32_SFLASH_DEBUG
+
+#define EFM32_NO_DATA				(0)
+#define EFM32_NO_OFFSET				(-1)
+#define EFM32_NO_POINTER			(RT_NULL)
 
-#define EFM32_SRAM_END 			(RAM_MEM_BASE + SRAM_SIZE)
+#define EFM32_SRAM_END 				(RAM_MEM_BASE + SRAM_SIZE)
 
-#define EFM32_BASE_PRI_DEFAULT 	(0x0UL << 5)
-#define EFM32_IRQ_PRI_DEFAULT 	(0x4UL << 5)
+#define EFM32_BASE_PRI_DEFAULT 		(0x0UL << 5)
+#define EFM32_IRQ_PRI_DEFAULT 		(0x4UL << 5)
 
 #if (defined(EFM32_G890_STK) || defined(EFM32_G290_DK))
-#define EFM32_HFXO_FREQUENCY 	(32000000)
+#define EFM32_HFXO_FREQUENCY 		(32000000)
 #else
-#define EFM32_HFXO_FREQUENCY	(00000000)
+#define EFM32_HFXO_FREQUENCY		(00000000)
 #endif
 
-#define UART_BAUDRATE			(115200)
+#define UART_BAUDRATE				(115200)
+#define USART_RX_BUFFER_SIZE		(64)
 
-#define SERIAL_RX_BUFFER_SIZE	(64)
+/* Max SPI clock: HFPERCLK/2 for master, HFPERCLK/8 for slave */
+#define SPI_BAUDRATE				(4000000)
 
-#define IIC_RX_BUFFER_SIZE		(32)
+/* Slave select PIN setting for unit 2, 1 and 0 */
+#define SPI_AUTOCS_ENABLE 			((0 << 2) | (0 << 1) | (1 << 0))
 
-#define ADC_INIT_REF			adcRef2V5
-#define ADC_INIT_CH 			adcSingleInpCh5
-#define ADC_CONVERT_FREQUENCY 	(7000000)
+#define IIC_RX_BUFFER_SIZE			(32)
+
+#define ADC_INIT_REF				adcRef2V5
+#define ADC_INIT_CH 				adcSingleInpCh5
+#define ADC_CONVERT_FREQUENCY 		(7000000)
 
 #if (RT_CONSOLE_DEVICE == 0x0UL)
-#define CONSOLE_DEVICE 			RT_USART0_NAME
+#define CONSOLE_DEVICE 				RT_USART0_NAME
 #elif (RT_CONSOLE_DEVICE == 0x1UL)
-#define CONSOLE_DEVICE 			RT_USART1_NAME
+#define CONSOLE_DEVICE 				RT_USART1_NAME
 #elif (RT_CONSOLE_DEVICE == 0x2UL)
-#define CONSOLE_DEVICE 			RT_USART2_NAME
+#define CONSOLE_DEVICE 				RT_USART2_NAME
 #else
-#define CONSOLE_DEVICE 			"no"
+#define CONSOLE_DEVICE 				"no"
+#endif
+
+#if defined(EFM32_G290_DK)
+#define EFM32_USING_SFLASH
 #endif
+#define SFLASH_USING_DEVICE_NAME 	RT_USART0_NAME
 
 /*! fixme: move the following define to Rtdef.h */
 #define RT_DEVICE_CTRL_USART_RBUFFER	(0xF1)		/*!< set USART rx buffer */

+ 50 - 6
bsp/efm32/dev_led.c

@@ -12,7 +12,8 @@
  * @section Change Logs
  * Date			Author		Notes
  * 2009-01-05	Bernard		the first version
- * 2010-12-27	onelife		modify for EFM32
+ * 2010-12-27	onelife		Modify for EFM32
+ * 2011-05-06	onelife		Add EFM32 development kit support
  *********************************************************************/
 
 /******************************************************************//**
@@ -28,6 +29,7 @@
 /* Private define --------------------------------------------------------------*/
 /* Private macro --------------------------------------------------------------*/
 /* Private constants -----------------------------------------------------------*/
+#if defined(EFM32_G890_STK)
 static const rt_uint8_t	leds_list[LEDS_MAX_NUMBER][2] = \
 {
 	{LEDS_PIN_PORT_0, LEDS_PIN_NUMBER_0},
@@ -35,6 +37,7 @@ static const rt_uint8_t	leds_list[LEDS_MAX_NUMBER][2] = \
 	{LEDS_PIN_PORT_2, LEDS_PIN_NUMBER_2},
 	{LEDS_PIN_PORT_3, LEDS_PIN_NUMBER_3}
 };
+#endif
 
 /* Private variables ------------------------------------------------------------*/
 /* Private function prototypes ---------------------------------------------------*/
@@ -54,8 +57,17 @@ static const rt_uint8_t	leds_list[LEDS_MAX_NUMBER][2] = \
 void rt_hw_led_on(rt_uint8_t num)
 {
 	RT_ASSERT(num < LEDS_MAX_NUMBER);
-	
+
+#if defined(EFM32_G890_STK)
 	GPIO_PinOutSet(leds_list[num][0], leds_list[num][1]);
+#elif defined(EFM32_G290_DK)
+{
+	rt_uint16_t leds;
+	
+	leds = DVK_getLEDs() | (rt_uint16_t)(1 << num);
+	DVK_setLEDs(leds);
+}
+#endif
 }
 
 /******************************************************************//**
@@ -73,8 +85,17 @@ void rt_hw_led_on(rt_uint8_t num)
 void rt_hw_led_off(rt_uint8_t num)
 {
 	RT_ASSERT(num < LEDS_MAX_NUMBER);
-	
+
+#if defined(EFM32_G890_STK)
 	GPIO_PinOutClear(leds_list[num][0], leds_list[num][1]);
+#elif defined(EFM32_G290_DK)
+{
+	rt_uint16_t leds;
+	
+	leds = DVK_getLEDs() & ~(rt_uint16_t)(1 << num);
+	DVK_setLEDs(leds);
+}
+#endif
 }
 
 /******************************************************************//**
@@ -92,15 +113,29 @@ void rt_hw_led_off(rt_uint8_t num)
 void rt_hw_led_toggle(rt_uint8_t num)
 {
 	RT_ASSERT(num < LEDS_MAX_NUMBER);
-	
+
+#if defined(EFM32_G890_STK)
 	GPIO_PinOutToggle(leds_list[num][0], leds_list[num][1]);
+#elif defined(EFM32_G290_DK)
+{
+	rt_uint16_t leds;
+	
+	leds = DVK_getLEDs() ^ (rt_uint16_t)(1 << num);
+	DVK_setLEDs(leds);
+}
+#endif
 }
 
 rt_uint8_t rt_hw_led_state(rt_uint8_t num)
 {
 	RT_ASSERT(num < LEDS_MAX_NUMBER);
-	
+
+#if defined(EFM32_G890_STK)
 	return (rt_uint8_t)GPIO_PinInGet(leds_list[num][0], leds_list[num][1]);
+#elif defined(EFM32_G290_DK)
+	return ((DVK_getLEDs() & (rt_uint16_t)(1 << num)) >> num);
+#endif
+
 }
 
 /******************************************************************//**
@@ -116,6 +151,7 @@ rt_uint8_t rt_hw_led_state(rt_uint8_t num)
  *********************************************************************/
 rt_err_t rt_hw_led_init(void)
 {
+#if defined(EFM32_G890_STK)
 	rt_uint8_t i;
 		
 	/* Configure GPIO */
@@ -127,7 +163,7 @@ rt_err_t rt_hw_led_init(void)
 			gpioModePushPull,
 			0);
 	}
-
+#endif
 	return RT_EOK;
 }
 
@@ -146,8 +182,16 @@ void list_leds(void)
 
     for (i = 0; i < LEDS_MAX_NUMBER; i++)
 	{
+#if defined(EFM32_G890_STK)
 		rt_kprintf(" %d    \t %x    \t %x    \t %x    \n", 
 			i, leds_list[i][0], leds_list[i][1], rt_hw_led_state(i));
+#elif defined(EFM32_G290_DK)
+		rt_uint16_t leds;
+			
+		leds = DVK_getLEDs();
+		rt_kprintf(" %d    \t FPGA \t FPGA \t %x	  \n", 
+			i, (leds & (1 << i))? 1 : 0);
+#endif
 	}
 }
 FINSH_FUNCTION_EXPORT(list_leds, list all the LEDs.)

+ 3 - 3
bsp/efm32/dev_led.h

@@ -12,7 +12,8 @@
  * @section Change Logs
  * Date			Author		Notes
  * 2009-01-05	Bernard		the first version
- * 2010-12-27	onelife		modify for EFM32
+ * 2010-12-27	onelife		Modify for EFM32
+ * 2011-05-06	onelife		Add EFM32 development kit support
  *********************************************************************/
 #ifndef __DEV_LED_H__
 #define __DEV_LED_H__
@@ -32,9 +33,8 @@
 #define LEDS_PIN_NUMBER_2 		(2)
 #define LEDS_PIN_PORT_3 		gpioPortC
 #define LEDS_PIN_NUMBER_3 		(3)
-
 #elif defined(EFM32_G290_DK)
-	// TODO:
+#define LEDS_MAX_NUMBER 		(16)
 #endif
 
 /* Exported functions --------------------------------------------------------- */

+ 355 - 0
bsp/efm32/dev_sflash.c

@@ -0,0 +1,355 @@
+/******************************************************************//**
+ * @file 		dev_sflash.c
+ * @brief 	SPI Flash driver of RT-Thread RTOS for using EFM32 USART module.
+ * 	This driver is tested by using the M25PX16 device on the EFM32 development kit.
+ * 	COPYRIGHT (C) 2011, RT-Thread Development Team
+ * @author 	onelife
+ * @version 	0.4 beta
+ **********************************************************************
+ * @section License
+ * The license and distribution terms for this file may be found in the file LICENSE in this 
+ * distribution or at http://www.rt-thread.org/license/LICENSE
+ **********************************************************************
+ * @section Change Logs
+ * Date			Author		Notes
+ * 2010-05-06	onelife		Initial creation for using EFM32 USART module
+ *********************************************************************/
+
+/******************************************************************//**
+ * @addtogroup efm32_dk
+ * @{
+*********************************************************************/
+
+/* Includes -------------------------------------------------------------------*/
+#include "board.h"
+#include "dev_sflash.h"
+
+#if defined(EFM32_USING_SFLASH)
+/* Private typedef -------------------------------------------------------------*/
+typedef struct
+{
+	rt_uint8_t code;
+	rt_uint32_t address:24;
+	rt_uint32_t dummy:8;
+} sflash_instruction;
+
+/* Private define --------------------------------------------------------------*/
+/* Private macro --------------------------------------------------------------*/
+#ifdef EFM32_SFLASH_DEBUG
+#define sflash_debug(format,args...) 		rt_kprintf(format, ##args)
+#else
+#define sflash_debug(format,args...)
+#endif
+
+/* Private constants -----------------------------------------------------------*/
+static rt_uint8_t sflash_inst_code_tbl[] = 
+{
+	/* Instruction only */
+	SFLASH_INST_CODE_WREN,
+	SFLASH_INST_CODE_WRDI,
+	SFLASH_INST_CODE_RDID_L,
+	SFLASH_INST_CODE_RDID_S,
+	SFLASH_INST_CODE_RDSR,
+	SFLASH_INST_CODE_WRSR,
+	SFLASH_INST_CODE_BE,
+	SFLASH_INST_CODE_DP,
+	SFLASH_INST_CODE_RDP,
+	/* Instruction and address */
+	SFLASH_INST_CODE_WRLR,
+	SFLASH_INST_CODE_RDLR,
+	SFLASH_INST_CODE_READ,
+	SFLASH_INST_CODE_POTP,
+	SFLASH_INST_CODE_PP,
+	SFLASH_INST_CODE_DIFP,
+	SFLASH_INST_CODE_SSE,
+	SFLASH_INST_CODE_SE,
+	/* Instruction, address and dummy read */
+	SFLASH_INST_CODE_READ_F,
+	SFLASH_INST_CODE_DOFR,
+	SFLASH_INST_CODE_ROTP
+};
+static rt_uint16_t sflash_data_len_tbl[] = 
+{
+	/* Instruction only */
+	SFLASH_REPLY_LEN_WREN,
+	SFLASH_REPLY_LEN_WRDI,
+	SFLASH_REPLY_LEN_RDID_L,
+	SFLASH_REPLY_LEN_RDID_S,
+	SFLASH_REPLY_LEN_RDSR,
+	SFLASH_REPLY_LEN_WRSR,
+	SFLASH_REPLY_LEN_BE,
+	SFLASH_REPLY_LEN_DP,
+	SFLASH_REPLY_LEN_RDP,
+	/* Instruction and address */
+	SFLASH_REPLY_LEN_WRLR,
+	SFLASH_REPLY_LEN_RDLR,
+	SFLASH_REPLY_LEN_READ,
+	SFLASH_REPLY_LEN_POTP,
+	SFLASH_REPLY_LEN_PP,
+	SFLASH_REPLY_LEN_DIFP,
+	SFLASH_REPLY_LEN_SSE,
+	SFLASH_REPLY_LEN_SE,
+	/* Instruction, address and dummy read */
+	SFLASH_REPLY_LEN_READ_F,
+	SFLASH_REPLY_LEN_DOFR,
+	SFLASH_REPLY_LEN_ROTP
+};
+static rt_bool_t sflash_read_inst_tbl[] = 
+{
+	/* Instruction only */
+	false,
+	false,
+	true,
+	true,
+	true,
+	false,
+	false,
+	false,
+	false,
+	/* Instruction and address */
+	false,
+	true,
+	true,
+	false,
+	false,
+	false,
+	false,
+	false,
+	/* Instruction, address and dummy read */
+	true,
+	true,
+	true
+};
+
+/* Private variables ------------------------------------------------------------*/
+static rt_device_t 	sflash 					= RT_NULL;
+
+/* Private function prototypes ---------------------------------------------------*/
+/* Private functions ------------------------------------------------------------*/
+/******************************************************************//**
+ * @brief
+ *   Initialize the SPI Flash
+ *
+ * @details
+ *
+ * @note
+ *
+ * @return
+ *	 Error code
+ *********************************************************************/
+rt_err_t efm_spiFash_init(void)
+{
+	/* Find SPI device */
+	sflash = rt_device_find(SFLASH_USING_DEVICE_NAME);
+
+	do
+	{
+		if (sflash == RT_NULL)
+		{
+			sflash_debug("SFLASH: Can't find device %s!\n", 
+				SFLASH_USING_DEVICE_NAME);
+			break;
+		}
+		sflash_debug("SFLASH: Find device %s\n", SFLASH_USING_DEVICE_NAME);
+	
+		/* Open SPI device */
+		if (sflash->open(sflash, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
+		{
+			break;
+		}
+
+		return RT_EOK;
+	} while(0);
+
+	sflash_debug("SFLASH: Init failed!\n");
+	return -RT_ERROR;
+}
+
+/******************************************************************//**
+ * @brief
+ *   De-initialize the SPI Flash
+ *
+ * @details
+ *
+ * @note
+ *
+ * @return
+ *	 Error code
+ *********************************************************************/
+rt_err_t efm_spiFash_deinit(void)
+{
+	do
+	{
+		if (sflash == RT_NULL)
+		{
+			sflash_debug("SFLASH: Already deinit!\n");
+			break;
+		}
+	
+		/* Close SPI device */
+		if (sflash->close(sflash) != RT_EOK)
+		{
+			break;
+		}
+		sflash = RT_NULL;
+		sflash_debug("SFLASH: Close device %s\n", SFLASH_USING_DEVICE_NAME);
+
+		return RT_EOK;
+	} while(0);
+
+	sflash_debug("SFLASH: Deinit failed!\n");
+	return -RT_ERROR;
+}
+
+
+/******************************************************************//**
+ * @brief
+ *   Execute a command
+ *
+ * @details
+ *
+ * @note
+ *
+ * @param[in] command
+ *  SPI Flash instruction
+ *
+ * @param[in] address
+ *   Memory address
+ *
+ * @param[in] buffer
+ *   Poniter to the read/write buffer
+ *
+ * @param[in] size
+ *   Buffer size in byte
+ *
+ * @return
+ *	 Number of read/written bytes
+ *********************************************************************/
+rt_uint32_t efm_spiFash_cmd(
+	enum sflash_inst_type_t command, 
+	rt_uint32_t address,
+	rt_uint8_t *buffer, 
+	rt_uint32_t size)
+{
+	RT_ASSERT(sflash != RT_NULL);
+
+	sflash_instruction *inst;
+	rt_uint8_t *inst_buf;
+	rt_uint8_t inst_len, head_len;
+	rt_uint32_t data_len;
+
+	sflash_debug("SFLASH: Inst %x\n", sflash_inst_code_tbl[command]);
+	if (sflash_data_len_tbl[command] && !size)
+	{
+		sflash_debug("SFLASH: No data!\n");
+		return 0x00;
+	}
+
+	data_len = (sflash_data_len_tbl[command] < size)? \
+				sflash_data_len_tbl[command] : size;
+	if (data_len && (buffer == RT_NULL))
+	{
+		sflash_debug("SFLASH: No buffer specified!\n");
+		return 0x00;
+	}
+
+	/* Allocate memory for write buffer */
+	if (sflash_read_inst_tbl[command])
+	{
+		inst_buf = rt_malloc(6 + 4);
+		inst = (sflash_instruction *)(inst_buf + 1);
+		head_len = 1;
+	}
+	else
+	{
+		inst_buf = rt_malloc(5 + data_len);
+		inst = (sflash_instruction *)inst_buf;
+		head_len = 0;
+	}
+
+	/* Fill in instruction */
+	inst->code = sflash_inst_code_tbl[command];
+	if (command >= sflash_inst_wrlr)
+	{
+		/* MSB first */
+		inst->address = ((address & 0x000000FF) << 16) | \
+						(address & 0x0000FF00) | \
+						((address & 0x00FF0000) >> 16);
+		if (command >= sflash_inst_read_f)
+		{
+			inst->dummy = 0x00;
+			inst_len = 5;
+		}
+		else
+		{
+			inst_len = 4;
+		}
+	}
+	else
+	{
+		inst_len = 1;
+	}
+	head_len += inst_len;
+
+	/* Fill in data and send the buffer */
+	if (sflash_read_inst_tbl[command])
+	{
+		inst_buf[0] = inst_len;
+		*(rt_uint8_t **)(inst_buf + head_len) = buffer;
+
+		if (sflash->read(sflash, EFM32_NO_DATA, inst_buf, \
+			(data_len == size)? data_len - 1 : data_len) == 0)
+		{
+			sflash_debug("SFLASH: Read failed!\n");
+			return 0x00;
+		}
+		buffer[data_len] = 0x00;
+		sflash_debug("SFLASH: Read %d bytes data to 0x%x\n", data_len, buffer);
+	}
+	else
+	{
+		if (data_len)
+		{
+			rt_memcpy((inst_buf + head_len), buffer, data_len);
+		}
+
+		if (sflash->write(sflash, EFM32_NO_DATA, inst_buf, \
+			head_len + data_len) == 0)
+		{
+			sflash_debug("SFLASH: Write failed!\n");
+			return 0x00;
+		}
+		sflash_debug("SFLASH: Write %d/%d bytes data\n", data_len, \
+			head_len + data_len);
+	}
+
+	/* Free the buffer */
+	rt_free(inst_buf);
+	return data_len;
+}
+
+/*********************************************************************
+* 	Export to FINSH
+*********************************************************************/
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+
+void list_sflash(void)
+{
+	rt_uint8_t buf[4];
+
+	efm_spiFash_cmd(sflash_inst_rdid_s, EFM32_NO_DATA, buf, sizeof(buf));
+	
+	rt_kprintf(" spi flash on %s\n", SFLASH_USING_DEVICE_NAME);
+	rt_kprintf(" manufacturer id: \t%x\n", buf[0]);
+	rt_kprintf(" memory type: \t\t%x\n", buf[1]);
+	rt_kprintf(" memory capacity: \t%x\n", buf[2]);
+}
+FINSH_FUNCTION_EXPORT(list_sflash, list the SPI Flash.)
+#endif
+
+#endif /* defined(EFM32_USING_SFLASH) */
+
+/******************************************************************//**
+ * @}
+*********************************************************************/

+ 102 - 0
bsp/efm32/dev_sflash.h

@@ -0,0 +1,102 @@
+/******************************************************************//**
+ * @file 		dev_sflash.h
+ * @brief 	SPI Flash driver of RT-Thread RTOS for using EFM32 USART module
+ * 	This driver is tested by using the M25PX16 device on the EFM32 development kit.
+ * 	COPYRIGHT (C) 2011, RT-Thread Development Team
+ * @author 	onelife
+ * @version 	0.4 beta
+ **********************************************************************
+ * @section License
+ * The license and distribution terms for this file may be found in the file LICENSE in this 
+ * distribution or at http://www.rt-thread.org/license/LICENSE
+ **********************************************************************
+ * @section Change Logs
+ * Date			Author		Notes
+ * 2010-05-06	onelife		Initial creation for using EFM32 USART module
+ *********************************************************************/
+#ifndef __DEV_SFLASH_H__
+#define __DEV_SFLASH_H__
+
+/* Includes -------------------------------------------------------------------*/
+/* Exported types -------------------------------------------------------------*/
+enum sflash_inst_type_t
+{
+	/* Instruction only */
+	sflash_inst_wren = 0x00,
+	sflash_inst_wrdi,
+	sflash_inst_rdid_l,
+	sflash_inst_rdid_s,
+	sflash_inst_rdsr,
+	sflash_inst_wrsr,
+	sflash_inst_be,
+	sflash_inst_dp,
+	sflash_inst_rdp,
+	/* Instruction and address */
+	sflash_inst_wrlr,
+	sflash_inst_rdlr,
+	sflash_inst_read,
+	sflash_inst_potp,
+	sflash_inst_pp,
+	sflash_inst_difp,
+	sflash_inst_sse,
+	sflash_inst_se,
+	/* Instruction, address and dummy read */
+	sflash_inst_read_f,
+	sflash_inst_dofr,
+	sflash_inst_rotp
+};
+
+/* Exported constants ---------------------------------------------------------*/
+/* Exported macro -------------------------------------------------------------*/
+#define SFLASH_INST_CODE_WREN 		(0x06)
+#define SFLASH_INST_CODE_WRDI 		(0x04)
+#define SFLASH_INST_CODE_RDID_L 	(0x9F)
+#define SFLASH_INST_CODE_RDID_S 	(0x9E)
+#define SFLASH_INST_CODE_RDSR 		(0x05)
+#define SFLASH_INST_CODE_WRSR 		(0x01)
+#define SFLASH_INST_CODE_WRLR 		(0xE5)
+#define SFLASH_INST_CODE_RDLR 		(0xE8)
+#define SFLASH_INST_CODE_READ 		(0x03)
+#define SFLASH_INST_CODE_READ_F 	(0x0B)
+#define SFLASH_INST_CODE_DOFR 		(0x3B)
+#define SFLASH_INST_CODE_ROTP 		(0x4B)
+#define SFLASH_INST_CODE_POTP 		(0x42)
+#define SFLASH_INST_CODE_PP 		(0x02)
+#define SFLASH_INST_CODE_DIFP 		(0xA2)
+#define SFLASH_INST_CODE_SSE 		(0x20)
+#define SFLASH_INST_CODE_SE 		(0xD8)
+#define SFLASH_INST_CODE_BE 		(0xC7)
+#define SFLASH_INST_CODE_DP 		(0xB9)
+#define SFLASH_INST_CODE_RDP 		(0xAB)
+
+#define SFLASH_REPLY_LEN_WREN 		(0)
+#define SFLASH_REPLY_LEN_WRDI 		(0)
+#define SFLASH_REPLY_LEN_RDID_L 	(20)
+#define SFLASH_REPLY_LEN_RDID_S 	(3)
+#define SFLASH_REPLY_LEN_RDSR 		(1)
+#define SFLASH_REPLY_LEN_WRSR 		(1)
+#define SFLASH_REPLY_LEN_WRLR 		(1)
+#define SFLASH_REPLY_LEN_RDLR 		(1)
+#define SFLASH_REPLY_LEN_READ 		(-1)
+#define SFLASH_REPLY_LEN_READ_F 	(-1)
+#define SFLASH_REPLY_LEN_DOFR 		(-1)
+#define SFLASH_REPLY_LEN_ROTP 		(65)
+#define SFLASH_REPLY_LEN_POTP 		(65)
+#define SFLASH_REPLY_LEN_PP 		(256)
+#define SFLASH_REPLY_LEN_DIFP 		(256)
+#define SFLASH_REPLY_LEN_SSE 		(0)
+#define SFLASH_REPLY_LEN_SE 		(0)
+#define SFLASH_REPLY_LEN_BE 		(0)
+#define SFLASH_REPLY_LEN_DP 		(0)
+#define SFLASH_REPLY_LEN_RDP 		(0)
+
+/* Exported functions --------------------------------------------------------- */
+rt_err_t efm_spiFash_init(void);
+rt_err_t efm_spiFash_deinit(void);
+rt_uint32_t efm_spiFash_cmd(
+	enum sflash_inst_type_t command, 
+	rt_uint32_t address,
+	rt_uint8_t *buffer, 
+	rt_uint32_t size);
+
+#endif /* __DEV_SFLASH_H__ */

+ 255 - 123
bsp/efm32/drv_usart.c

@@ -13,6 +13,7 @@
  * Date			Author		Notes
  * 2010-12-22	onelife		Initial creation for EFM32
  * 2011-01-17	onelife		Merge with serial.c
+ * 2011-05-06	onelife		Add sync mode (SPI) support
  *
  * @section Change Logs of serial.c
  * 2009-02-05	Bernard		first version
@@ -31,8 +32,20 @@
 #include "drv_usart.h"
 
 /* Private typedef -------------------------------------------------------------*/
+union efm32_usart_init_t
+{
+	USART_InitAsync_TypeDef 	async;
+	USART_InitSync_TypeDef		sync;
+};							
+
 /* Private define --------------------------------------------------------------*/
 /* Private macro --------------------------------------------------------------*/
+#ifdef RT_USART_DEBUG
+#define usart_debug(format,args...) 		rt_kprintf(format, ##args)
+#else
+#define usart_debug(format,args...)
+#endif
+
 /* Private variables ------------------------------------------------------------*/
 #ifdef RT_USING_USART0
 #if (RT_USING_USART0 > 3)
@@ -128,64 +141,64 @@ static rt_err_t rt_usart_open(rt_device_t dev, rt_uint16_t oflag)
 	RT_ASSERT(dev != RT_NULL);
 
 	struct efm32_usart_device_t	*usart;
-	IRQn_Type 					rxIrq;
-	
-	usart = (struct efm32_usart_device_t *)(dev->user_data);
 
-	//if (usart->state & USART_STATE_CONSOLE)
-	{	/* Allocate new RX buffer */
-		struct efm32_usart_int_mode_t	*int_mode;
+	usart = (struct efm32_usart_device_t *)(dev->user_data);
+	
+	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
+	{
+		IRQn_Type 					rxIrq;
 		
-		int_mode = (struct efm32_usart_int_mode_t *)(usart->rx_mode);
+		//if (usart->state & USART_STATE_CONSOLE)
+		{	/* Allocate new RX buffer */
+			struct efm32_usart_int_mode_t	*int_mode;
+			
+			int_mode = (struct efm32_usart_int_mode_t *)(usart->rx_mode);
 
-		if ((int_mode->data_ptr = rt_malloc(SERIAL_RX_BUFFER_SIZE)) == RT_NULL)
+			if ((int_mode->data_ptr = rt_malloc(USART_RX_BUFFER_SIZE)) == RT_NULL)
+			{
+				usart_debug("USART: no memory for RX buffer\n");
+				return -RT_ENOMEM;
+			}
+			rt_memset(int_mode->data_ptr, 0, USART_RX_BUFFER_SIZE);
+			int_mode->data_size = USART_RX_BUFFER_SIZE;
+			int_mode->read_index = 0;
+			int_mode->save_index = 0;
+		}
+		
+		/* Enable TX/RX interrupt */	
+		switch (usart->unit)
 		{
-#ifdef RT_USART_DEBUG
-			rt_kprintf("no memory for serial RX buffer\n");
-#endif
-			return -RT_ENOMEM;
+		case 0:
+			rxIrq 		= USART0_RX_IRQn;
+			break;
+		case 1:
+			rxIrq		= USART1_RX_IRQn;
+			break;
+		case 2:
+			rxIrq		= USART2_RX_IRQn;
+			break;
 		}
-		rt_memset(int_mode->data_ptr, 0, SERIAL_RX_BUFFER_SIZE);
-		int_mode->data_size = SERIAL_RX_BUFFER_SIZE;
-		int_mode->read_index = 0;
-		int_mode->save_index = 0;
-	}
-	
-	/* Enable TX/RX interrupt */	
-	switch (usart->unit)
-	{
-	case 0:
-		rxIrq 		= USART0_RX_IRQn;
-		break;
-	case 1:
-		rxIrq		= USART1_RX_IRQn;
-		break;
-	case 2:
-		rxIrq		= USART2_RX_IRQn;
-		break;
-	}
 
-	/* Enable RX interrupts */
-	usart->usart_device->IEN 	= USART_IEN_RXDATAV;
-	usart->usart_device->IFC 	= _USART_IFC_MASK;
+		/* Enable RX interrupts */
+		usart->usart_device->IEN 	= USART_IEN_RXDATAV;
 
-	/* Enable IRQ */
-	if (oflag != RT_DEVICE_OFLAG_WRONLY)
-	{
-		NVIC_ClearPendingIRQ(rxIrq);
-		NVIC_SetPriority(rxIrq, EFM32_IRQ_PRI_DEFAULT);
-		NVIC_EnableIRQ(rxIrq);
+		/* Enable IRQ */
+		if (oflag != RT_DEVICE_OFLAG_WRONLY)
+		{
+			NVIC_ClearPendingIRQ(rxIrq);
+			NVIC_SetPriority(rxIrq, EFM32_IRQ_PRI_DEFAULT);
+			NVIC_EnableIRQ(rxIrq);
+		}
 	}
-	if (oflag != RT_DEVICE_OFLAG_RDONLY)
+	usart->usart_device->IFC 	= _USART_IFC_MASK;
+	
+	if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (oflag != RT_DEVICE_OFLAG_RDONLY))
 	{
 		/* DMA IRQ is enabled by DMA_Init() */
 		NVIC_SetPriority(DMA_IRQn, EFM32_IRQ_PRI_DEFAULT);
 	}
 
-#ifdef RT_USART_DEBUG
-		rt_kprintf("USART%d: Open with flag %x\n", usart->unit, oflag);
-#endif
-
+	usart_debug("USART%d: Open with flag %x\n", usart->unit, oflag);
 	return RT_EOK;
 }
 
@@ -205,14 +218,16 @@ static rt_err_t rt_usart_open(rt_device_t dev, rt_uint16_t oflag)
  *********************************************************************/
 static rt_err_t rt_usart_close(rt_device_t dev)
 {
-	struct efm32_usart_int_mode_t *int_rx;
+	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
+	{
+		struct efm32_usart_int_mode_t *int_rx;
 
-	int_rx = (struct efm32_usart_int_mode_t *)\
-		(((struct efm32_usart_device_t *)(dev->user_data))->rx_mode);
-	
-	rt_free(int_rx->data_ptr);
-	int_rx->data_ptr = RT_NULL;
-	
+		int_rx = (struct efm32_usart_int_mode_t *)\
+			(((struct efm32_usart_device_t *)(dev->user_data))->rx_mode);
+		
+		rt_free(int_rx->data_ptr);
+		int_rx->data_ptr = RT_NULL;
+	}
 	return RT_EOK;
 }
 
@@ -242,17 +257,19 @@ static rt_err_t rt_usart_close(rt_device_t dev)
 static rt_size_t rt_usart_read (
 	rt_device_t 	dev, 
 	rt_off_t 		pos, 
-	void* 			buffer, 
+	void 			*buffer, 
 	rt_size_t 		size)
 {
-	rt_uint8_t* ptr;
+	rt_uint8_t 	*ptr;
 	rt_err_t 	err_code;
+	rt_size_t 	read_len;
 
-	ptr = buffer;
 	err_code = RT_EOK;
 
 	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
 	{
+		ptr = buffer;
+
 		/* interrupt mode Rx */
 		while (size)
 		{
@@ -273,7 +290,7 @@ static rt_size_t rt_usart_read (
 
 				/* move to next position */
 				int_rx->read_index ++;
-				if (int_rx->read_index >= SERIAL_RX_BUFFER_SIZE)
+				if (int_rx->read_index >= USART_RX_BUFFER_SIZE)
 				{
 					int_rx->read_index = 0;
 				}
@@ -291,28 +308,77 @@ static rt_size_t rt_usart_read (
 			/* enable interrupt */
 			rt_hw_interrupt_enable(level);
 		}
+
+		read_len = (rt_uint32_t)ptr - (rt_uint32_t)buffer;
 	}
 	else
 	{
-		/* polling mode */
+		RT_ASSERT(buffer != RT_NULL);
+	
+		struct efm32_usart_device_t *usart;
 		USART_TypeDef *usart_device;
 
-		RT_ASSERT(buffer != RT_NULL);
+		usart = (struct efm32_usart_device_t *)(dev->user_data);
 		usart_device = ((struct efm32_usart_device_t *)(dev->user_data))->usart_device;
-			
-		while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
+
+		if (usart->state & USART_STATE_SYNC)
 		{
-			while (usart_device->STATUS & USART_STATUS_RXDATAV)
+			/* SPI read */
+			rt_uint8_t inst_len = *((rt_uint8_t *)buffer);
+			rt_uint8_t *inst_ptr = (rt_uint8_t *)(buffer + 1);
+			rt_uint8_t *rx_buf = *((rt_uint8_t **)(buffer + inst_len + 1));
+
+			ptr = rx_buf;
+
+			/* write instruction */
+			while (inst_len)
+			{
+				while (!(usart->usart_device->STATUS & USART_STATUS_TXBL));
+				usart->usart_device->TXDATA = (rt_uint32_t)*inst_ptr;
+				++inst_ptr; --inst_len;
+			}
+
+			/* Flushing RX */
+			usart_device->CMD = USART_CMD_CLEARRX;
+			/* dummy write */
+			while (!(usart_device->STATUS & USART_STATUS_TXBL));
+			usart_device->TXDATA = (rt_uint32_t)0x00;
+			/* dummy read */
+			while (!(usart_device->STATUS & USART_STATUS_RXDATAV));
+			*((rt_uint32_t *)0x00) = usart_device->RXDATA;
+	
+			while ((rt_uint32_t)ptr - (rt_uint32_t)rx_buf < size)
 			{
+				/* dummy write */
+				while (!(usart_device->STATUS & USART_STATUS_TXBL));
+				usart_device->TXDATA = (rt_uint32_t)0x00;
+				/* read a byte of data */
+				while (!(usart_device->STATUS & USART_STATUS_RXDATAV));
 				*ptr = usart_device->RXDATA & 0xff;
 				ptr ++;
 			}
 		}
+		else
+		{
+			ptr = buffer;
+
+			/* polling mode */
+			while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
+			{
+				while (usart_device->STATUS & USART_STATUS_RXDATAV)
+				{
+					*ptr = usart_device->RXDATA & 0xff;
+					ptr ++;
+				}
+			}
+		}
+
+		read_len = size;
 	}
 
 	/* set error code */
 	rt_set_errno(err_code);
-	return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
+	return read_len;
 }
 
 /******************************************************************//**
@@ -336,7 +402,7 @@ static rt_size_t rt_usart_read (
  *   Buffer size in byte
  *
  * @return
- *   Error code
+ *   Number of written bytes
  *********************************************************************/
 static rt_size_t rt_usart_write (
 	rt_device_t 	dev, 
@@ -352,7 +418,7 @@ static rt_size_t rt_usart_write (
 	write_size = 0;
 	usart = (struct efm32_usart_device_t*)(dev->user_data);
 
-	if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
+	if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (size > 1))
 	{	/* DMA mode Tx */
 		struct efm32_usart_dma_mode_t *dma_tx;
 	
@@ -393,7 +459,7 @@ static rt_size_t rt_usart_write (
 	}
 	else
 	{	/* polling mode */	
-		rt_uint8_t* ptr = (rt_uint8_t*)buffer;
+		rt_uint8_t *ptr = (rt_uint8_t *)buffer;
 	
 		if (dev->flag & RT_DEVICE_FLAG_STREAM)
 		{
@@ -408,7 +474,6 @@ static rt_size_t rt_usart_write (
 
 				while (!(usart->usart_device->STATUS & USART_STATUS_TXBL));
 				usart->usart_device->TXDATA = (rt_uint32_t)*ptr;
-
 				++ptr; --size;
 			}
 		}
@@ -419,7 +484,6 @@ static rt_size_t rt_usart_write (
 			{
 				while (!(usart->usart_device->STATUS & USART_STATUS_TXBL));
 				usart->usart_device->TXDATA = (rt_uint32_t)*ptr;
-
 				++ptr; --size;
 			}
 		}
@@ -500,9 +564,7 @@ static rt_err_t rt_usart_control (
 					if ((int_rx->data_ptr = rt_realloc(int_rx->data_ptr, size)) \
 						== RT_NULL)
 					{
-#ifdef RT_USART_DEBUG
-						rt_kprintf("no memory for usart rx buffer\n");
-#endif
+						usart_debug("USART: no memory for RX buffer\n");
 						return -RT_ENOMEM;
 					}
 					// TODO: Is the following line necessary?
@@ -514,9 +576,7 @@ static rt_err_t rt_usart_control (
 				/* Allocate new RX buffer */
 				if ((int_rx->data_ptr = rt_malloc(size)) == RT_NULL)
 				{
-#ifdef RT_USART_DEBUG
-					rt_kprintf("no memory for usart rx buffer\n");
-#endif
+					usart_debug("USART: no memory for RX buffer\n");
 					return -RT_ENOMEM;
 				}
 			}
@@ -570,14 +630,14 @@ void rt_hw_usart_rx_isr(rt_device_t dev)
 		int_rx->data_ptr[int_rx->save_index] = \
 			(rt_uint8_t)(usart->usart_device->RXDATA & 0xFFUL);
 		int_rx->save_index ++;
-		if (int_rx->save_index >= SERIAL_RX_BUFFER_SIZE)
+		if (int_rx->save_index >= USART_RX_BUFFER_SIZE)
 			int_rx->save_index = 0;
 
 		/* if the next position is read index, discard this 'read char' */
 		if (int_rx->save_index == int_rx->read_index)
 		{
 			int_rx->read_index ++;
-			if (int_rx->read_index >= SERIAL_RX_BUFFER_SIZE)
+			if (int_rx->read_index >= USART_RX_BUFFER_SIZE)
 			{
 				int_rx->read_index = 0;
 			}
@@ -594,7 +654,7 @@ void rt_hw_usart_rx_isr(rt_device_t dev)
 
 		/* get rx length */
 		rx_length = int_rx->read_index > int_rx->save_index ?
-			SERIAL_RX_BUFFER_SIZE - int_rx->read_index + int_rx->save_index : \
+			USART_RX_BUFFER_SIZE - int_rx->read_index + int_rx->save_index : \
 			int_rx->save_index - int_rx->read_index;
 
 		dev->rx_indicate(dev, rx_length);
@@ -720,33 +780,24 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init(
 	rt_uint8_t 	location,
 	rt_uint32_t flag,
 	rt_uint32_t	dmaChannel,
-	rt_bool_t 	console)
+	rt_uint8_t 	config)
 {
 	struct efm32_usart_device_t 	*usart;
 	struct efm32_usart_dma_mode_t	*dma_mode;
 	CMU_Clock_TypeDef				usartClock;
 	rt_uint32_t						txDmaSelect;
-	USART_InitAsync_TypeDef			init;
+	union efm32_usart_init_t 		init;
 	efm32_irq_hook_init_t			hook;
 
 	/* Allocate device */
 	usart = rt_malloc(sizeof(struct efm32_usart_device_t));
 	if (usart == RT_NULL)
 	{
-#ifdef RT_USART_DEBUG
-		rt_kprintf("no memory for USART driver\n");
-#endif
+		usart_debug("USART: no memory for device\n");
 		return usart;
 	}
 	usart->unit 	= unitNumber;
-	if (console == true)
-	{
-		usart->state = USART_STATE_CONSOLE;
-	}
-	else
-	{
-		usart->state = 0;
-	}
+	usart->state 	= config;
 	usart->tx_mode 	= RT_NULL;
 	usart->rx_mode 	= RT_NULL;
 
@@ -757,9 +808,7 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init(
 		usart->tx_mode = dma_mode = rt_malloc(sizeof(struct efm32_usart_dma_mode_t));
 		if (dma_mode == RT_NULL)
 		{
-#ifdef RT_USART_DEBUG
-			rt_kprintf("no memory for USART TX by DMA\n");
-#endif
+			usart_debug("USART: no memory for DMA TX\n");
 			rt_free(usart->rx_mode);
 			rt_free(usart);
 			usart = RT_NULL;
@@ -774,9 +823,7 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init(
 		usart->rx_mode = rt_malloc(sizeof(struct efm32_usart_int_mode_t));
 		if (usart->rx_mode == RT_NULL)
 		{
-#ifdef RT_USART_DEBUG
-			rt_kprintf("no memory for USART RX by interrupt\n");
-#endif
+			usart_debug("USART: no memory for interrupt RX\n");
 			rt_free(usart->tx_mode);
 			rt_free(usart);
 			usart = RT_NULL;
@@ -823,6 +870,22 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init(
 		AF_PIN(AF_USART_RX(unitNumber), location),
 		gpioModeInputPull,
 		1);
+	if (config & USART_STATE_SYNC)
+	{
+		GPIO_PinModeSet(
+			(GPIO_Port_TypeDef)AF_PORT(AF_USART_CLK(unitNumber), location),
+			AF_PIN(AF_USART_CLK(unitNumber), location),
+			gpioModePushPull,
+			0);
+	}
+	if (config & USART_STATE_AUTOCS)
+	{
+		GPIO_PinModeSet(
+			(GPIO_Port_TypeDef)AF_PORT(AF_USART_CS(unitNumber), location),
+			AF_PIN(AF_USART_CS(unitNumber), location),
+			gpioModePushPull,
+			1);
+	}
 
 	/* Config interrupt and NVIC */
 	if (flag & RT_DEVICE_FLAG_INT_RX)
@@ -871,16 +934,49 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init(
 	/* Enable RX and TX pins and set location */
 	usart->usart_device->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | \
 					(location << _USART_ROUTE_LOCATION_SHIFT);
+	if (config & USART_STATE_SYNC)
+	{
+		usart->usart_device->ROUTE |= USART_ROUTE_CLKPEN;
+	}
+	if (config & USART_STATE_AUTOCS)
+	{
+		usart->usart_device->ROUTE |= USART_ROUTE_CSPEN;
+		if (config & USART_STATE_MASTER)
+		{
+			usart->usart_device->CTRL |= USART_CTRL_AUTOCS;
+		}
+	}
 
 	/* Init specified USART unit */
-	init.enable 		= usartEnable;
-	init.refFreq		= 0;
-	init.baudrate		= UART_BAUDRATE;
-	init.oversampling	= USART_CTRL_OVS_X4;
-	init.databits		= USART_FRAME_DATABITS_EIGHT;
-	init.parity 		= USART_FRAME_PARITY_NONE;
-	init.stopbits		= USART_FRAME_STOPBITS_ONE;
-	USART_InitAsync(usart->usart_device, &init);
+	if (config & USART_STATE_SYNC)
+	{
+		init.sync.enable 		= usartEnable;
+		init.sync.refFreq		= 0;
+		init.sync.baudrate		= SPI_BAUDRATE;
+		init.sync.databits 		= usartDatabits8;
+		if (config & USART_STATE_MASTER)
+		{
+			init.sync.master 	= true;
+		}
+		else
+		{
+			init.sync.master	= false;
+		}
+		init.sync.msbf 			= true;
+		init.sync.clockMode 	= usartClockMode0; /* Clock idle low, sample on rising edge. */  
+		USART_InitSync(usart->usart_device, &init.sync);
+	}
+	else
+	{
+		init.async.enable 		= usartEnable;
+		init.async.refFreq		= 0;
+		init.async.baudrate		= UART_BAUDRATE;
+		init.async.oversampling	= USART_CTRL_OVS_X4;
+		init.async.databits		= USART_FRAME_DATABITS_EIGHT;
+		init.async.parity 		= USART_FRAME_PARITY_NONE;
+		init.async.stopbits		= USART_FRAME_STOPBITS_ONE;
+		USART_InitAsync(usart->usart_device, &init.async);
+	}
 
 	/* Clear RX/TX buffers */
 	usart->usart_device->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
@@ -900,17 +996,31 @@ void rt_hw_usart_init(void)
 {
 	struct efm32_usart_device_t	*usart;
 	rt_uint32_t 				flag;
-	rt_bool_t					console;
+	rt_uint8_t					config;
 
 	/* Register usart0 */
 #ifdef RT_USING_USART0
+	config = 0x00;
 	flag = RT_DEVICE_FLAG_RDWR;
 
+ #ifdef RT_USART0_SYNC_MODE
+	config |= USART_STATE_SYNC;
+  #if (RT_USART0_SYNC_MODE != 0x0UL)
+	config |= USART_STATE_MASTER;
+  #else
+	 flag |= RT_DEVICE_FLAG_INT_RX;
+  #endif
+ #else
+	 flag |= RT_DEVICE_FLAG_INT_RX;
+ #endif
+
+ #if (SPI_AUTOCS_ENABLE & (1 << 0))
+	config |= USART_STATE_AUTOCS;
+ #endif
+
  #if (RT_CONSOLE_DEVICE == 0x0UL)
-	console = true;
+	config |= USART_STATE_CONSOLE;
 	flag |= RT_DEVICE_FLAG_STREAM;
- #else
-	console = false;
  #endif
 
  #ifdef RT_USART0_USING_DMA
@@ -920,28 +1030,40 @@ void rt_hw_usart_init(void)
    #define RT_USART0_USING_DMA EFM32_NO_DATA
  #endif
 
-	flag |= RT_DEVICE_FLAG_INT_RX;
-
 	usart = rt_hw_usart_unit_init(
 		&usart0_device, 
 		0, 
 		RT_USING_USART0, 
 		flag, 
 		RT_USART0_USING_DMA, 
-		console);
+		config);
 
 	rt_hw_usart_register(&usart0_device, RT_USART0_NAME, flag, usart);
 #endif
 
 	/* Register usart1 */
 #ifdef RT_USING_USART1
+	config = 0x00;
 	flag = RT_DEVICE_FLAG_RDWR;
 
+ #ifdef RT_USART1_SYNC_MODE
+	config |= USART_STATE_SYNC;
+  #if (RT_USART1_SYNC_MODE != 0x0UL)
+	config |= USART_STATE_MASTER;
+  #else
+	 flag |= RT_DEVICE_FLAG_INT_RX;
+  #endif
+ #else
+	 flag |= RT_DEVICE_FLAG_INT_RX;
+ #endif
+
+ #if (SPI_AUTOCS_ENABLE & (1 << 1))
+	config |= USART_STATE_AUTOCS;
+ #endif
+
  #if (RT_CONSOLE_DEVICE == 0x1UL)
-	console = true;
+	config |= USART_STATE_CONSOLE;
 	flag |= RT_DEVICE_FLAG_STREAM;
- #else
-	console = false;
  #endif
 
  #ifdef RT_USART1_USING_DMA
@@ -951,8 +1073,6 @@ void rt_hw_usart_init(void)
 	
    #define RT_USART1_USING_DMA EFM32_NO_DATA
  #endif
-
-	flag |= RT_DEVICE_FLAG_INT_RX;
   
 	usart = rt_hw_usart_unit_init(
 		&usart1_device, 
@@ -960,22 +1080,36 @@ void rt_hw_usart_init(void)
 		RT_USING_USART1, 
 		flag, 
 		RT_USART1_USING_DMA, 
-		console);
+		config);
 
 	rt_hw_usart_register(&usart1_device, RT_USART1_NAME, flag, usart);
 #endif
 
 	/* Register usart2 */
 #ifdef RT_USING_USART2
+	config = 0x00;
 	flag = RT_DEVICE_FLAG_RDWR;
 
- #if (RT_CONSOLE_DEVICE == 0x2UL)
-	console = true;
-	flag |= RT_DEVICE_FLAG_STREAM;
+ #ifdef RT_USART2_SYNC_MODE
+	config |= USART_STATE_SYNC;
+  #if (RT_USART2_SYNC_MODE != 0x0UL)
+	config |= USART_STATE_MASTER;
+  #else
+	flag |= RT_DEVICE_FLAG_INT_RX;
+  #endif
  #else
-	console = false;
+	flag |= RT_DEVICE_FLAG_INT_RX;
  #endif
 
+#if (SPI_AUTOCS_ENABLE & (1 << 2))
+	config |= USART_STATE_AUTOCS;
+#endif
+
+#if (RT_CONSOLE_DEVICE == 0x2UL)
+	config |= USART_STATE_CONSOLE;
+	flag |= RT_DEVICE_FLAG_STREAM;
+#endif
+
  #ifdef RT_USART2_USING_DMA
  	RT_ASSERT(RT_USART2_USING_DMA < DMA_CHAN_COUNT);
 	flag |= RT_DEVICE_FLAG_DMA_TX;
@@ -985,15 +1119,13 @@ void rt_hw_usart_init(void)
    #define RT_USART2_USING_DMA EFM32_NO_DATA
  #endif
 
-	flag |= RT_DEVICE_FLAG_INT_RX;
-  
 	usart = rt_hw_usart_unit_init(
 		&usart2_device, 
 		2, 
 		RT_USING_USART2, 
 		flag, 
 		RT_USART2_USING_DMA, 
-		console);
+		config);
 
 	rt_hw_usart_register(&usart2_device, RT_USART2_NAME, flag, usart);
 #endif

+ 5 - 2
bsp/efm32/drv_usart.h

@@ -54,8 +54,11 @@ struct efm32_usart_device_t
 #define USART_WAIT_TIME_TX		(RT_TICK_PER_SECOND / 100 * 3)
 
 #define USART_STATE_CONSOLE 	(1 << 0)
-#define USART_STATE_TX_BUSY 	(1 << 1)
-#define USART_STATE_RX_BUSY 	(1 << 2)
+#define USART_STATE_SYNC		(1 << 1)
+#define USART_STATE_MASTER		(1 << 2)
+#define USART_STATE_AUTOCS 		(1 << 3)
+#define USART_STATE_TX_BUSY 	(1 << 4)
+#define USART_STATE_RX_BUSY 	(1 << 5)
 
 
 /* Exported functions --------------------------------------------------------- */

+ 1 - 1
bsp/efm32/hdl_interrupt.c

@@ -563,7 +563,7 @@ void I2C0_IRQHandler(void)
  * @note
  *
  *********************************************************************/
-rt_err_t efm32_irq_hook_register(efm32_irq_hook_init_t *hook)
+void efm32_irq_hook_register(efm32_irq_hook_init_t *hook)
 {
 	switch (hook->type)
 	{

+ 1 - 1
bsp/efm32/hdl_interrupt.h

@@ -55,7 +55,7 @@ typedef struct
 //void SVC_Handler(void);
 //void DebugMon_Handler(void);
 void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user);
-rt_err_t efm32_irq_hook_register(efm32_irq_hook_init_t *hook);
+void efm32_irq_hook_register(efm32_irq_hook_init_t *hook);
 
 #endif /* __HDL_INTERRUPT_H__ */
 

+ 19 - 6
bsp/efm32/rtconfig.h

@@ -39,7 +39,7 @@
 //#define RT_ADC_DEBUG
 //#define RT_ACMP_DEBUG
 //#define RT_TIMER_DEBUG
-//#define RT_USART_DEBUG
+#define RT_USART_DEBUG
 
 /* Using Hook */
 //#define RT_USING_HOOK
@@ -82,15 +82,28 @@
 
 /* USART Device for Console */
 #if defined(EFM32_G290_DK)
-#define RT_USING_USART0			0x2UL
-#define RT_USART0_NAME			"debug"
-#define RT_USART0_USING_DMA		0x0UL
+#define RT_USING_USART1			0x0UL
+#define RT_USART1_NAME			"debug"
+#define RT_USART1_USING_DMA		0x0UL
 #elif defined(EFM32_G890_STK)
 #define RT_USING_USART1			0x1UL
 #define RT_USART1_NAME			"debug"
 #define RT_USART1_USING_DMA		0x0UL
 #endif
 
+/* SECTION: SPI options */
+#if defined(EFM32_G290_DK)
+#define RT_USING_USART0			0x2UL
+#define RT_USART0_SYNC_MODE		0x1UL 	/* Master */
+#define RT_USART0_NAME			"spi0"
+#define RT_USART0_USING_DMA		0x1UL
+#elif defined(EFM32_G890_STK)
+//#define RT_USING_USART0			0x0UL
+//#define RT_USART0_SYNC_MODE		0x1UL 	/* Master */
+//#define RT_USART0_NAME			"spi0"
+//#define RT_USART0_USING_DMA		0x1UL
+#endif
+
 /* SECTION: RTC options */
 #if (defined(EFM32_G290_DK) || defined(EFM32_G890_STK))
 #define RT_USING_RTC
@@ -107,7 +120,7 @@
 
 /* SECTION: Serial options */
 #if defined(EFM32_G290_DK)
-#define RT_CONSOLE_DEVICE		0x0UL
+#define RT_CONSOLE_DEVICE		0x1UL
 #elif defined(EFM32_G890_STK)
 #define RT_CONSOLE_DEVICE		0x1UL
 #endif
@@ -125,4 +138,4 @@
 
 /* Exported functions --------------------------------------------------------- */
 
-#endif /* __RTTHREAD_CFG_H__ */
+#endif /* __RTTHREAD_CFG_H__ */

+ 2 - 2
bsp/efm32/rtconfig.py

@@ -8,8 +8,8 @@ if CROSS_TOOL == 'gcc':
 	EXEC_PATH 	= 'C:\Program Files (x86)\CodeSourcery\Sourcery G++ Lite\bin'
 
 BUILD = 'debug'
-EFM32_BOARD 	=  'EFM32_G890_STK'
-# EFM32_BOARD 	=  'EFM32_G290_DK'
+# EFM32_BOARD 	=  'EFM32_G890_STK'
+EFM32_BOARD 	=  'EFM32_G290_DK'
 
 if EFM32_BOARD == 'EFM32_G890_STK':
 	EFM32_TYPE = 'EFM32G890F128'