From 169c31fc4f22c12f1b74b17aec9d44ed65a752b9 Mon Sep 17 00:00:00 2001 From: "onelife.real" Date: Thu, 12 May 2011 07:19:37 +0000 Subject: [PATCH] *** 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 --- bsp/efm32/EFM32_Gxxx_DK/dvk.c | 62 ++++ bsp/efm32/EFM32_Gxxx_DK/dvk.h | 125 +++++++ bsp/efm32/EFM32_Gxxx_DK/dvk_bcregisters.h | 174 ++++++++++ bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.c | 248 ++++++++++++++ bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.h | 81 +++++ bsp/efm32/EFM32_Gxxx_DK/dvk_ebi.c | 237 +++++++++++++ bsp/efm32/EFM32_Gxxx_DK/dvk_spi.c | 230 +++++++++++++ bsp/efm32/SConscript | 13 +- bsp/efm32/application.c | 95 +++++- bsp/efm32/board.c | 10 + bsp/efm32/board.h | 53 ++- bsp/efm32/dev_led.c | 56 ++- bsp/efm32/dev_led.h | 6 +- bsp/efm32/dev_sflash.c | 355 +++++++++++++++++++ bsp/efm32/dev_sflash.h | 102 ++++++ bsp/efm32/drv_usart.c | 378 ++++++++++++++------- bsp/efm32/drv_usart.h | 7 +- bsp/efm32/hdl_interrupt.c | 2 +- bsp/efm32/hdl_interrupt.h | 2 +- bsp/efm32/rtconfig.h | 25 +- bsp/efm32/rtconfig.py | 4 +- 21 files changed, 2082 insertions(+), 183 deletions(-) create mode 100644 bsp/efm32/EFM32_Gxxx_DK/dvk.c create mode 100644 bsp/efm32/EFM32_Gxxx_DK/dvk.h create mode 100644 bsp/efm32/EFM32_Gxxx_DK/dvk_bcregisters.h create mode 100644 bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.c create mode 100644 bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.h create mode 100644 bsp/efm32/EFM32_Gxxx_DK/dvk_ebi.c create mode 100644 bsp/efm32/EFM32_Gxxx_DK/dvk_spi.c create mode 100644 bsp/efm32/dev_sflash.c create mode 100644 bsp/efm32/dev_sflash.h diff --git a/bsp/efm32/EFM32_Gxxx_DK/dvk.c b/bsp/efm32/EFM32_Gxxx_DK/dvk.c new file mode 100644 index 0000000000..c10fa09b4e --- /dev/null +++ b/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 + * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com + ****************************************************************************** + * + * 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 +} diff --git a/bsp/efm32/EFM32_Gxxx_DK/dvk.h b/bsp/efm32/EFM32_Gxxx_DK/dvk.h new file mode 100644 index 0000000000..bac1c9ecb0 --- /dev/null +++ b/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 + * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com + ****************************************************************************** + * + * 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 +#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 diff --git a/bsp/efm32/EFM32_Gxxx_DK/dvk_bcregisters.h b/bsp/efm32/EFM32_Gxxx_DK/dvk_bcregisters.h new file mode 100644 index 0000000000..b0f9357113 --- /dev/null +++ b/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 + * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com + ****************************************************************************** + * + * 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 + +/**************************************************************************//** + * 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 diff --git a/bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.c b/bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.c new file mode 100644 index 0000000000..b14e0fc44e --- /dev/null +++ b/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 + * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com + ****************************************************************************** + * + * 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_ + *****************************************************************************/ +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_ + *****************************************************************************/ +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_ + *****************************************************************************/ +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); +} diff --git a/bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.h b/bsp/efm32/EFM32_Gxxx_DK/dvk_boardcontrol.h new file mode 100644 index 0000000000..1323ceec1a --- /dev/null +++ b/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 + * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com + ****************************************************************************** + * + * 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 +#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 diff --git a/bsp/efm32/EFM32_Gxxx_DK/dvk_ebi.c b/bsp/efm32/EFM32_Gxxx_DK/dvk_ebi.c new file mode 100644 index 0000000000..1d37f358cf --- /dev/null +++ b/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 + * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com + ****************************************************************************** + * + * 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; +} diff --git a/bsp/efm32/EFM32_Gxxx_DK/dvk_spi.c b/bsp/efm32/EFM32_Gxxx_DK/dvk_spi.c new file mode 100644 index 0000000000..a3f9c4dafc --- /dev/null +++ b/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 + * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com + ****************************************************************************** + * + * 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 +#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; +} diff --git a/bsp/efm32/SConscript b/bsp/efm32/SConscript index 97f795f977..a9083c9362 100644 --- a/bsp/efm32/SConscript +++ b/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) diff --git a/bsp/efm32/application.c b/bsp/efm32/application.c index 8d519685a4..1688e42461 100644 --- a/bsp/efm32/application.c +++ b/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 #endif -#ifdef RT_USING_LWIP -#include -#include -#include +#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); } diff --git a/bsp/efm32/board.c b/bsp/efm32/board.c index 507a416ef6..a9a0f7648f 100644 --- a/bsp/efm32/board.c +++ b/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 */ diff --git a/bsp/efm32/board.h b/bsp/efm32/board.h index be56bcc326..fb4e9b08f1 100644 --- a/bsp/efm32/board.h +++ b/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 +#if defined(EFM32_G290_DK) +#include +#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 */ diff --git a/bsp/efm32/dev_led.c b/bsp/efm32/dev_led.c index 060e6644d0..c1cceb92e8 100644 --- a/bsp/efm32/dev_led.c +++ b/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.) diff --git a/bsp/efm32/dev_led.h b/bsp/efm32/dev_led.h index 14b6ccc1f3..9bc7190e4a 100644 --- a/bsp/efm32/dev_led.h +++ b/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 --------------------------------------------------------- */ diff --git a/bsp/efm32/dev_sflash.c b/bsp/efm32/dev_sflash.c new file mode 100644 index 0000000000..fa79ce6883 --- /dev/null +++ b/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 + +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) */ + +/******************************************************************//** + * @} +*********************************************************************/ diff --git a/bsp/efm32/dev_sflash.h b/bsp/efm32/dev_sflash.h new file mode 100644 index 0000000000..1a10999331 --- /dev/null +++ b/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__ */ diff --git a/bsp/efm32/drv_usart.c b/bsp/efm32/drv_usart.c index 2119af6860..26997bf3dc 100644 --- a/bsp/efm32/drv_usart.c +++ b/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 diff --git a/bsp/efm32/drv_usart.h b/bsp/efm32/drv_usart.h index 134b094c3c..e0e844b52c 100644 --- a/bsp/efm32/drv_usart.h +++ b/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 --------------------------------------------------------- */ diff --git a/bsp/efm32/hdl_interrupt.c b/bsp/efm32/hdl_interrupt.c index ea8e388909..2b3894a283 100644 --- a/bsp/efm32/hdl_interrupt.c +++ b/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) { diff --git a/bsp/efm32/hdl_interrupt.h b/bsp/efm32/hdl_interrupt.h index 13f33c947b..6003e8dd2d 100644 --- a/bsp/efm32/hdl_interrupt.h +++ b/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__ */ diff --git a/bsp/efm32/rtconfig.h b/bsp/efm32/rtconfig.h index d23f515c18..b24b25b9cb 100644 --- a/bsp/efm32/rtconfig.h +++ b/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__ */ \ No newline at end of file +#endif /* __RTTHREAD_CFG_H__ */ diff --git a/bsp/efm32/rtconfig.py b/bsp/efm32/rtconfig.py index 61bc0ea801..c98e1d3b30 100644 --- a/bsp/efm32/rtconfig.py +++ b/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' -- GitLab