From 19e3ce5ee3ca5759d7e70c26a675438a29029478 Mon Sep 17 00:00:00 2001 From: "onelife.real" Date: Fri, 29 Jul 2011 02:47:37 +0000 Subject: [PATCH] *** EFM32 branch *** 1. Add interrupt context check function (context_gcc.S) 2. Add lock (semaphore) for IIC, USART and Ethernet drivers to prevent simultaneously access 3. Add multiple channels support for scan mode of ADC driver 4. Modify miscellaneous drivers according to ADC driver changes 5. Add SWO output enable function (board.c) 6. Disable all interrupts in GPIO interrupt handler (hdl_interrupt.c) 7. Add two Ethernet utility functions (drv_ethernet.c) 8. Add accelerometer driver (analog output) 9. Add accelerometer demo (draft, application.c) git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1654 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- bsp/efm32/Readme.txt | 8 +- bsp/efm32/SConscript | 2 +- bsp/efm32/application.c | 61 +- bsp/efm32/board.c | 159 +++-- bsp/efm32/board.h | 46 +- bsp/efm32/dev_accel.c | 266 ++++++++ bsp/efm32/dev_accel.h | 40 ++ bsp/efm32/dev_misc.c | 58 +- bsp/efm32/drv_adc.c | 934 +++++++++++++++++++---------- bsp/efm32/drv_adc.h | 43 +- bsp/efm32/drv_ethernet.c | 275 ++++++++- bsp/efm32/drv_ethernet.h | 2 +- bsp/efm32/drv_iic.c | 300 +++++---- bsp/efm32/drv_iic.h | 42 +- bsp/efm32/drv_usart.c | 286 ++++++--- bsp/efm32/drv_usart.h | 28 +- bsp/efm32/hdl_interrupt.c | 211 ++++--- bsp/efm32/httpd.c | 5 +- bsp/efm32/rtconfig.h | 43 +- libcpu/arm/cortex-m3/context_gcc.S | 50 +- 20 files changed, 2076 insertions(+), 783 deletions(-) create mode 100644 bsp/efm32/dev_accel.c create mode 100644 bsp/efm32/dev_accel.h diff --git a/bsp/efm32/Readme.txt b/bsp/efm32/Readme.txt index 234360105b..88bc49d0f2 100644 --- a/bsp/efm32/Readme.txt +++ b/bsp/efm32/Readme.txt @@ -14,4 +14,10 @@ #define EFM32_USING_ETHERNET #define RT_USING_LWIP #RT_LWIP_* -3. and then compile \ No newline at end of file +3. please also turn on the following define to use simple http server + #define EFM32_USING_ETH_HTTPD + or turn on the following defines to use EFM32 Ethernet utility functions (due to memory limitation, you may not turn on both) + #define EFM32_USING_ETH_UTILS + #define hostName "onelife.dyndns.org" /* Please change to your own host name */ + #define userPwdB64 "dXNlcjpwYXNzd2Q=" /* Please change to your own user name and password (base 64 encoding) */ +4. and then compile \ No newline at end of file diff --git a/bsp/efm32/SConscript b/bsp/efm32/SConscript index c968b15dff..00ab59d67b 100644 --- a/bsp/efm32/SConscript +++ b/bsp/efm32/SConscript @@ -12,7 +12,7 @@ else: src_bsp = ['application.c', 'startup.c', 'board.c'] src_drv1 = ['drv_dma.c', 'drv_rtc.c', 'drv_adc.c', 'drv_acmp.c', 'drv_usart.c', 'drv_iic.c', 'drv_timer.c'] src_drv2 = ['drv_sdcard.c', 'drv_ethernet.c'] -src_dev = ['dev_misc.c', 'dev_led.c', 'dev_sflash.c'] +src_dev = ['dev_misc.c', 'dev_led.c', 'dev_accel.c', 'dev_sflash.c'] src_hdl = ['hdl_interrupt.c'] src_app = ['httpd.c'] diff --git a/bsp/efm32/application.c b/bsp/efm32/application.c index 3d13a6290f..0465f72bc3 100644 --- a/bsp/efm32/application.c +++ b/bsp/efm32/application.c @@ -14,6 +14,8 @@ * 2009-01-05 Bernard first version * 2010-12-29 onelife Modify for EFM32 * 2011-05-06 onelife Add SPI Flash DEMO + * 2011-07-15 onelife Add accelerometer DEMO + * 2011-07-27 onelife Modify Ethernet DEMO ******************************************************************************/ /***************************************************************************//** @@ -34,6 +36,9 @@ #endif #include "dev_led.h" +#if defined(EFM32_USING_ACCEL) +#include "dev_accel.h" +#endif #if defined(EFM32_USING_SFLASH) #include "dev_sflash.h" #endif @@ -48,12 +53,28 @@ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ -rt_uint32_t rt_system_status = 0; +volatile rt_uint32_t rt_system_status = 0; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ void rt_demo_thread_entry(void* parameter) { +#if 0 //defined(EFM32_USING_ACCEL) + struct efm32_accel_result_t result; + + rt_kprintf(">>> waiting\n"); + rt_thread_sleep(6000); + rt_kprintf(">>> start\n"); + while(1) + { + efm_accel_get_data(&result); + rt_kprintf("Accel x: %x\n", result.x); + rt_kprintf("Accel y: %x\n", result.y); + rt_kprintf("Accel z: %x\n\n", result.z); + rt_thread_sleep(200); + } +#endif + #if defined(RT_USING_DFS) /* Filesystem Initialization */ dfs_init(); @@ -114,23 +135,42 @@ void rt_demo_thread_entry(void* parameter) #endif #if defined(EFM32_USING_ETHERNET) + extern void lwip_sys_init(void); +#if defined(EFM32_USING_ETH_HTTPD) extern void httpd_init(void); +#endif rt_device_t eth = RT_NULL; + /* find Ethernet device */ eth = rt_device_find(ETH_DEVICE_NAME); if (eth != RT_NULL) { + /* init Ethernet device */ eth->init(eth); + rt_kprintf("Ethernet init OK!\n"); + + /* init lwip system */ + lwip_sys_init(); + rt_kprintf("TCP/IP stack init OK!\n"); + +#if defined(EFM32_USING_ETH_HTTPD) + /* init http server */ httpd_init(); rt_kprintf("Http service init OK!\n"); +#endif } else { rt_kprintf("%s is not found\n"), ETH_DEVICE_NAME; } -#endif +#endif /* defined(EFM32_USING_ETHERNET) */ rt_kprintf("Demo End\n"); + + while(1) + { + rt_thread_sleep(10); + } } void rt_led_thread_entry(void* parameter) @@ -158,6 +198,14 @@ int rt_application_init() { rt_thread_t demo_thread, led_thread; +#if defined(EFM32_USING_ACCEL) + if (efm_accel_init() != RT_EOK) + { + rt_kprintf("*** Init accelerometer driver failed!"); + while(1); //Or do something? + } +#endif + #if defined(EFM32_USING_SFLASH) if (efm_spiFlash_init() != RT_EOK) { @@ -180,7 +228,7 @@ int rt_application_init() rt_kprintf("*** Init LED driver failed!"); while(1); //Or do something? } -#if defined(RT_USING_ADC0) +#if defined(RT_USING_MISC) if (rt_hw_misc_init() != RT_EOK) { rt_kprintf("*** Init miscellaneous driver failed!"); @@ -190,8 +238,6 @@ int rt_application_init() #if defined(RT_USING_LWIP) { - extern void lwip_sys_init(void); - /* Create Ethernet Threads */ if (eth_system_device_init() != RT_EOK) { @@ -205,9 +251,6 @@ int rt_application_init() while(1); //Or do something? } #endif - /* init lwip system */ - lwip_sys_init(); - rt_kprintf("TCP/IP stack init OK!\n"); } #endif @@ -216,7 +259,7 @@ int rt_application_init() "demo", rt_demo_thread_entry, RT_NULL, - 512, + 1024, 3, 20); diff --git a/bsp/efm32/board.c b/bsp/efm32/board.c index e5ef9a7d37..ea794e5436 100644 --- a/bsp/efm32/board.c +++ b/bsp/efm32/board.c @@ -1,53 +1,54 @@ -/******************************************************************//** - * @file board.c - * @brief USART driver of RT-Thread RTOS for EFM32 +/***************************************************************************//** + * @file board.c + * @brief Board support of RT-Thread RTOS for EFM32 * COPYRIGHT (C) 2011, RT-Thread Development Team * @author onelife - * @version 0.4 beta - ********************************************************************** + * @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 - ********************************************************************** + * 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-12-21 onelife Initial creation for EFM32 * 2011-05-06 onelife Add EFM32 development kit and SPI Flash support - *********************************************************************/ + * 2011-07-12 onelife Add SWO output enable function + ******************************************************************************/ -/******************************************************************//** -* @addtogroup efm32 -* @{ -*********************************************************************/ +/***************************************************************************//** + * @addtogroup efm32 + * @{ + ******************************************************************************/ -/* Includes -------------------------------------------------------------------*/ +/* Includes ------------------------------------------------------------------*/ #include "board.h" -/* Private typedef -------------------------------------------------------------*/ -/* Private define --------------------------------------------------------------*/ +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ #define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == RAM_MEM_BASE) || \ ((VECTTAB) == FLASH_MEM_BASE)) #define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) -/******************************************************************//** -* @addtogroup SysTick_clock_source -* @{ -*********************************************************************/ +/***************************************************************************//** + * @addtogroup SysTick_clock_source + * @{ + ******************************************************************************/ #define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) #define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) #define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) -/******************************************************************//** +/***************************************************************************//** * @} -*********************************************************************/ + ******************************************************************************/ -/* Private macro --------------------------------------------------------------*/ -/* Private variables ------------------------------------------------------------*/ -/* Private function prototypes ---------------------------------------------------*/ -/* Private functions ------------------------------------------------------------*/ -/******************************************************************//** +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/***************************************************************************//** * @brief - * Set the allocation and offset of the vector table + * Set the allocation and offset of the vector table * * @details * @@ -57,9 +58,11 @@ * Indicate the vector table is allocated in RAM or ROM * * @param[in] Offset - * The vector table offset - *********************************************************************/ -static void NVIC_SetVectorTable(rt_uint32_t NVIC_VectTab, rt_uint32_t Offset) + * The vector table offset + ******************************************************************************/ +static void NVIC_SetVectorTable( + rt_uint32_t NVIC_VectTab, + rt_uint32_t Offset) { /* Check the parameters */ RT_ASSERT(IS_NVIC_VECTTAB(NVIC_VectTab)); @@ -68,15 +71,15 @@ static void NVIC_SetVectorTable(rt_uint32_t NVIC_VectTab, rt_uint32_t Offset) SCB->VTOR = NVIC_VectTab | (Offset & (rt_uint32_t)0x1FFFFF80); } -/******************************************************************//** +/***************************************************************************//** * @brief - * Configure the address of vector table + * Configure the address of vector table * * @details * * @note * - *********************************************************************/ + ******************************************************************************/ static void NVIC_Configuration(void) { #ifdef VECT_TAB_RAM @@ -87,23 +90,24 @@ static void NVIC_Configuration(void) NVIC_SetVectorTable(FLASH_MEM_BASE, 0x0); #endif - /* Set NVIC Preemption Priority Bits: 0 bit for pre-emption, 4 bits for subpriority */ + /* Set NVIC Preemption Priority Bits: 0 bit for pre-emption, 4 bits for + subpriority */ NVIC_SetPriorityGrouping(0x7UL); /* Set Base Priority Mask Register */ __set_BASEPRI(EFM32_BASE_PRI_DEFAULT); } -/******************************************************************//** +/***************************************************************************//** * @brief - * Enable high frequency crystal oscillator (HFXO), and set HFCLK domain to use HFXO as - * source. + * Enable high frequency crystal oscillator (HFXO), and set HFCLK domain to + * use HFXO as source. * * @details * * @note * - *********************************************************************/ + ******************************************************************************/ static void switchToHFXO(void) { CMU_TypeDef *cmu = CMU; @@ -122,9 +126,9 @@ static void switchToHFXO(void) cmu->OSCENCMD = CMU_OSCENCMD_HFRCODIS; } -/******************************************************************//** +/***************************************************************************//** * @brief - * Configure the SysTick clock source + * Configure the SysTick clock source * * @details * @@ -138,7 +142,7 @@ static void switchToHFXO(void) * * @arg SysTick_CLKSource_HCLK * AHB clock selected as SysTick clock source. - *********************************************************************/ + ******************************************************************************/ static void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) { /* Check the parameters */ @@ -154,15 +158,15 @@ static void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) } } -/******************************************************************//** +/***************************************************************************//** * @brief - * Configure the SysTick for OS tick. + * Configure the SysTick for OS tick. * * @details * * @note * - *********************************************************************/ + ******************************************************************************/ static void SysTick_Configuration(void) { rt_uint32_t core_clock; @@ -176,15 +180,58 @@ static void SysTick_Configuration(void) SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); } -/******************************************************************//** +/***************************************************************************//** * @brief - * Initialize the board. + * Enable SWO. * * @details * * @note * - *********************************************************************/ + ******************************************************************************/ +void setupSWO(void) +{ + rt_uint32_t *dwt_ctrl = (rt_uint32_t *) 0xE0001000; + rt_uint32_t *tpiu_prescaler = (rt_uint32_t *) 0xE0040010; + rt_uint32_t *tpiu_protocol = (rt_uint32_t *) 0xE00400F0; + + CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO; + /* Enable Serial wire output pin */ + GPIO->ROUTE |= GPIO_ROUTE_SWOPEN; + /* Set location 1 */ + GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC1; + /* Enable output on pin */ + GPIO->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE15_MASK); + GPIO->P[2].MODEH |= GPIO_P_MODEH_MODE15_PUSHPULL; + /* Enable debug clock AUXHFRCO */ + CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN; + + while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY)); + + /* Enable trace in core debug */ + CoreDebug->DHCSR |= 1; + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Enable PC and IRQ sampling output */ + *dwt_ctrl = 0x400113FF; + /* Set TPIU prescaler to 16. */ + *tpiu_prescaler = 0xf; + /* Set protocol to NRZ */ + *tpiu_protocol = 2; + /* Unlock ITM and output data */ + ITM->LAR = 0xC5ACCE55; + ITM->TCR = 0x10009; +} + +/***************************************************************************//** + * @brief + * Initialize the board. + * + * @details + * + * @note + * + ******************************************************************************/ void rt_hw_board_init(void) { /* Chip errata */ @@ -205,15 +252,15 @@ void rt_hw_board_init(void) SysTick_Configuration(); } -/******************************************************************//** +/***************************************************************************//** * @brief - * Initialize the hardware drivers. + * Initialize the hardware drivers. * * @details * * @note * - *********************************************************************/ + ******************************************************************************/ void rt_hw_driver_init(void) { CMU_ClockEnable(cmuClock_HFPER, true); @@ -224,6 +271,11 @@ void rt_hw_driver_init(void) /* Enabling clock to the interface of the low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); +#ifdef EFM32_SWO_ENABLE + /* Enable SWO */ + setupSWO(); +#endif + /* Initialize DMA */ rt_hw_dma_init(); @@ -265,7 +317,6 @@ void rt_hw_driver_init(void) #endif } -/******************************************************************//** +/***************************************************************************//** * @} -*********************************************************************/ - + ******************************************************************************/ diff --git a/bsp/efm32/board.h b/bsp/efm32/board.h index 3ba7529cd5..a0c95e805e 100644 --- a/bsp/efm32/board.h +++ b/bsp/efm32/board.h @@ -1,19 +1,21 @@ -/******************************************************************//** - * @file drv_dma.h - * @brief USART driver of RT-Thread RTOS for EFM32 +/***************************************************************************//** + * @file board.h + * @brief Board support of RT-Thread RTOS for EFM32 * 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 - ********************************************************************** + * 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-12-21 onelife Initial creation for EFM32 * 2011-05-06 onelife Add EFM32 development kit and SPI Flash support - *********************************************************************/ + * 2011-07-12 onelife Add prototype for SWO output enable and interrupt + * context check functions + ******************************************************************************/ #ifndef __BOARD_H__ #define __BOARD_H__ @@ -24,7 +26,7 @@ #error Unknown MCU type #endif -/* Includes -------------------------------------------------------------------*/ +/* Includes ------------------------------------------------------------------*/ #include #include #include @@ -44,18 +46,22 @@ #include #endif -/* Exported types -------------------------------------------------------------*/ -/* Exported constants ---------------------------------------------------------*/ -/* Exported variables ----------------------------------------------------------*/ -extern rt_uint32_t rt_system_status; +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported variables --------------------------------------------------------*/ +extern volatile rt_uint32_t rt_system_status; -/* Exported macro -------------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +#ifdef EFM32_DEBUG #define DEBUG_EFM #define DEBUG_EFM_USER +#define EFM32_SWO_ENABLE +#endif #define EFM32_NO_DATA (0) -#define EFM32_NO_OFFSET (-1) #define EFM32_NO_POINTER (RT_NULL) +#define EFM32_NO_OFFSET (-1) +#define EFM32_NO_DMA (-1) /* SECTION: SPI Flash */ #if defined(EFM32_USING_SFLASH) @@ -79,7 +85,7 @@ extern rt_uint32_t rt_system_status; #endif /* SECTION: SYSTEM */ -#define EFM32_SRAM_END (RAM_MEM_BASE + SRAM_SIZE) +#define EFM32_SRAM_END (SRAM_BASE + SRAM_SIZE) #define EFM32_BASE_PRI_DEFAULT (0x0UL << 5) #define EFM32_IRQ_PRI_DEFAULT (0x4UL << 5) #if (defined(EFM32_G890_STK) || defined(EFM32_G290_DK)) @@ -95,6 +101,7 @@ extern rt_uint32_t rt_system_status; #define UART_BAUDRATE (115200) /* SUBSECTION: SPI */ +/* Max SPI clock: HFPERCLK/2 for master, HFPERCLK/8 for slave */ #define SPI_BAUDRATE (4000000) #ifndef USART_0_AUTOCS @@ -107,7 +114,9 @@ extern rt_uint32_t rt_system_status; #define USART_2_AUTOCS (0) #endif /* Auto Slave Select */ -#define SPI_AUTOCS_ENABLE ((USART_2_AUTOCS << 2) | (USART_1_AUTOCS << 1) | (USART_0_AUTOCS << 0)) +#define SPI_AUTOCS_ENABLE ((USART_2_AUTOCS << 2) | \ + (USART_1_AUTOCS << 1) | \ + (USART_0_AUTOCS << 0)) /* SECTION: I2C */ #define IIC_RX_BUFFER_SIZE (32) @@ -161,8 +170,9 @@ extern rt_uint32_t rt_system_status; #define RT_DEVICE_CTRL_ACMP_INIT (0xF6) /*!< Initialize ACMP */ #define RT_DEVICE_CTRL_ACMP_OUTPUT (0xF7) /*!< get ACMP output */ -/* Exported functions --------------------------------------------------------- */ +/* Exported functions ------------------------------------------------------- */ void rt_hw_board_init(void); void rt_hw_driver_init(void); +rt_uint32_t rt_hw_interrupt_check(void); #endif /*__BOARD_H__ */ diff --git a/bsp/efm32/dev_accel.c b/bsp/efm32/dev_accel.c new file mode 100644 index 0000000000..b0423e227c --- /dev/null +++ b/bsp/efm32/dev_accel.c @@ -0,0 +1,266 @@ +/***************************************************************************//** + * @file dev_accel.c + * @brief Accelerometer driver of RT-Thread RTOS for EFM32 + * 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 + * 2011-07-13 onelife Initial creation for using EFM32 ADC module to + * interface the Freescale MMA7361L + ******************************************************************************/ + +/***************************************************************************//** + * @addtogroup efm32 + * @{ + ******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "board.h" +#include "drv_adc.h" +#include "dev_accel.h" + +#if defined(EFM32_USING_ACCEL) +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +#ifdef RT_ACCEL_DEBUG +#define accel_debug(format,args...) rt_kprintf(format, ##args) +#else +#define accel_debug(format,args...) +#endif + +/* Private constants ---------------------------------------------------------*/ +static rt_device_t accel; +static struct efm32_adc_control_t control = \ + {ADC_MODE_SCAN, {3, ACCEL_USING_DMA}, {}}; +static struct efm32_accel_result_t accelOffset = {0}; +static rt_bool_t accelInTime = true; + +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/***************************************************************************//** + * @brief + * Get accelerometer output + * + * @details + * + * @note + * + * @param[out] data + * Pointer to output buffer + * + * @return + * Error code + ******************************************************************************/ +rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data) +{ + RT_ASSERT(accel != RT_NULL); + + struct efm32_adc_result_t result; + + if (data == RT_NULL) + { + return -RT_ERROR; + } + + result.mode = control.mode; + result.buffer = (void *)data; + accel->control(accel, RT_DEVICE_CTRL_RESUME, &result); + accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, &result); + + return RT_EOK; +} + +/***************************************************************************//** + * @brief + * Accelerometer timeout interrupt handler + * + * @details + * + * @note + * + * @param[in] parameter + * Parameter + ******************************************************************************/ +static void efm_accel_timer(void* parameter) +{ + accelInTime = false; +} + +/***************************************************************************//** + * @brief + * Accelerometer auto-zero calibration function + * + * @details + * + * @note + * + * @param[in] period + * Time period to perform auto-zero calibration + * + * @return + * Error code + ******************************************************************************/ +rt_err_t efm_accel_auto_zero(rt_tick_t period) +{ + RT_ASSERT(accel != RT_NULL); + + rt_timer_t calTimer; + struct efm32_accel_result_t min = {0x7ff, 0x7ff, 0x7ff}; + struct efm32_accel_result_t max = {0x7ff, 0x7ff, 0x7ff}; + struct efm32_accel_result_t temp; + struct efm32_adc_result_t result; + + if ((calTimer = rt_timer_create( + "cal_tmr", + efm_accel_timer, + RT_NULL, + period, + RT_TIMER_FLAG_ONE_SHOT)) == RT_NULL) + { + accel_debug("Accel err: Create timer failed!\n"); + return -RT_ERROR; + } + + result.mode = control.mode; + result.buffer = (void *)&temp; + accelInTime = true; + rt_timer_start(calTimer); + do + { + accel->control(accel, RT_DEVICE_CTRL_RESUME, &result); + accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, &result); + if (temp.x < min.x) + { + min.x = temp.x; + } + if (temp.y < min.y) + { + min.y = temp.y; + } + if (temp.z < min.z) + { + min.z = temp.z; + } + if (temp.x > max.x) + { + max.x = temp.x; + } + if (temp.y > max.y) + { + max.y = temp.y; + } + if (temp.z > max.z) + { + max.z = temp.z; + } + rt_thread_sleep(1); + } while (accelInTime); + + accelOffset.x = (min.x + max.x) >> 1; + accelOffset.y = (min.y + max.y) >> 1; + accelOffset.z = (min.z + max.z) >> 1; + accel_debug("Accel: Min %x %x %x, max %x %x %x, Offset %x %x %x\n", + min.x, min.y, min.z, max.x, max.y, max.z, + accelOffset.x, accelOffset.y, accelOffset.z); + + rt_timer_delete(calTimer); + return RT_EOK; +} + +/***************************************************************************//** + * @brief + * Initialize the accelerometer + * + * @details + * + * @note + * + * @return + * Error code + ******************************************************************************/ +rt_err_t efm_accel_init(void) +{ + ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT; + +#if defined(EFM32_G290_DK) + /* Enable accelerometer */ + DVK_enablePeripheral(DVK_ACCEL); + /* Select low g-range */ + DVK_disablePeripheral(DVK_ACCEL_GSEL); +#endif + + do + { + /* Find ADC device */ + accel = rt_device_find(ACCEL_USING_DEVICE_NAME); + if (accel == RT_NULL) + { + accel_debug("Accel err: Can't find device: %s!\n", ACCEL_USING_DEVICE_NAME); + break; + } + accel_debug("Accel: Find device %s\n", ACCEL_USING_DEVICE_NAME); + + /* Init ADC for scan mode */ + scanInit.reference = adcRefVDD; + scanInit.input = ACCEL_X_ADC_CH | ACCEL_Y_ADC_CH | ACCEL_Z_ADC_CH; + + control.scan.init = &scanInit; + accel->control(accel, RT_DEVICE_CTRL_ADC_MODE, &control); + + accel_debug("Accel: Init OK\n"); + return RT_EOK; + } while (0); + + accel_debug("Accel err: Init failed!\n"); + return -RT_ERROR; +} + +/******************************************************************************* + * Export to FINSH + ******************************************************************************/ +#ifdef RT_USING_FINSH +#include + +void accel_cal(rt_uint32_t second) +{ + efm_accel_auto_zero(RT_TICK_PER_SECOND * second); + + rt_kprintf("Calibration done. Offset: 0x%03x, 0x%03x, 0x%03x\n", + accelOffset.x, accelOffset.y, accelOffset.z); +} +FINSH_FUNCTION_EXPORT(accel_cal, auto-zero calibration.) + +void list_accel(void) +{ + struct efm32_accel_result_t temp; + rt_int32_t x, y, z; + + if ((accelOffset.x == 0) && \ + (accelOffset.y == 0) && \ + (accelOffset.z == 0)) + { + rt_kprintf("Please calibrate the device first!\n"); + return; + } + efm_accel_get_data(&temp); + x = temp.x - accelOffset.x; + y = temp.y - accelOffset.y; + z = temp.z - accelOffset.z; + + rt_kprintf("X: %d, Y: %d, Z: %d\n", x, y, z); +} +FINSH_FUNCTION_EXPORT(list_accel, list accelerometer info.) +#endif + +#endif +/***************************************************************************//** + * @} + ******************************************************************************/ diff --git a/bsp/efm32/dev_accel.h b/bsp/efm32/dev_accel.h new file mode 100644 index 0000000000..2950ce354d --- /dev/null +++ b/bsp/efm32/dev_accel.h @@ -0,0 +1,40 @@ +/***************************************************************************//** + * @file dev_accel.h + * @brief Accelerometer driver of RT-Thread RTOS for EFM32 + * 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 + * 2011-07-13 onelife Initial creation for using EFM32 ADC module to + * interface the Freescale MMA7361L + ******************************************************************************/ +#ifndef __DEV_ACCEL_H__ +#define __DEV_ACCEL_H__ + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +struct efm32_accel_result_t +{ + rt_uint32_t x; + rt_uint32_t y; + rt_uint32_t z; +}; + +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +#define ACCEL_X_ADC_CH ADC_SCANCTRL_INPUTMASK_CH2 +#define ACCEL_Y_ADC_CH ADC_SCANCTRL_INPUTMASK_CH3 +#define ACCEL_Z_ADC_CH ADC_SCANCTRL_INPUTMASK_CH4 + +/* Exported functions ------------------------------------------------------- */ +rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data); +rt_err_t efm_accel_auto_zero(rt_tick_t period); +rt_err_t efm_accel_init(void); + +#endif /*__DEV_ACCEL_H__ */ diff --git a/bsp/efm32/dev_misc.c b/bsp/efm32/dev_misc.c index f1031342a0..1181ec6606 100644 --- a/bsp/efm32/dev_misc.c +++ b/bsp/efm32/dev_misc.c @@ -12,6 +12,7 @@ * @section Change Logs * Date Author Notes * 2011-02-22 onelife Initial creation for EFM32 + * 2011-07-27 onelife Modify according to ADC driver changes ******************************************************************************/ /***************************************************************************//** @@ -23,6 +24,7 @@ #include "board.h" #include "drv_adc.h" +#if defined(RT_USING_MISC) /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ @@ -33,8 +35,9 @@ #endif /* Private constants ---------------------------------------------------------*/ -static rt_device_t adc0; -static struct efm32_adc_control_t control = {ADC_MODE_SINGLE}; +static rt_device_t adc0; +static struct efm32_adc_control_t control = \ + {ADC_MODE_SINGLE, {}, {0, (rt_uint8_t)EFM32_NO_DMA}}; /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ @@ -55,8 +58,9 @@ rt_int32_t efm32_misc_getCelsius(rt_uint32_t adcSample); ******************************************************************************/ rt_int32_t rt_hw_get_temp(void) { - ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; - rt_uint32_t temp; + ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; + struct efm32_adc_result_t result; + rt_uint32_t temp; /* Set input to temperature sensor. Acquisition time must be 256 cycles. Reference must be 1.25V */ @@ -64,10 +68,12 @@ rt_int32_t rt_hw_get_temp(void) singleInit.reference = adcRef1V25; singleInit.input = adcSingleInpTemp; - control.singleInit = &singleInit; + control.single.init = &singleInit; adc0->control(adc0, RT_DEVICE_CTRL_ADC_MODE, &control); - adc0->control(adc0, RT_DEVICE_CTRL_RESUME, EFM32_NO_POINTER); - adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &temp); + result.mode = control.mode; + result.buffer = (void *)&temp; + adc0->control(adc0, RT_DEVICE_CTRL_RESUME, &result); + adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &result); return efm32_misc_getCelsius(temp); } @@ -86,18 +92,21 @@ rt_int32_t rt_hw_get_temp(void) ******************************************************************************/ rt_uint32_t rt_hw_get_vdd(void) { - ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; - rt_uint32_t vdd; + ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; + struct efm32_adc_result_t result; + rt_uint32_t vdd; /* Set input to temperature sensor. Reference must be 1.25V */ singleInit.acqTime = adcAcqTime32; singleInit.reference = adcRef1V25; singleInit.input = adcSingleInpVDDDiv3; - control.singleInit = &singleInit; + control.single.init = &singleInit; adc0->control(adc0, RT_DEVICE_CTRL_ADC_MODE, &control); - adc0->control(adc0, RT_DEVICE_CTRL_RESUME, EFM32_NO_POINTER); - adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &vdd); + result.mode = control.mode; + result.buffer = (void *)&vdd; + adc0->control(adc0, RT_DEVICE_CTRL_RESUME, &result); + adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &result); return (vdd * 125 * 3) / 4096; } @@ -115,18 +124,22 @@ rt_uint32_t rt_hw_get_vdd(void) ******************************************************************************/ rt_err_t rt_hw_misc_init(void) { - adc0 = rt_device_find(RT_ADC0_NAME); - if (adc0 == RT_NULL) + do { - misc_debug("Batt err: Can't find device: %s!\n", RT_ADC0_NAME); - goto MISC_INIT_ERROR; - } - return RT_EOK; + /* Find ADC device */ + adc0 = rt_device_find(RT_ADC0_NAME); + if (adc0 == RT_NULL) + { + misc_debug("Batt err: Can't find device: %s!\n", RT_ADC0_NAME); + break; + } + misc_debug("Batt: Find device %s\n", RT_ADC0_NAME); + + return RT_EOK; + } while (0); -MISC_INIT_ERROR: misc_debug("Misc err: Init failed!\n"); return -RT_ERROR; - } /***************************************************************************//** @@ -161,7 +174,7 @@ rt_int32_t efm32_misc_getCelsius(rt_uint32_t adcResult) return (cal_temp - (cal_value - (rt_int32_t)adcResult * 10000) / t_grad); } -/***************************************************************************//** +/******************************************************************************* * Export to FINSH ******************************************************************************/ #ifdef RT_USING_FINSH @@ -183,8 +196,9 @@ void list_vdd(void) } FINSH_FUNCTION_EXPORT(list_vdd, list current VDD value.) -#endif +#endif /* RT_USING_FINSH */ +#endif /* defined(RT_USING_MISC) */ /***************************************************************************//** * @} ******************************************************************************/ diff --git a/bsp/efm32/drv_adc.c b/bsp/efm32/drv_adc.c index d39cbd92e4..17484cc4e0 100644 --- a/bsp/efm32/drv_adc.c +++ b/bsp/efm32/drv_adc.c @@ -12,6 +12,7 @@ * @section Change Logs * Date Author Notes * 2011-02-21 onelife Initial creation for EFM32 + * 2011-07-14 onelife Add multiple channels support for scan mode ******************************************************************************/ /***************************************************************************//** @@ -35,312 +36,12 @@ /* Private variables ---------------------------------------------------------*/ #ifdef RT_USING_ADC0 - static struct rt_device adc0_device; +static struct rt_device adc0_device; #endif +static rt_uint32_t adcErrataShift = 0; /* Private function prototypes -----------------------------------------------*/ -rt_uint32_t efm32_adc_calibration( - ADC_TypeDef *adc, - ADC_Ref_TypeDef ref, - ADC_SingleInput_TypeDef input); - /* Private functions ---------------------------------------------------------*/ -/***************************************************************************//** - * @brief - * Initialize ADC device - * - * @details - * - * @note - * - * @param[in] dev - * Pointer to device descriptor - * - * @return - * Error code - ******************************************************************************/ - static rt_err_t rt_adc_init(rt_device_t dev) -{ - RT_ASSERT(dev != RT_NULL); - - rt_uint32_t temp; - - struct efm32_adc_device_t *adc; - - adc = (struct efm32_adc_device_t *)(dev->user_data); - - temp = efm32_adc_calibration(adc->adc_device, ADC_CALI_REF, ADC_CALI_CH); - - adc_debug("adc->CAL = %x\n", temp); - return RT_EOK; -} - -/***************************************************************************//** -* @brief -* Configure ADC device -* -* @details -* -* @note -* -* @param[in] dev -* Pointer to device descriptor -* -* @param[in] cmd -* ADC control command -* -* @param[in] args -* Arguments -* -* @return -* Error code -******************************************************************************/ -static rt_err_t rt_adc_control( - rt_device_t dev, - rt_uint8_t cmd, - void *args) -{ - RT_ASSERT(dev != RT_NULL); - - struct efm32_adc_device_t *adc; - - adc = (struct efm32_adc_device_t *)(dev->user_data); - - switch (cmd) - { - case RT_DEVICE_CTRL_SUSPEND: - /* Suspend device */ - dev->flag |= RT_DEVICE_FLAG_SUSPENDED; - adc->adc_device->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP; - break; - - case RT_DEVICE_CTRL_RESUME: - /* Resume device */ - dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; - - switch (adc->mode) - { - case ADC_MODE_SINGLE: - ADC_Start(adc->adc_device, adcStartSingle); - break; - - case ADC_MODE_SCAN: - ADC_Start(adc->adc_device, adcStartScan); - break; - - case ADC_MODE_TAILGATE: - ADC_Start(adc->adc_device, adcStartScanAndSingle); - break; - - default: - return -RT_ERROR; - } - break; - - case RT_DEVICE_CTRL_ADC_MODE: - { - /* change device setting */ - struct efm32_adc_control_t *control; - - control = (struct efm32_adc_control_t *)args; - - switch (control->mode) - { - case ADC_MODE_SINGLE: - ADC_InitSingle(adc->adc_device, control->singleInit); - break; - - case ADC_MODE_SCAN: - ADC_InitScan(adc->adc_device, control->scanInit); - break; - - case ADC_MODE_TAILGATE: - ADC_InitSingle(adc->adc_device, control->singleInit); - ADC_InitScan(adc->adc_device, control->scanInit); - break; - - default: - return -RT_ERROR; - } - - adc->mode = control->mode; - } - break; - - case RT_DEVICE_CTRL_ADC_RESULT: - switch (adc->mode) - { - case ADC_MODE_SINGLE: - while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT); - *((rt_uint32_t *)args) = ADC_DataSingleGet(adc->adc_device); - break; - - case ADC_MODE_SCAN: - while (adc->adc_device->STATUS & ADC_STATUS_SCANACT); - *((rt_uint32_t *)args) = ADC_DataScanGet(adc->adc_device); - break; - - case ADC_MODE_TAILGATE: - while (adc->adc_device->STATUS & ADC_STATUS_SCANACT); - *((rt_uint32_t *)args) = ADC_DataScanGet(adc->adc_device); - - while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT); - *((rt_uint32_t *)args + 1) = ADC_DataSingleGet(adc->adc_device); - break; - - default: - return -RT_ERROR; - } - break; - } - - return RT_EOK; -} - -/***************************************************************************//** -* @brief -* Register ADC device -* -* @details -* -* @note -* -* @param[in] device -* Pointer to device descriptor -* -* @param[in] name -* Device name -* -* @param[in] flag -* Configuration flags -* -* @param[in] adc -* Pointer to ADC device descriptor -* -* @return -* Error code -******************************************************************************/ -rt_err_t rt_hw_adc_register( - rt_device_t device, - const char *name, - rt_uint32_t flag, - struct efm32_adc_device_t *adc) -{ - RT_ASSERT(device != RT_NULL); - - device->type = RT_Device_Class_Char; /* fixme: should be adc type */ - device->rx_indicate = RT_NULL; - device->tx_complete = RT_NULL; - device->init = rt_adc_init; - device->open = RT_NULL; - device->close = RT_NULL; - device->read = RT_NULL; - device->write = RT_NULL; - device->control = rt_adc_control; - device->user_data = adc; - - /* register a character device */ - return rt_device_register(device, name, flag); -} - -/***************************************************************************//** -* @brief -* Initialize the specified ADC unit -* -* @details -* -* @note -* -* @param[in] device -* Pointer to device descriptor -* -* @param[in] unitNumber -* Unit number -* -* @return -* Pointer to ADC device -******************************************************************************/ -static struct efm32_adc_device_t *rt_hw_adc_unit_init( - rt_device_t device, - rt_uint8_t unitNumber) -{ - struct efm32_adc_device_t *adc; - CMU_Clock_TypeDef adcClock; - ADC_Init_TypeDef init = ADC_INIT_DEFAULT; - - do - { - /* Allocate device */ - adc = rt_malloc(sizeof(struct efm32_adc_device_t)); - if (adc == RT_NULL) - { - adc_debug("no memory for ADC%d driver\n", unitNumber); - break; - } - adc->mode = ADC_MODE_SINGLE; - - /* Initialization */ - if (unitNumber >= ADC_COUNT) - { - break; - } - switch (unitNumber) - { - case 0: - adc->adc_device = ADC0; - adcClock = (CMU_Clock_TypeDef)cmuClock_ADC0; - break; - - default: - break; - } - - /* Enable ADC clock */ - CMU_ClockEnable(adcClock, true); - - /* Reset */ - ADC_Reset(adc->adc_device); - - /* Configure ADC */ - // TODO: Fixed oversampling rate? - init.ovsRateSel = adcOvsRateSel4096; - init.timebase = ADC_TimebaseCalc(0); - init.prescale = ADC_PrescaleCalc(ADC_CONVERT_FREQUENCY, 0); - ADC_Init(adc->adc_device, &init); - - return adc; - } while(0); - - if (adc) - { - rt_free(adc); - } - rt_kprintf("ADC: Init failed!\n"); - return RT_NULL; -} - -/***************************************************************************//** -* @brief -* Initialize all ADC module related hardware and register ADC device to kernel -* -* @details -* -* @note -* -******************************************************************************/ -void rt_hw_adc_init(void) -{ - struct efm32_adc_device_t *adc; - -#ifdef RT_USING_ADC0 - if ((adc = rt_hw_adc_unit_init(&adc0_device, 0)) != RT_NULL) - { - rt_hw_adc_register(&adc0_device, RT_ADC0_NAME, EFM32_NO_DATA, adc); - } -#endif -} - - /***************************************************************************//** * @brief * Calibrate offset and gain for the specified reference. @@ -498,6 +199,635 @@ rt_uint32_t efm32_adc_calibration( return adc->CAL; } +/***************************************************************************//** + * @brief + * Configure DMA for ADC + * + * @details + * + * @note + * + * @param[in] adc_device + * Pointer to ADC registers base address + * + * @param[in] mode + * ADC mode + * + * @param[in] channel + * DMA channel + ******************************************************************************/ +void efm32_adc_cfg_dma( + ADC_TypeDef *adc_device, + rt_uint8_t mode, + rt_uint8_t channel) +{ + DMA_CfgChannel_TypeDef chnlCfg; + DMA_CfgDescr_TypeDef descrCfg; + + if (channel == (rt_uint8_t)EFM32_NO_DMA) + { + return; + } + + /* Set up DMA channel */ + chnlCfg.highPri = false; + chnlCfg.enableInt = false; + if (adc_device == ADC0) + { + switch (mode & ADC_MASK_MODE) + { + case ADC_MODE_SINGLE: + chnlCfg.select = DMAREQ_ADC0_SINGLE; + break; + + case ADC_MODE_SCAN: + chnlCfg.select = DMAREQ_ADC0_SCAN; + break; + + default: + return; + } + } + else + { + // TODO: Any other channel? + return; + } + chnlCfg.cb = RT_NULL; + DMA_CfgChannel((rt_uint32_t)channel, &chnlCfg); + + /* Setting up DMA channel descriptor */ + descrCfg.dstInc = dmaDataInc4; + descrCfg.srcInc = dmaDataIncNone; + descrCfg.size = dmaDataSize4; + descrCfg.arbRate = dmaArbitrate1; + descrCfg.hprot = 0; + DMA_CfgDescr((rt_uint32_t)channel, true, &descrCfg); +} + +/***************************************************************************//** + * @brief + * Activate DMA for ADC + * + * @details + * + * @note + * + * @param[in] adc_device + * Pointer to ADC registers base address + * + * @param[in] mode + * ADC mode + * + * @param[in] count + * ADC channel count + * + * @param[in] channel + * DMA channel + * + * @param[out] buffer + * Pointer to ADC results buffer + ******************************************************************************/ +void efm32_adc_on_dma( + ADC_TypeDef *adc_device, + rt_uint8_t mode, + rt_uint8_t count, + rt_uint8_t channel, + void *buffer) +{ + switch (mode & ADC_MASK_MODE) + { + case ADC_MODE_SINGLE: + /* Activate DMA */ + DMA_ActivateBasic( + (rt_uint32_t)channel, + true, + false, + buffer, + (void *)&(adc_device->SINGLEDATA), + count - 1); + break; + + case ADC_MODE_SCAN: + DMA_ActivateBasic( + (rt_uint32_t)channel, + true, + false, + buffer, + (void *)&(adc_device->SCANDATA), + count - 1); + break; + + default: + return; + } +} + +/***************************************************************************//** + * @brief + * Initialize ADC device + * + * @details + * + * @note + * + * @param[in] dev + * Pointer to device descriptor + * + * @return + * Error code + ******************************************************************************/ + static rt_err_t rt_adc_init(rt_device_t dev) +{ + RT_ASSERT(dev != RT_NULL); + + rt_uint32_t temp; + + struct efm32_adc_device_t *adc; + + adc = (struct efm32_adc_device_t *)(dev->user_data); + + temp = efm32_adc_calibration(adc->adc_device, ADC_CALI_REF, ADC_CALI_CH); + + adc_debug("adc->CAL = %x\n", temp); + return RT_EOK; +} + +/***************************************************************************//** + * @brief + * Configure ADC device + * + * @details + * + * @note + * + * @param[in] dev + * Pointer to device descriptor + * + * @param[in] cmd + * ADC control command + * + * @param[in] args + * Arguments + * + * @return + * Error code + ******************************************************************************/ +static rt_err_t rt_adc_control( + rt_device_t dev, + rt_uint8_t cmd, + void *args) +{ + RT_ASSERT(dev != RT_NULL); + + struct efm32_adc_device_t *adc; + + adc = (struct efm32_adc_device_t *)(dev->user_data); + + switch (cmd) + { + case RT_DEVICE_CTRL_SUSPEND: + /* Suspend device */ + dev->flag |= RT_DEVICE_FLAG_SUSPENDED; + adc->adc_device->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP; + break; + + case RT_DEVICE_CTRL_RESUME: + { + /* Resume device */ + struct efm32_adc_result_t *control = \ + (struct efm32_adc_result_t *)args; + + dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; + + switch (control->mode) + { + case ADC_MODE_SINGLE: + if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->singleCount, + adc->singleDmaChannel, + control->buffer); + } + ADC_Start(adc->adc_device, adcStartSingle); + break; + + case ADC_MODE_SCAN: + if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->scanCount, + adc->scanDmaChannel, + control->buffer); + } + ADC_Start(adc->adc_device, adcStartScan); + break; + + case ADC_MODE_TAILGATE: + { + void *index = control->buffer; + + if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->scanCount, + adc->scanDmaChannel, + index); + index += adc->scanCount; + } + if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->singleCount, + adc->singleDmaChannel, + index); + index += adc->singleCount; + } + ADC_Start(adc->adc_device, adcStartScanAndSingle); + } + + break; + + default: + return -RT_ERROR; + } + } + break; + + case RT_DEVICE_CTRL_ADC_MODE: + { + /* change device setting */ + struct efm32_adc_control_t *control = \ + (struct efm32_adc_control_t *)args; + + switch (control->mode) + { + case ADC_MODE_SINGLE: + ADC_InitSingle(adc->adc_device, control->single.init); + break; + + case ADC_MODE_SCAN: + ADC_InitScan(adc->adc_device, control->scan.init); + break; + + case ADC_MODE_TAILGATE: + ADC_InitSingle(adc->adc_device, control->single.init); + ADC_InitScan(adc->adc_device, control->scan.init); + break; + + default: + return -RT_ERROR; + } + + if (control->mode == ADC_MODE_TAILGATE) + { + adc->mode = ADC_MODE_TAILGATE; + } + else + { + adc->mode &= ~(rt_uint8_t)ADC_MODE_TAILGATE; + adc->mode |= control->mode; + } + if ((control->mode == ADC_MODE_TAILGATE) || \ + (control->mode == ADC_MODE_SINGLE)) + { + if (control->single.init->rep) + { + adc->mode |= ADC_OP_SINGLE_REPEAT; + } + adc->singleCount = control->single.count; + adc->singleDmaChannel = control->single.dmaChannel; + efm32_adc_cfg_dma(adc->adc_device, control->mode, adc->singleDmaChannel); + } + if ((control->mode == ADC_MODE_TAILGATE) || \ + (control->mode == ADC_MODE_SCAN)) + { + if (control->scan.init->rep) + { + adc->mode |= ADC_OP_SCAN_REPEAT; + } + adc->scanCount = control->scan.count; + adc->scanDmaChannel = control->scan.dmaChannel; + efm32_adc_cfg_dma(adc->adc_device, control->mode, adc->scanDmaChannel); + } + } + break; + + case RT_DEVICE_CTRL_ADC_RESULT: + { + struct efm32_adc_result_t *control = \ + (struct efm32_adc_result_t *)args; + + switch (control->mode) + { + case ADC_MODE_SINGLE: + if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + if (adc->mode & ADC_OP_SINGLE_REPEAT) + { + if (!(DMA->IF & (1 << adc->singleDmaChannel))) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->singleCount, + adc->singleDmaChannel, + control->buffer); + } + while (!(DMA->IF & (1 << adc->singleDmaChannel))); + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT); + } + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT); + *((rt_uint32_t *)control->buffer) = \ + ADC_DataSingleGet(adc->adc_device) << adcErrataShift; + } + break; + + case ADC_MODE_SCAN: + if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + if (adc->mode & ADC_OP_SCAN_REPEAT) + { + if (!(DMA->IF & (1 << adc->scanDmaChannel))) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->scanCount, + adc->scanDmaChannel, + control->buffer); + } + while (!(DMA->IF & (1 << adc->scanDmaChannel))); + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SCANACT); + } + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SCANACT); + *((rt_uint32_t *)control->buffer) = \ + ADC_DataScanGet(adc->adc_device) << adcErrataShift; + } + break; + + case ADC_MODE_TAILGATE: + { + void *index = control->buffer; + + if ((adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA) && \ + !(adc->mode & ADC_OP_SCAN_REPEAT)) + { + index += adc->scanCount; + } + if ((adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA) && \ + !(adc->mode & ADC_OP_SINGLE_REPEAT)) + { + index += adc->singleCount; + } + + if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + if (adc->mode & ADC_OP_SCAN_REPEAT) + { + if (!(DMA->IF & (1 << adc->scanDmaChannel))) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->scanCount, + adc->scanDmaChannel, + index); + index += adc->scanCount; + } + while (!(DMA->IF & (1 << adc->scanDmaChannel))); + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SCANACT); + } + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SCANACT); + *(rt_uint32_t *)(index++) = \ + ADC_DataScanGet(adc->adc_device) << adcErrataShift; + } + if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA) + { + if (adc->mode & ADC_OP_SINGLE_REPEAT) + { + if (!(DMA->IF & (1 << adc->singleDmaChannel))) + { + efm32_adc_on_dma( + adc->adc_device, + control->mode, + adc->singleCount, + adc->singleDmaChannel, + index); + index += adc->singleCount; + } + while (!(DMA->IF & (1 << adc->singleDmaChannel))); + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT); + } + } + else + { + while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT); + *(rt_uint32_t *)(index++) = \ + ADC_DataSingleGet(adc->adc_device) << adcErrataShift; + } + } + break; + + default: + return -RT_ERROR; + } + } + break; + + default: + return -RT_ERROR; + } + + return RT_EOK; +} + +/***************************************************************************//** + * @brief + * Register ADC device + * + * @details + * + * @note + * + * @param[in] device + * Pointer to device descriptor + * + * @param[in] name + * Device name + * + * @param[in] flag + * Configuration flags + * + * @param[in] adc + * Pointer to ADC device descriptor + * + * @return + * Error code + ******************************************************************************/ +rt_err_t rt_hw_adc_register( + rt_device_t device, + const char *name, + rt_uint32_t flag, + struct efm32_adc_device_t *adc) +{ + RT_ASSERT(device != RT_NULL); + + device->type = RT_Device_Class_Char; /* fixme: should be adc type */ + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->init = rt_adc_init; + device->open = RT_NULL; + device->close = RT_NULL; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = rt_adc_control; + device->user_data = adc; + + /* register a character device */ + return rt_device_register(device, name, flag); +} + +/***************************************************************************//** + * @brief + * Initialize the specified ADC unit + * + * @details + * + * @note + * + * @param[in] device + * Pointer to device descriptor + * + * @param[in] unitNumber + * Unit number + * + * @return + * Pointer to ADC device + ******************************************************************************/ +static struct efm32_adc_device_t *rt_hw_adc_unit_init( + rt_device_t device, + rt_uint8_t unitNumber) +{ + struct efm32_adc_device_t *adc; + CMU_Clock_TypeDef adcClock; + ADC_Init_TypeDef init = ADC_INIT_DEFAULT; + + do + { + /* Allocate device and set default value */ + adc = rt_malloc(sizeof(struct efm32_adc_device_t)); + if (adc == RT_NULL) + { + adc_debug("no memory for ADC%d driver\n", unitNumber); + break; + } + adc->mode = 0; + adc->singleCount = 0; + adc->singleDmaChannel = (rt_uint8_t)EFM32_NO_DMA; + adc->scanCount = 0; + adc->scanDmaChannel = (rt_uint8_t)EFM32_NO_DMA; + + /* Initialization */ + if (unitNumber >= ADC_COUNT) + { + break; + } + switch (unitNumber) + { + case 0: + adc->adc_device = ADC0; + adcClock = (CMU_Clock_TypeDef)cmuClock_ADC0; + break; + + default: + break; + } + + /* Enable ADC clock */ + CMU_ClockEnable(adcClock, true); + + /* Reset */ + ADC_Reset(adc->adc_device); + + /* Configure ADC */ + // TODO: Fixed oversampling rate? + init.ovsRateSel = adcOvsRateSel4096; + init.timebase = ADC_TimebaseCalc(0); + init.prescale = ADC_PrescaleCalc(ADC_CONVERT_FREQUENCY, 0); + ADC_Init(adc->adc_device, &init); + + return adc; + } while(0); + + if (adc) + { + rt_free(adc); + } + rt_kprintf("ADC: Init failed!\n"); + return RT_NULL; +} + +/***************************************************************************//** + * @brief + * Initialize all ADC module related hardware and register ADC device to kernel + * + * @details + * + * @note + * + ******************************************************************************/ +void rt_hw_adc_init(void) +{ + SYSTEM_ChipRevision_TypeDef chipRev; + struct efm32_adc_device_t *adc; + +#ifdef RT_USING_ADC0 + if ((adc = rt_hw_adc_unit_init(&adc0_device, 0)) != RT_NULL) + { + rt_hw_adc_register(&adc0_device, RT_ADC0_NAME, EFM32_NO_DATA, adc); + } +#endif + + /* ADC errata for rev B when using VDD as reference, need to multiply */ + /* result by 2 */ + SYSTEM_ChipRevisionGet(&chipRev); + if ((chipRev.major == 0x01) && (chipRev.minor == 0x01)) + { + adcErrataShift = 1; + } +} + #endif /***************************************************************************//** * @} diff --git a/bsp/efm32/drv_adc.h b/bsp/efm32/drv_adc.h index c67d28b50d..3d714b7f2f 100644 --- a/bsp/efm32/drv_adc.h +++ b/bsp/efm32/drv_adc.h @@ -12,6 +12,7 @@ * @section Change Logs * Date Author Notes * 2011-02-21 onelife Initial creation for EFM32 + * 2011-07-14 onelife Add multiple channels support for scan mode ******************************************************************************/ #ifndef __DRV_ADC_H__ #define __DRV_ADC_H__ @@ -21,21 +22,49 @@ struct efm32_adc_device_t { ADC_TypeDef *adc_device; - rt_uint32_t mode; + rt_uint8_t mode; + rt_uint8_t singleCount; + rt_uint8_t singleDmaChannel; + rt_uint8_t scanCount; + rt_uint8_t scanDmaChannel; +}; + +struct efm32_adc_control_single_t +{ + rt_uint8_t count; + rt_uint8_t dmaChannel; + ADC_InitSingle_TypeDef *init; +}; + +struct efm32_adc_control_scan_t +{ + rt_uint8_t count; + rt_uint8_t dmaChannel; + ADC_InitScan_TypeDef *init; }; struct efm32_adc_control_t { - rt_uint32_t mode; - ADC_InitSingle_TypeDef *singleInit; - ADC_InitScan_TypeDef *scanInit; + rt_uint8_t mode; + struct efm32_adc_control_scan_t scan; + struct efm32_adc_control_single_t single; +}; + +struct efm32_adc_result_t +{ + rt_uint8_t mode; + void *buffer; }; /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ -#define ADC_MODE_SINGLE 0x00UL -#define ADC_MODE_SCAN 0x01UL -#define ADC_MODE_TAILGATE 0x02UL +#define ADC_MODE_SINGLE (0x01) +#define ADC_MODE_SCAN (0x02) +#define ADC_MODE_TAILGATE (0x04) +#define ADC_OP_SINGLE_REPEAT (0x10) +#define ADC_OP_SCAN_REPEAT (0x20) +#define ADC_MASK_MODE (0x0f) +#define ADC_MASK_OP (0xf0) /* Exported functions ------------------------------------------------------- */ void rt_hw_adc_init(void); diff --git a/bsp/efm32/drv_ethernet.c b/bsp/efm32/drv_ethernet.c index 9fd85890b2..6391db5986 100644 --- a/bsp/efm32/drv_ethernet.c +++ b/bsp/efm32/drv_ethernet.c @@ -15,6 +15,9 @@ * @section Change Logs * Date Author Notes * 2011-06-22 onelife Initial creation for using EFM32 USART module + * 2011-07-25 onelife Add lock (semaphore) to prevent simultaneously + * access + * 2011-07-28 onelife Add get_ip() and update_ip() utilities ******************************************************************************/ /***************************************************************************//** @@ -366,8 +369,8 @@ void efm_eth_isr(rt_device_t dev) rt_uint8_t reg_eir, data; volatile rt_uint8_t cnt; - /* Disable RX interrutp */ - data = EIE_PKTIE; + /* Disable RX and other interrutps */ + data = EIE_PKTIE | EIE_INTIE; efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data); /* Get interrupt flag */ @@ -410,6 +413,10 @@ void efm_eth_isr(rt_device_t dev) /* Inform Ethernet thread */ eth_device_ready(ð_dev); } + + /* Enable other interrupts */ + data = EIE_INTIE; + efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data); } /***************************************************************************//** @@ -470,8 +477,7 @@ static rt_err_t efm_eth_init(rt_device_t dev) efm_eth_writeReg(EPMM1, 0x30); efm_eth_writeReg(EPMCSL, 0xf9); efm_eth_writeReg(EPMCSH, 0xf7); - efm_eth_writeReg(ERXFCON, - ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN); + efm_eth_writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN); //efm_eth_writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); /* Waiting For OST: The OST does not expire until 7500 OSC1 clock cycles (300 uS) pass after Power-on Reset or wake-up from Power-Down mode occurs */ @@ -720,14 +726,14 @@ struct pbuf *efm_eth_rx(rt_device_t dev) rt_uint16_t len_rx, sta_rx; struct pbuf* p; - p = RT_NULL; - /* Lock device */ rt_sem_take(ðLock, RT_WAITING_FOREVER); + /* Disable interrupts */ data = EIE_INTIE; efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data); + p = RT_NULL; reg_eie = 0; if (efm_eth_readReg(EPKTCNT)) { @@ -778,10 +784,11 @@ struct pbuf *efm_eth_rx(rt_device_t dev) eth_debug("ETH: ***** read RX (q->len %x) *****\n", q->len); for (i = 0; i < q->len; i += 8) { - eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x (%d %d)\n", + eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x | %c %c %c %c %c %c %c %c\n", temp[i], temp[i + 1], temp[i + 2], temp[i + 3], temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7], - i, q->len); + temp[i], temp[i + 1], temp[i + 2], temp[i + 3], + temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7]); } } #endif @@ -820,6 +827,7 @@ struct pbuf *efm_eth_rx(rt_device_t dev) /* Enable interrupts */ reg_eie |= EIE_INTIE; efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, ®_eie); + /* Unlock device */ rt_sem_release(ðLock); @@ -850,6 +858,7 @@ rt_err_t efm_eth_tx(rt_device_t dev, struct pbuf* p) /* Lock device */ rt_sem_take(ðLock, RT_WAITING_FOREVER); + /* Disable interrupts */ data = EIE_INTIE; efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data); @@ -880,10 +889,11 @@ rt_err_t efm_eth_tx(rt_device_t dev, struct pbuf* p) eth_debug("ETH: ***** write TX (len %d) *****\n", p->len); for (i = 0; i < q->len; i += 8) { - eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x (%d %d)\n", + eth_debug("%02x %02x %02x %02x %02x %02x %02x %02x | %c %c %c %c %c %c %c %c\n", temp[i], temp[i + 1], temp[i + 2], temp[i + 3], temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7], - i, q->len); + temp[i], temp[i + 1], temp[i + 2], temp[i + 3], + temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7]); } } #endif @@ -902,9 +912,12 @@ rt_err_t efm_eth_tx(rt_device_t dev, struct pbuf* p) efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data); } + /* Waiting for a while */ + rt_thread_delay(ETH_PERIOD_WAIT_INIT); /* Enable interrupts */ data = EIE_INTIE; efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data); + /* Unlock device */ rt_sem_release(ðLock); @@ -983,7 +996,7 @@ rt_err_t efm_hw_eth_init(void) USART_BaudrateSyncSet(usart->usart_device, 0, ETH_CLK_MAX); /* Initialize semaphore */ - rt_sem_init(ðLock, "lck_eth", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(ðLock, ETH_DEVICE_NAME, 1, RT_IPC_FLAG_FIFO); /* Register Ethernet device */ eth_dev.parent.init = efm_eth_init; @@ -1011,6 +1024,7 @@ rt_err_t efm_hw_eth_init(void) /***************************************************************************//** * Export to FINSH ******************************************************************************/ +#if defined(EFM32_USING_ETH_UTILS) #ifdef RT_USING_FINSH #include @@ -1021,9 +1035,6 @@ void list_eth(void) rt_kprintf(" ENC28J60 on %s\n", ETH_USING_DEVICE_NAME); rt_kprintf(" ------------------------------\n"); - rt_kprintf(" MAC address is %02x %02x %02x %02x %02x %02x\n", - eth_addr[0], eth_addr[1], eth_addr[2], eth_addr[3], eth_addr[4], - eth_addr[5], eth_addr[6]); reg_phy = efm_eth_readPhy(PHSTAT2); if (reg_phy & PHSTAT2_PLRITY) { @@ -1075,8 +1086,244 @@ void list_eth(void) } } FINSH_FUNCTION_EXPORT(list_eth, list the Ethernet device status.) + +#include "lwip\api.h" + +rt_err_t get_ip(char *ip) +{ + err_t ret; + struct ip_addr server_ip; + struct netconn *conn; + struct netbuf *buf; + char *rq, *rq2; + u16_t len; + const char query[] = "GET / HTTP/1.0\r\nHOST: checkip.dyndns.com\r\n\r\n"; + const char find[] = "body"; + + do + { +#if defined(RT_LWIP_DNS) + ret = netconn_gethostbyname("checkip.dyndns.com", &server_ip); + if (ret != ERR_OK) + { + break; + } +#else + IP4_ADDR(&server_ip, 216,146,38,70); // IP address of "checkip.dyndns.com" #endif + conn = netconn_new(NETCONN_TCP); + if (conn == NULL) + { + break; + } + + ret = netconn_connect(conn, &server_ip, 80); + if (ret != ERR_OK) + { + break; + } + + /* Send the query */ + ret = netconn_write(conn, query, sizeof(query) - 1, 0); + if (ret != ERR_OK) + { + break; + } + + buf = netconn_recv(conn); + if (buf != NULL) + { + /* Get the response */ + ret = netbuf_data(buf, (void **)&rq, &len); + if (ret != ERR_OK) + { + break; + } + + /* Find the IP address */ + rq = rt_strstr(rq, find); + if (rq == RT_NULL) + { + break; + } + rq += 5; + rq2 = rq; + rq2 = rt_strstr(rq2, find); + if (rq2 == RT_NULL) + { + break; + } + rq2 -= 2; + *rq2 = 0x0; +// rt_kprintf("[%s]\n", rq); + } + else + { + break; + } + + /* Copy the IP address to buffer */ + if (ip != NULL) + { + while(*rq < '0' || *rq > '9') + { + rq++; + } + rt_memcpy(ip, rq, rq2 - rq + 1); + } + netconn_delete(conn); + netbuf_delete(buf); + return RT_EOK; + } while (0); + + netconn_delete(conn); + netbuf_delete(buf); + return -RT_ERROR; +} + +void list_myip(void) +{ + rt_uint8_t ip[20]; + + if (get_ip(ip) != RT_EOK) + { + rt_kprintf("Get IP failed!\n"); + return; + } + + rt_kprintf("Current IP: [%s]\n", ip); +} +FINSH_FUNCTION_EXPORT(list_myip, list the current IP address.) + +#if !defined(hostName) || !defined(userPwdB64) +#error "The 'hostName' and 'userPwdB64' must be defined to use update_ip() function" +#endif + +rt_err_t update_ip(char *ip) +{ + err_t ret; + struct ip_addr server_ip; + struct netconn *conn; + struct netbuf *buf; + char *rq; + u16_t len, len2; + char query[200] = "GET /nic/update?hostname="; + const char query2[] = "&myip="; + const char query3[] = " HTTP/1.0\r\nHost: members.dyndns.org\r\nAuthorization: Basic "; + const char query4[] = "\r\nUser-Agent: onelife - EFM32 - 0.4\r\n\r\n"; + const char find[] = "good"; + + /* Make the query */ + len = rt_strlen(query); + len2 = sizeof(hostName) - 1; + rt_memcpy(&query[len], hostName, len2); + len += len2; + + len2 = sizeof(query2) - 1; + rt_memcpy(&query[len], query2, len2); + len += len2; + + len2 = rt_strlen(ip); + rt_memcpy(&query[len], ip, len2); + len += len2; + + len2 = sizeof(query3) - 1; + rt_memcpy(&query[len], query3, len2); + len += len2; + + len2 = sizeof(userPwdB64) - 1; + rt_memcpy(&query[len], userPwdB64, len2); + len += len2; + + len2 = sizeof(query4) - 1; + rt_memcpy(&query[len], query4, len2); + len += len2; + + query[len] = 0x0; +// rt_kprintf("Query: %s\n", &query[100]); + + do + { +#if defined(RT_LWIP_DNS) + ret = netconn_gethostbyname("members.dyndns.org", &server_ip); + if (ret != ERR_OK) + { + break; + } +#else + IP4_ADDR(&server_ip, 204,13,248,112); // IP address of "members.dyndns.org" +#endif + + conn = netconn_new(NETCONN_TCP); + if (conn == NULL) + { + break; + } + + ret = netconn_connect(conn, &server_ip, 80); + if (ret != ERR_OK) + { + break; + } + + /* Send the query */ + ret = netconn_write(conn, query, len, 0); + if (ret != ERR_OK) + { + break; + } + + /* Get the response */ + buf = netconn_recv(conn); + if (buf != NULL) + { + ret = netbuf_data(buf, (void **)&rq, &len); + if (ret != ERR_OK) + { + break; + } + + /* Find the result */ + rq = rt_strstr(rq, find); + if (rq == RT_NULL) + { + break; + } +// rt_kprintf("[%s]\n", rq); + } + else + { + break; + } + + netconn_delete(conn); + netbuf_delete(buf); + return RT_EOK; + } while (0); + + netconn_delete(conn); + netbuf_delete(buf); + return -RT_ERROR; +} + +void update_myip(char *ip) +{ + rt_kprintf("Update host, \"%s\", to new IP address %s: ", hostName, ip); + + if (update_ip(ip) != RT_EOK) + { + rt_kprintf("failed!\n"); + return; + } + + rt_kprintf("succeeded.\n", ip); +} +FINSH_FUNCTION_EXPORT(update_myip, update DDNS with specified IP address.) + +#endif /* RT_USING_FINSH */ +#endif /* defined(EFM32_USING_ETH_UTILS) */ + #endif /* defined(EFM32_USING_ETHERNET) */ /******************************************************************//** * @} diff --git a/bsp/efm32/drv_ethernet.h b/bsp/efm32/drv_ethernet.h index 7c9718cdc4..3eac5ed8fb 100644 --- a/bsp/efm32/drv_ethernet.h +++ b/bsp/efm32/drv_ethernet.h @@ -30,9 +30,9 @@ //#define ETH_HALF_DUPLEX #define ETH_PERIOD_WAIT_INIT (RT_TICK_PER_SECOND/100) +#define ETH_PERIOD_WAIT_TX (RT_TICK_PER_SECOND/100) #define ETH_SPI_RX_SKIP (1) - #define ETH_RESET_PORT (gpioPortB) #define ETH_RESET_PIN (9) #define ETH_INT_PORT (gpioPortB) diff --git a/bsp/efm32/drv_iic.c b/bsp/efm32/drv_iic.c index 6e6a39de55..c6eca69667 100644 --- a/bsp/efm32/drv_iic.c +++ b/bsp/efm32/drv_iic.c @@ -1,60 +1,62 @@ -/******************************************************************//** - * @file drv_iic.c +/***************************************************************************//** + * @file drv_iic.c * @brief Serial API of RT-Thread RTOS for EFM32 * COPYRIGHT (C) 2011, RT-Thread Development Team * @author onelife - * @version 0.4 beta - ********************************************************************** + * @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 - ********************************************************************** + * 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 * 2011-01-06 onelife Initial creation for EFM32 * 2011-06-17 onelife Modify init function for efm32lib v2 upgrading - *********************************************************************/ + * 2011-07-11 onelife Add lock (semaphore) to prevent simultaneously + * access + ******************************************************************************/ -/******************************************************************//** +/***************************************************************************//** * @addtogroup efm32 * @{ -*********************************************************************/ + ******************************************************************************/ -/* Includes -------------------------------------------------------------------*/ +/* Includes ------------------------------------------------------------------*/ #include "board.h" #include "hdl_interrupt.h" #include "drv_iic.h" #if (defined(RT_USING_IIC0) || defined(RT_USING_IIC1)) -/* Private typedef -------------------------------------------------------------*/ -/* Private define --------------------------------------------------------------*/ -/* Private macro --------------------------------------------------------------*/ +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ #ifdef RT_IIC_DEBUG #define iic_debug(format,args...) rt_kprintf(format, ##args) #else #define iic_debug(format,args...) #endif -/* Private variables ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ #ifdef RT_USING_IIC0 #if (RT_USING_IIC0 > 3) #error "The location number range of IIC is 0~3" #endif - struct rt_device iic0_device; - static struct rt_device iic0_rx_index; + struct rt_device iic0_device; + static struct rt_semaphore iic0_lock; #endif #ifdef RT_USING_IIC1 #if (RT_USING_IIC1 > 3) #error "The location number range of IIC is 0~3" #endif - struct rt_device iic1_device; - static struct rt_device iic1_rx_index; + struct rt_device iic1_device; + static struct rt_semaphore iic1_lock; #endif -/* Private function prototypes ---------------------------------------------------*/ -/* Private functions ------------------------------------------------------------*/ -/******************************************************************//** +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/***************************************************************************//** * @brief * Initialize IIC device * @@ -67,7 +69,7 @@ * * @return * Error code - *********************************************************************/ + ******************************************************************************/ static rt_err_t rt_iic_init (rt_device_t dev) { struct efm32_iic_device_t* iic; @@ -87,7 +89,7 @@ static rt_err_t rt_iic_init (rt_device_t dev) return RT_EOK; } -/******************************************************************//** +/***************************************************************************//** * @brief * Open IIC device * @@ -103,16 +105,21 @@ static rt_err_t rt_iic_init (rt_device_t dev) * * @return * Error code - *********************************************************************/ + ******************************************************************************/ static rt_err_t rt_iic_open(rt_device_t dev, rt_uint16_t oflag) { RT_ASSERT(dev != RT_NULL); + struct efm32_iic_device_t *iic; + + iic = (struct efm32_iic_device_t *)(dev->user_data); + iic->counter++; + iic_debug("IIC: Open with flag %x\n", oflag); return RT_EOK; } -/******************************************************************//** +/***************************************************************************//** * @brief * Close IIC device * @@ -125,21 +132,24 @@ static rt_err_t rt_iic_open(rt_device_t dev, rt_uint16_t oflag) * * @return * Error code - *********************************************************************/ + ******************************************************************************/ static rt_err_t rt_iic_close(rt_device_t dev) { + RT_ASSERT(dev != RT_NULL); + struct efm32_iic_device_t *iic; iic = (struct efm32_iic_device_t *)(dev->user_data); - - rt_free(iic->rx_buffer->data_ptr); - rt_free(iic->rx_buffer); - iic->rx_buffer = RT_NULL; - + if (--iic->counter == 0) + { + rt_free(iic->rx_buffer->data_ptr); + rt_free(iic->rx_buffer); + iic->rx_buffer = RT_NULL; + } return RT_EOK; } -/******************************************************************//** +/***************************************************************************//** * @brief * Read from IIC device * @@ -161,7 +171,7 @@ static rt_err_t rt_iic_close(rt_device_t dev) * * @return * Error code - *********************************************************************/ + ******************************************************************************/ static rt_size_t rt_iic_read ( rt_device_t dev, rt_off_t pos, @@ -185,6 +195,20 @@ static rt_size_t rt_iic_read ( iic = (struct efm32_iic_device_t*)dev->user_data; data[0] = (rt_uint8_t)(pos & 0x000000FF); + /* Lock device */ + if (rt_hw_interrupt_check()) + { + ret = rt_sem_take(iic->lock, RT_WAITING_NO); + } + else + { + ret = rt_sem_take(iic->lock, RT_WAITING_FOREVER); + } + if (ret != RT_EOK) + { + return ret; + } + if (iic->state & IIC_STATE_MASTER) { seq.addr = iic->slave_address; @@ -267,12 +291,15 @@ static rt_size_t rt_iic_read ( iic_debug("IIC0 slave read size: %d\n", read_size); } + /* Unlock device */ + rt_sem_release(iic->lock); + /* set error code */ rt_set_errno(err_code); return read_size; } -/******************************************************************//** +/***************************************************************************//** * @brief * Write to IIC device * @@ -294,7 +321,7 @@ static rt_size_t rt_iic_read ( * * @return * Error code - *********************************************************************/ + ******************************************************************************/ static rt_size_t rt_iic_write ( rt_device_t dev, rt_off_t pos, @@ -306,7 +333,6 @@ static rt_size_t rt_iic_write ( struct efm32_iic_device_t* iic; I2C_TransferSeq_TypeDef seq; I2C_TransferReturn_TypeDef ret; - //rt_uint8_t data[1]; if (!size) { @@ -316,7 +342,20 @@ static rt_size_t rt_iic_write ( err_code = RT_EOK; write_size = 0; iic = (struct efm32_iic_device_t*)dev->user_data; - //data[0] = (rt_uint8_t)(pos & 0x000000FF); + + /* Lock device */ + if (rt_hw_interrupt_check()) + { + ret = rt_sem_take(iic->lock, RT_WAITING_NO); + } + else + { + ret = rt_sem_take(iic->lock, RT_WAITING_FOREVER); + } + if (ret != RT_EOK) + { + return ret; + } if (iic->state & IIC_STATE_MASTER) { @@ -360,12 +399,15 @@ static rt_size_t rt_iic_write ( write_size = size; } + /* Unlock device */ + rt_sem_release(iic->lock); + /* set error code */ rt_set_errno(err_code); return write_size; } - /******************************************************************//** + /***************************************************************************//** * @brief * Configure IIC device * @@ -384,7 +426,7 @@ static rt_size_t rt_iic_write ( * * @return * Error code - *********************************************************************/ + ******************************************************************************/ static rt_err_t rt_iic_control ( rt_device_t dev, rt_uint8_t cmd, @@ -392,9 +434,25 @@ static rt_err_t rt_iic_control ( { RT_ASSERT(dev != RT_NULL); + rt_err_t ret; struct efm32_iic_device_t *iic; iic = (struct efm32_iic_device_t*)dev->user_data; + + /* Lock device */ + if (rt_hw_interrupt_check()) + { + ret = rt_sem_take(iic->lock, RT_WAITING_NO); + } + else + { + ret = rt_sem_take(iic->lock, RT_WAITING_FOREVER); + } + if (ret != RT_EOK) + { + return ret; + } + switch (cmd) { case RT_DEVICE_CTRL_SUSPEND: @@ -475,32 +533,35 @@ static rt_err_t rt_iic_control ( break; } + /* Unlock device */ + rt_sem_release(iic->lock); + return RT_EOK; } -/******************************************************************//** -* @brief -* Register IIC device -* -* @details -* -* @note -* -* @param[in] device -* Pointer to device descriptor -* -* @param[in] name -* Device name -* -* @param[in] flag -* Configuration flags -* -* @param[in] iic -* Pointer to IIC device descriptor -* -* @return -* Error code -*********************************************************************/ +/***************************************************************************//** + * @brief + * Register IIC device + * + * @details + * + * @note + * + * @param[in] device + * Pointer to device descriptor + * + * @param[in] name + * Device name + * + * @param[in] flag + * Configuration flags + * + * @param[in] iic + * Pointer to IIC device descriptor + * + * @return + * Error code + ******************************************************************************/ rt_err_t rt_hw_iic_register( rt_device_t device, const char *name, @@ -530,7 +591,7 @@ rt_err_t rt_hw_iic_register( return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag); } -/******************************************************************//** +/***************************************************************************//** * @brief * IIC slave mode RX data valid interrupt handler * @@ -540,7 +601,7 @@ rt_err_t rt_hw_iic_register( * * @param[in] dev * Pointer to device descriptor - *********************************************************************/ + ******************************************************************************/ static void rt_hw_iic_slave_isr(rt_device_t dev) { struct efm32_iic_device_t *iic; @@ -607,20 +668,20 @@ static void rt_hw_iic_slave_isr(rt_device_t dev) } } -/******************************************************************//** -* @brief -* Initialize the specified IIC unit -* -* @details -* -* @note -* -* @param[in] unitNumber -* Unit number -* -* @param[in] location -* Pin location number -*********************************************************************/ +/***************************************************************************//** + * @brief + * Initialize the specified IIC unit + * + * @details + * + * @note + * + * @param[in] unitNumber + * Unit number + * + * @param[in] location + * Pin location number + ******************************************************************************/ static struct efm32_iic_device_t *rt_hw_iic_unit_init( rt_device_t device, rt_uint8_t unitNumber, @@ -637,9 +698,10 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init( iic = rt_malloc(sizeof(struct efm32_iic_device_t)); if (iic == RT_NULL) { - iic_debug("no memory for IIC%d driver\n", unitNumber); + iic_debug("IIC: no memory for IIC%d driver\n", unitNumber); break; } + iic->counter = 0; iic->state |= IIC_STATE_MASTER; iic->master_address = 0x0000; iic->slave_address = 0x0000; @@ -653,12 +715,14 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init( switch (unitNumber) { case 0: + iic->lock = &iic0_lock; iic->iic_device = I2C0; iicClock = (CMU_Clock_TypeDef)cmuClock_I2C0; break; #if (I2C_COUNT > 1) case 1: + iic->lock = &iic1_lock; iic->iic_device = I2C1; iicClock = (CMU_Clock_TypeDef)cmuClock_I2C1; break; @@ -710,43 +774,71 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init( { rt_free(iic); } - rt_kprintf("IIC: Init failed!\n"); + + iic_debug("IIC: Unit %d init failed!\n", unitNumber); return RT_NULL; } -/******************************************************************//** -* @brief -* Initialize all IIC module related hardware and register IIC device to kernel -* -* @details -* -* @note -*********************************************************************/ +/***************************************************************************//** + * @brief + * Initialize all IIC module related hardware and register IIC device to kernel + * + * @details + * + * @note + ******************************************************************************/ void rt_hw_iic_init(void) { struct efm32_iic_device_t *iic; rt_uint32_t flag; - flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; - - /* register iic0 */ + do + { + flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; #ifdef RT_USING_IIC0 - if ((iic = rt_hw_iic_unit_init(&iic0_device, 0, RT_USING_IIC0)) != RT_NULL) - { - rt_hw_iic_register(&iic0_device, RT_IIC0_NAME, flag, iic); - } + /* Initialize and register iic0 */ + if ((iic = rt_hw_iic_unit_init(&iic0_device, 0, RT_USING_IIC0)) != RT_NULL) + { + rt_hw_iic_register(&iic0_device, RT_IIC0_NAME, flag, iic); + } + else + { + break; + } + + /* Initialize lock for iic0 */ + if (rt_sem_init(iic->lock, RT_IIC0_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + break; + } #endif - /* register iic1 */ #ifdef RT_USING_IIC1 - if ((iic = rt_hw_iic_unit_init(&iic1_device, 1, RT_USING_IIC1)) != RT_NULL) - { - rt_hw_iic_register(&iic1_device, RT_IIC1_NAME, flag, iic); - } + /* Initialize and register iic1 */ + if ((iic = rt_hw_iic_unit_init(&iic1_device, 1, RT_USING_IIC1)) != RT_NULL) + { + rt_hw_iic_register(&iic1_device, RT_IIC1_NAME, flag, iic); + } + else + { + break; + } + + /* Initialize lock for iic1 */ + if (rt_sem_init(iic->lock, RT_IIC1_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + break; + } #endif + + iic_debug("IIC: H/W init OK!\n"); + return; + } while (0); + + rt_kprintf("IIC: H/W init failed!\n"); } -#endif -/******************************************************************//** +#endif /* (defined(RT_USING_IIC0) || defined(RT_USING_IIC1)) */ +/***************************************************************************//** * @} -*********************************************************************/ + ******************************************************************************/ diff --git a/bsp/efm32/drv_iic.h b/bsp/efm32/drv_iic.h index 2c9d2f723a..8199c56eb6 100644 --- a/bsp/efm32/drv_iic.h +++ b/bsp/efm32/drv_iic.h @@ -1,23 +1,25 @@ -/******************************************************************//** - * @file drv_iic.h +/***************************************************************************//** + * @file drv_iic.h * @brief IIC driver of RT-Thread RTOS for EFM32 * COPYRIGHT (C) 2011, RT-Thread Development Team * @author onelife - * @version 0.4 beta - ********************************************************************** + * @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 - ********************************************************************** + * 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 * 2011-01-07 onelife Initial creation for EFM32 - *********************************************************************/ + * 2011-07-11 onelife Add lock (semaphore) to prevent simultaneously + * access + ******************************************************************************/ #ifndef __DRV_IIC_H__ #define __DRV_IIC_H__ -/* Includes -------------------------------------------------------------------*/ -/* Exported types -------------------------------------------------------------*/ +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ struct efm32_iic_int_mode_t { rt_uint8_t *data_ptr; @@ -27,16 +29,20 @@ struct efm32_iic_int_mode_t struct efm32_iic_device_t { + /* Counter */ + rt_uint32_t counter; + /* Lock */ + struct rt_semaphore *lock; /* State */ - rt_uint8_t state; + rt_uint8_t state; /* Pointer to IIC device structure */ - I2C_TypeDef* iic_device; + I2C_TypeDef *iic_device; /* Master address */ - rt_uint16_t master_address; + rt_uint16_t master_address; /* Slave address */ - rt_uint16_t slave_address; + rt_uint16_t slave_address; /* RX structure */ - struct efm32_iic_int_mode_t *rx_buffer; + struct efm32_iic_int_mode_t *rx_buffer; }; struct efm32_iic_control_t @@ -46,14 +52,14 @@ struct efm32_iic_control_t rt_uint16_t slave_address; }; -/* Exported constants ---------------------------------------------------------*/ -/* Exported macro -------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ #define IIC_STATE_MASTER (1 << 0) #define IIC_STATE_BROADCAST (1 << 1) //#define IIC_STATE_TX_BUSY (1 << 2) #define IIC_STATE_RX_BUSY (1 << 3) -/* Exported functions --------------------------------------------------------- */ +/* Exported functions --------------------------------------------------------*/ void rt_hw_iic_init(void); #endif /* __DRV_IIC_H__ */ diff --git a/bsp/efm32/drv_usart.c b/bsp/efm32/drv_usart.c index 1ab0c470ea..0b6f491c81 100644 --- a/bsp/efm32/drv_usart.c +++ b/bsp/efm32/drv_usart.c @@ -17,6 +17,8 @@ * 2011-06-14 onelife Fix a bug of TX by DMA * 2011-06-16 onelife Modify init function for efm32lib v2 upgrading * 2011-07-07 onelife Modify write function to avoid sleep in ISR + * 2011-07-26 onelife Add lock (semaphore) to prevent simultaneously + * access * * @section Change Logs of serial.c * 2009-02-05 Bernard first version @@ -57,6 +59,7 @@ union efm32_usart_init_t #error "The location number range of usart is 0~3" #endif struct rt_device usart0_device; + static struct rt_semaphore usart0_lock; #endif #ifdef RT_USING_USART1 @@ -64,6 +67,7 @@ union efm32_usart_init_t #error "The location number range of usart is 0~3" #endif struct rt_device usart1_device; + static struct rt_semaphore usart1_lock; #endif #ifdef RT_USING_USART2 @@ -71,6 +75,7 @@ union efm32_usart_init_t #error "The location number range of usart is 0~3" #endif struct rt_device usart2_device; + static struct rt_semaphore usart2_lock; #endif /* Private function prototypes -----------------------------------------------*/ @@ -203,6 +208,7 @@ static rt_err_t rt_usart_open(rt_device_t dev, rt_uint16_t oflag) NVIC_SetPriority(DMA_IRQn, EFM32_IRQ_PRI_DEFAULT); } + usart->counter++; usart_debug("USART%d: Open with flag %x\n", usart->unit, oflag); return RT_EOK; } @@ -223,16 +229,25 @@ 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) { - if (dev->flag & RT_DEVICE_FLAG_INT_RX) - { - struct efm32_usart_int_mode_t *int_rx; + RT_ASSERT(dev != 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; + struct efm32_usart_device_t *usart; + + usart = (struct efm32_usart_device_t *)(dev->user_data); + + if (--usart->counter == 0) + { + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + struct efm32_usart_int_mode_t *int_rx; + + int_rx = (struct efm32_usart_int_mode_t *)usart->rx_mode; + + rt_free(int_rx->data_ptr); + int_rx->data_ptr = RT_NULL; + } } + return RT_EOK; } @@ -265,11 +280,27 @@ static rt_size_t rt_usart_read ( void *buffer, rt_size_t size) { + struct efm32_usart_device_t *usart; rt_uint8_t *ptr; rt_err_t err_code; rt_size_t read_len; + + usart = (struct efm32_usart_device_t *)(dev->user_data); - err_code = RT_EOK; + /* Lock device */ + if (rt_hw_interrupt_check()) + { + err_code = rt_sem_take(usart->lock, RT_WAITING_NO); + } + else + { + err_code = rt_sem_take(usart->lock, RT_WAITING_FOREVER); + } + if (err_code != RT_EOK) + { + rt_set_errno(err_code); + return 0; + } if (dev->flag & RT_DEVICE_FLAG_INT_RX) { @@ -384,6 +415,9 @@ static rt_size_t rt_usart_read ( read_len = size; } + /* Unlock device */ + rt_sem_release(usart->lock); + /* set error code */ rt_set_errno(err_code); return read_len; @@ -422,10 +456,24 @@ static rt_size_t rt_usart_write ( rt_size_t write_size; struct efm32_usart_device_t* usart; - err_code = RT_EOK; write_size = 0; usart = (struct efm32_usart_device_t*)(dev->user_data); + /* Lock device */ + if (rt_hw_interrupt_check()) + { + err_code = rt_sem_take(usart->lock, RT_WAITING_NO); + } + else + { + err_code = rt_sem_take(usart->lock, RT_WAITING_FOREVER); + } + if (err_code != RT_EOK) + { + rt_set_errno(err_code); + return 0; + } + if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (size > 2)) { /* DMA mode Tx */ struct efm32_usart_dma_mode_t *dma_tx; @@ -503,6 +551,9 @@ static rt_size_t rt_usart_write ( write_size = (rt_size_t)ptr - (rt_size_t)buffer; } + /* Unlock device */ + rt_sem_release(usart->lock); + /* set error code */ rt_set_errno(err_code); return write_size; @@ -535,10 +586,25 @@ static rt_err_t rt_usart_control ( { RT_ASSERT(dev != RT_NULL); + rt_err_t err_code; struct efm32_usart_device_t *usart; usart = (struct efm32_usart_device_t *)(dev->user_data); - + + /* Lock device */ + if (rt_hw_interrupt_check()) + { + err_code = rt_sem_take(usart->lock, RT_WAITING_NO); + } + else + { + err_code = rt_sem_take(usart->lock, RT_WAITING_FOREVER); + } + if (err_code != RT_EOK) + { + return err_code; + } + switch (cmd) { case RT_DEVICE_CTRL_SUSPEND: @@ -577,7 +643,8 @@ static rt_err_t rt_usart_control ( == RT_NULL) { usart_debug("USART: no memory for RX buffer\n"); - return -RT_ENOMEM; + err_code = -RT_ENOMEM; + break; } // TODO: Is the following line necessary? //rt_memset(int_rx->data_ptr, 0, size); @@ -589,7 +656,8 @@ static rt_err_t rt_usart_control ( if ((int_rx->data_ptr = rt_malloc(size)) == RT_NULL) { usart_debug("USART: no memory for RX buffer\n"); - return -RT_ENOMEM; + err_code = -RT_ENOMEM; + break; } } int_rx->data_size = size; @@ -600,7 +668,10 @@ static rt_err_t rt_usart_control ( } - return RT_EOK; + /* Unlock device */ + rt_sem_release(usart->lock); + + return err_code; } /***************************************************************************//** @@ -811,6 +882,7 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init( usart_debug("USART: no memory for USART%d device\n", unitNumber); break; } + usart->counter = 0; usart->unit = unitNumber; usart->state = config; usart->tx_mode = RT_NULL; @@ -848,18 +920,21 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init( switch (unitNumber) { case 0: + usart->lock = &usart0_lock; usart->usart_device = USART0; usartClock = (CMU_Clock_TypeDef)cmuClock_USART0; txDmaSelect = DMAREQ_USART0_TXBL; break; case 1: + usart->lock = &usart1_lock; usart->usart_device = USART1; usartClock = (CMU_Clock_TypeDef)cmuClock_USART1; txDmaSelect = DMAREQ_USART1_TXBL; break; case 2: + usart->lock = &usart2_lock; usart->usart_device = USART2; usartClock = (CMU_Clock_TypeDef)cmuClock_USART2; txDmaSelect = DMAREQ_USART2_TXBL; @@ -1017,6 +1092,8 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init( { rt_free(usart); } + + usart_debug("USART: Unit %d init failed!\n", unitNumber); return RT_NULL; } @@ -1035,143 +1112,178 @@ void rt_hw_usart_init(void) rt_uint32_t flag; rt_uint8_t config; - /* Register usart0 */ + do + { #ifdef RT_USING_USART0 - config = 0x00; - flag = RT_DEVICE_FLAG_RDWR; + config = 0x00; + flag = RT_DEVICE_FLAG_RDWR; #ifdef RT_USART0_SYNC_MODE - config |= USART_STATE_SYNC; + config |= USART_STATE_SYNC; #if (RT_USART0_SYNC_MODE != 0x0UL) - config |= USART_STATE_MASTER; + config |= USART_STATE_MASTER; #else - flag |= RT_DEVICE_FLAG_INT_RX; + flag |= RT_DEVICE_FLAG_INT_RX; #endif #else - flag |= RT_DEVICE_FLAG_INT_RX; + flag |= RT_DEVICE_FLAG_INT_RX; #endif #if (SPI_AUTOCS_ENABLE & (1 << 0)) - config |= USART_STATE_AUTOCS; + config |= USART_STATE_AUTOCS; #endif #if (RT_CONSOLE_DEVICE == 0x0UL) - config |= USART_STATE_CONSOLE; - flag |= RT_DEVICE_FLAG_STREAM; + config |= USART_STATE_CONSOLE; + flag |= RT_DEVICE_FLAG_STREAM; #endif #ifdef RT_USART0_USING_DMA - RT_ASSERT(RT_USART0_USING_DMA < DMA_CHAN_COUNT); - flag |= RT_DEVICE_FLAG_DMA_TX; + RT_ASSERT(RT_USART0_USING_DMA < DMA_CHAN_COUNT); + flag |= RT_DEVICE_FLAG_DMA_TX; #else - #define RT_USART0_USING_DMA EFM32_NO_DATA + #define RT_USART0_USING_DMA EFM32_NO_DATA #endif - if ((usart = rt_hw_usart_unit_init( - &usart0_device, - 0, - RT_USING_USART0, - flag, - RT_USART0_USING_DMA, - config)) != RT_NULL) - { - rt_hw_usart_register(&usart0_device, RT_USART0_NAME, flag, usart); - } + /* Initialize and Register usart0 */ + if ((usart = rt_hw_usart_unit_init( + &usart0_device, + 0, + RT_USING_USART0, + flag, + RT_USART0_USING_DMA, + config)) != RT_NULL) + { + rt_hw_usart_register(&usart0_device, RT_USART0_NAME, flag, usart); + } + else + { + break; + } + /* Initialize lock for usart0 */ + if (rt_sem_init(usart->lock, RT_USART0_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + break; + } #endif - /* Register usart1 */ #ifdef RT_USING_USART1 - config = 0x00; - flag = RT_DEVICE_FLAG_RDWR; + config = 0x00; + flag = RT_DEVICE_FLAG_RDWR; #ifdef RT_USART1_SYNC_MODE - config |= USART_STATE_SYNC; + config |= USART_STATE_SYNC; #if (RT_USART1_SYNC_MODE != 0x0UL) - config |= USART_STATE_MASTER; + config |= USART_STATE_MASTER; #else - flag |= RT_DEVICE_FLAG_INT_RX; + flag |= RT_DEVICE_FLAG_INT_RX; #endif #else - flag |= RT_DEVICE_FLAG_INT_RX; + flag |= RT_DEVICE_FLAG_INT_RX; #endif #if (SPI_AUTOCS_ENABLE & (1 << 1)) - config |= USART_STATE_AUTOCS; + config |= USART_STATE_AUTOCS; #endif #if (RT_CONSOLE_DEVICE == 0x1UL) - config |= USART_STATE_CONSOLE; - flag |= RT_DEVICE_FLAG_STREAM; + config |= USART_STATE_CONSOLE; + flag |= RT_DEVICE_FLAG_STREAM; #endif #ifdef RT_USART1_USING_DMA - RT_ASSERT(RT_USART1_USING_DMA < DMA_CHAN_COUNT); - flag |= RT_DEVICE_FLAG_DMA_TX; + RT_ASSERT(RT_USART1_USING_DMA < DMA_CHAN_COUNT); + flag |= RT_DEVICE_FLAG_DMA_TX; #else - - #define RT_USART1_USING_DMA EFM32_NO_DATA + + #define RT_USART1_USING_DMA EFM32_NO_DATA #endif - - if ((usart = rt_hw_usart_unit_init( - &usart1_device, - 1, - RT_USING_USART1, - flag, - RT_USART1_USING_DMA, - config)) != RT_NULL) - { - rt_hw_usart_register(&usart1_device, RT_USART1_NAME, flag, usart); - } + + /* Initialize and Register usart1 */ + if ((usart = rt_hw_usart_unit_init( + &usart1_device, + 1, + RT_USING_USART1, + flag, + RT_USART1_USING_DMA, + config)) != RT_NULL) + { + rt_hw_usart_register(&usart1_device, RT_USART1_NAME, flag, usart); + } + else + { + break; + } + /* Initialize lock for usart1 */ + if (rt_sem_init(usart->lock, RT_USART1_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + break; + } #endif - /* Register usart2 */ #ifdef RT_USING_USART2 - config = 0x00; - flag = RT_DEVICE_FLAG_RDWR; + config = 0x00; + flag = RT_DEVICE_FLAG_RDWR; #ifdef RT_USART2_SYNC_MODE - config |= USART_STATE_SYNC; + config |= USART_STATE_SYNC; #if (RT_USART2_SYNC_MODE != 0x0UL) - config |= USART_STATE_MASTER; + config |= USART_STATE_MASTER; #else - flag |= RT_DEVICE_FLAG_INT_RX; + flag |= RT_DEVICE_FLAG_INT_RX; #endif #else - flag |= RT_DEVICE_FLAG_INT_RX; + flag |= RT_DEVICE_FLAG_INT_RX; #endif #if (SPI_AUTOCS_ENABLE & (1 << 2)) - config |= USART_STATE_AUTOCS; + config |= USART_STATE_AUTOCS; #endif #if (RT_CONSOLE_DEVICE == 0x2UL) - config |= USART_STATE_CONSOLE; - flag |= RT_DEVICE_FLAG_STREAM; + 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; + RT_ASSERT(RT_USART2_USING_DMA < DMA_CHAN_COUNT); + flag |= RT_DEVICE_FLAG_DMA_TX; #else - - #define RT_USART2_USING_DMA EFM32_NO_DATA + + #define RT_USART2_USING_DMA EFM32_NO_DATA #endif - if ((usart = rt_hw_usart_unit_init( - &usart2_device, - 2, - RT_USING_USART2, - flag, - RT_USART2_USING_DMA, - config)) != RT_NULL) - { - rt_hw_usart_register(&usart2_device, RT_USART2_NAME, flag, usart); - } + /* Initialize and Register usart2 */ + if ((usart = rt_hw_usart_unit_init( + &usart2_device, + 2, + RT_USING_USART2, + flag, + RT_USART2_USING_DMA, + config)) != RT_NULL) + { + rt_hw_usart_register(&usart2_device, RT_USART2_NAME, flag, usart); + } + else + { + break; + } + /* Initialize lock for usart2 */ + if (rt_sem_init(usart->lock, RT_USART2_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + break; + } #endif + + usart_debug("USART: H/W init OK!\n"); + return; + } while (0); + + rt_kprintf("USART: H/W init failed!\n"); } -#endif +#endif /* (defined(RT_USING_USART0) || defined(RT_USING_USART1) || defined(RT_USING_USART2)) */ /***************************************************************************//** * @} ******************************************************************************/ diff --git a/bsp/efm32/drv_usart.h b/bsp/efm32/drv_usart.h index 765f3bbe41..89b1fb455d 100644 --- a/bsp/efm32/drv_usart.h +++ b/bsp/efm32/drv_usart.h @@ -13,6 +13,8 @@ * Date Author Notes * 2010-12-22 onelife Initial creation for EFM32 * 2011-06-27 onelife Fix a bug when using compiler optimization + * 2011-07-26 onelife Add lock (semaphore) to prevent simultaneously + * access ******************************************************************************/ #ifndef __DRV_USART_H__ #define __DRV_USART_H__ @@ -21,33 +23,37 @@ /* Exported types ------------------------------------------------------------*/ struct efm32_usart_int_mode_t { - rt_uint8_t *data_ptr; - rt_uint8_t data_size; - rt_uint32_t read_index, save_index; + rt_uint8_t *data_ptr; + rt_uint8_t data_size; + rt_uint32_t read_index, save_index; }; struct efm32_usart_dma_mode_t { /* DMA Channel */ - rt_uint32_t dma_channel; + rt_uint32_t dma_channel; /* buffer info */ - rt_uint32_t *data_ptr; - rt_uint8_t data_size; + rt_uint32_t *data_ptr; + rt_uint8_t data_size; }; struct efm32_usart_device_t { + /* Counter */ + rt_uint32_t counter; + /* Lock */ + struct rt_semaphore *lock; /* Unit number */ - rt_uint8_t unit; + rt_uint8_t unit; /* State */ - volatile rt_uint8_t state; + volatile rt_uint8_t state; /* Pointer to USART device structure */ - USART_TypeDef* usart_device; + USART_TypeDef *usart_device; /* Pointer to RX structure */ - void *rx_mode; + void *rx_mode; /* Pointer to TX structure */ - void *tx_mode; + void *tx_mode; }; /* Exported constants --------------------------------------------------------*/ diff --git a/bsp/efm32/hdl_interrupt.c b/bsp/efm32/hdl_interrupt.c index 7a924f611b..cc26dd11f5 100644 --- a/bsp/efm32/hdl_interrupt.c +++ b/bsp/efm32/hdl_interrupt.c @@ -1,27 +1,28 @@ -/******************************************************************//** +/***************************************************************************//** * @file hdl_interrupt.c * @brief USART driver of RT-Thread RTOS for EFM32 * 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 - ********************************************************************** + * 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-12-29 onelife Initial creation for EFM32 - *********************************************************************/ + * 2011-07-12 onelife Disable interrupts in GPIO handler + ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "board.h" #include "hdl_interrupt.h" -/******************************************************************//** +/***************************************************************************//** * @addtogroup efm32 * @{ -*********************************************************************/ + ******************************************************************************/ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ @@ -44,88 +45,88 @@ efm32_irq_hook_t iicCbTable[I2C_COUNT] = {RT_NULL}; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ -/******************************************************************//** -* @brief -* NMI exception handler -* -* @details -* -* @note -*********************************************************************/ +/***************************************************************************//** + * @brief + * NMI exception handler + * + * @details + * + * @note + ******************************************************************************/ void NMI_Handler(void) { hdl_debug("[NMI_Handler: NOP]\n"); } -/******************************************************************//** -* @brief -* Memory manage exception handler -* -* @details -* -* @note -*********************************************************************/ +/***************************************************************************//** + * @brief + * Memory manage exception handler + * + * @details + * + * @note + ******************************************************************************/ void MemManage_Handler(void) { hdl_debug("[MemManage_Handler: infinite loop]\n"); while (1); } -/******************************************************************//** -* @brief -* Bus fault exception handler -* -* @details -* -* @note -*********************************************************************/ +/***************************************************************************//** + * @brief + * Bus fault exception handler + * + * @details + * + * @note + ******************************************************************************/ void BusFault_Handler(void) { hdl_debug("[BusFault_Handler: infinite loop]\n"); while (1); } -/******************************************************************//** -* @brief -* Usage fault exception handler -* -* @details -* -* @note -*********************************************************************/ +/***************************************************************************//** + * @brief + * Usage fault exception handler + * + * @details + * + * @note + ******************************************************************************/ void UsageFault_Handler(void) { hdl_debug("[UsageFault_Handler: infinite loop]\n"); while (1); } -/******************************************************************//** -* @brief -* Supervisor call exception handler -* -* @details -* -* @note -*********************************************************************/ +/***************************************************************************//** + * @brief + * Supervisor call exception handler + * + * @details + * + * @note + ******************************************************************************/ void SVC_Handler(void) { hdl_debug("[SVC_Handler: NOP]\n"); } -/******************************************************************//** -* @brief -* Debug monitor exception handler -* -* @details -* -* @note -*********************************************************************/ +/***************************************************************************//** + * @brief + * Debug monitor exception handler + * + * @details + * + * @note + ******************************************************************************/ void DebugMon_Handler(void) { hdl_debug("[DebugMon_Handler: NOP]\n"); } -/******************************************************************//** +/***************************************************************************//** * @brief * System tick timer interrupt handler * @@ -133,7 +134,7 @@ void DebugMon_Handler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void SysTick_Handler(void) { /* enter interrupt */ @@ -145,14 +146,14 @@ void SysTick_Handler(void) rt_interrupt_leave(); } -/********************************************************************** +/******************************************************************************* * STM32F10x Peripherals Interrupt Handlers * Add here the Interrupt Handler for the used peripheral(s) (PPP), for the * available peripheral interrupt handler's name please refer to the startup * file (startup_stm32f10x_xx.s). -/*********************************************************************/ +/******************************************************************************/ -/******************************************************************//** +/***************************************************************************//** * @brief * Common DMA interrupt handler * @@ -160,7 +161,7 @@ void SysTick_Handler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user) { /* enter interrupt */ @@ -176,7 +177,7 @@ void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user) rt_interrupt_leave(); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common Timer1 interrupt handler * @@ -185,7 +186,7 @@ void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user) * * @note * - *********************************************************************/ + ******************************************************************************/ void TIMER1_IRQHandler(void) { if (TIMER1->IF & TIMER_IF_OF) @@ -201,7 +202,7 @@ void TIMER1_IRQHandler(void) } } -/******************************************************************//** +/***************************************************************************//** * @brief * Common Timer2 interrupt handler * @@ -210,7 +211,7 @@ void TIMER1_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void TIMER2_IRQHandler(void) { if (TIMER2->IF & TIMER_IF_OF) @@ -226,7 +227,7 @@ void TIMER2_IRQHandler(void) } } -/******************************************************************//** +/***************************************************************************//** * @brief * Common RTC interrupt handler * @@ -235,7 +236,7 @@ void TIMER2_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void RTC_IRQHandler(void) { /* enter interrupt */ @@ -254,7 +255,7 @@ void RTC_IRQHandler(void) rt_interrupt_leave(); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common even number GPIO interrupt handler * @@ -262,12 +263,15 @@ void RTC_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void GPIO_EVEN_IRQHandler(void) { rt_uint16_t flag, n; - - /* enter interrupt */ + rt_base_t level; + + /* Disable interrupt */ + level = rt_hw_interrupt_disable(); + /* Enter ISR */ rt_interrupt_enter(); /* invoke callback function */ @@ -283,11 +287,13 @@ void GPIO_EVEN_IRQHandler(void) /* clear interrupt */ GPIO->IFC = 0x5555UL; - /* leave interrupt */ - rt_interrupt_leave(); + /* Leave ISR */ + rt_interrupt_leave(); + /* Enable interrupt */ + rt_hw_interrupt_enable(level); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common odd number GPIO interrupt handler * @@ -295,12 +301,15 @@ void GPIO_EVEN_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void GPIO_ODD_IRQHandler(void) { rt_uint16_t flag, n; - - /* enter interrupt */ + rt_base_t level; + + /* Disable interrupt */ + level = rt_hw_interrupt_disable(); + /* Enter ISR */ rt_interrupt_enter(); /* invoke callback function */ @@ -316,11 +325,13 @@ void GPIO_ODD_IRQHandler(void) /* clear interrupt */ GPIO->IFC = 0xAAAAUL; - /* leave interrupt */ - rt_interrupt_leave(); + /* Leave ISR */ + rt_interrupt_leave(); + /* Enable interrupt */ + rt_hw_interrupt_enable(level); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common ACMP interrupt handler * @@ -329,7 +340,7 @@ void GPIO_ODD_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void ACMP0_IRQHandler(void) { /* enter interrupt */ @@ -363,7 +374,7 @@ void ACMP0_IRQHandler(void) rt_interrupt_leave(); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common USART0 TX interrupt handler * @@ -372,7 +383,7 @@ void ACMP0_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void USART0_TX_IRQHandler(void) { /* enter interrupt */ @@ -394,7 +405,7 @@ void USART0_TX_IRQHandler(void) rt_interrupt_leave(); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common USART0 RX interrupt handler * @@ -403,7 +414,7 @@ void USART0_TX_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void USART0_RX_IRQHandler(void) { if (USART0->IF & USART_IF_RXDATAV) @@ -416,7 +427,7 @@ void USART0_RX_IRQHandler(void) } } -/******************************************************************//** +/***************************************************************************//** * @brief * Common USART1 TX interrupt handler * @@ -425,7 +436,7 @@ void USART0_RX_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void USART1_TX_IRQHandler(void) { /* enter interrupt */ @@ -447,7 +458,7 @@ void USART1_TX_IRQHandler(void) rt_interrupt_leave(); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common USART1 RX interrupt handler * @@ -456,7 +467,7 @@ void USART1_TX_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void USART1_RX_IRQHandler(void) { if (USART1->IF & USART_IF_RXDATAV) @@ -469,7 +480,7 @@ void USART1_RX_IRQHandler(void) } } -/******************************************************************//** +/***************************************************************************//** * @brief * Common USART2 TX interrupt handler * @@ -478,7 +489,7 @@ void USART1_RX_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void USART2_TX_IRQHandler(void) { /* enter interrupt */ @@ -500,7 +511,7 @@ void USART2_TX_IRQHandler(void) rt_interrupt_leave(); } -/******************************************************************//** +/***************************************************************************//** * @brief * Common USART2 RX interrupt handler * @@ -509,7 +520,7 @@ void USART2_TX_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void USART2_RX_IRQHandler(void) { if (USART2->IF & USART_IF_RXDATAV) @@ -522,7 +533,7 @@ void USART2_RX_IRQHandler(void) } } -/******************************************************************//** +/***************************************************************************//** * @brief * Common IIC0 interrupt handler * @@ -531,7 +542,7 @@ void USART2_RX_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void I2C0_IRQHandler(void) { if ((I2C0->IF & I2C_IF_ADDR) || \ @@ -548,7 +559,7 @@ void I2C0_IRQHandler(void) I2C_IntClear(I2C0, I2C_IFC_ADDR | I2C_IFC_SSTOP); } -/******************************************************************//** +/***************************************************************************//** * @brief * EFM32 common interrupt handlers register function * @@ -556,7 +567,7 @@ void I2C0_IRQHandler(void) * * @note * - *********************************************************************/ + ******************************************************************************/ void efm32_irq_hook_register(efm32_irq_hook_init_t *hook) { switch (hook->type) @@ -604,6 +615,6 @@ void efm32_irq_hook_register(efm32_irq_hook_init_t *hook) hook->type, hook->unit, hook->cbFunc, hook->userPtr); } -/******************************************************************//** +/***************************************************************************//** * @} -*********************************************************************/ + ******************************************************************************/ diff --git a/bsp/efm32/httpd.c b/bsp/efm32/httpd.c index 607e9704fe..fc6e5dbd35 100644 --- a/bsp/efm32/httpd.c +++ b/bsp/efm32/httpd.c @@ -82,7 +82,7 @@ #include "rtthread.h" #include "dev_misc.h" -#if defined(RT_USING_LWIP) +#if defined(RT_USING_LWIP) && defined(EFM32_USING_ETH_HTTPD) #include "lwip\tcp.h" #include "lwip\ip_addr.h" @@ -230,8 +230,7 @@ void httpd_init(void) tcp_accept(pcb, http_accept); } -#endif - +#endif /* defined(RT_USING_LWIP) && defined(EFM32_USING_ETH_HTTPD) */ /***************************************************************************//** * @} ******************************************************************************/ diff --git a/bsp/efm32/rtconfig.h b/bsp/efm32/rtconfig.h index 951225b98f..4db20604ab 100644 --- a/bsp/efm32/rtconfig.h +++ b/bsp/efm32/rtconfig.h @@ -32,6 +32,7 @@ #define RT_DEBUG //#define RT_DEBUG_MEM (1) //#define RT_DEBUG_SCHEDULER (1) +//#define RT_DEBUG_IPC (1) //#define THREAD_DEBUG //#define IRQ_DEBUG #define RT_USING_OVERFLOW_CHECK @@ -47,9 +48,11 @@ //#define RT_TIMER_DEBUG //#define RT_RTC_DEBUG +#define EFM32_DEBUG +#define RT_ACCEL_DEBUG #define EFM32_SFLASH_DEBUG //#define EFM32_SDCARD_DEBUG -#define EFM32_ETHERNET_DEBUG +//#define EFM32_ETHERNET_DEBUG /* Using Hook */ @@ -94,7 +97,7 @@ #elif defined(EFM32_G890_STK) #define RT_USING_USART1 (0x1UL) #define RT_USART1_NAME "debug" -#define RT_USART1_USING_DMA (0x0UL) +//#define RT_USART1_USING_DMA (0x0UL) #endif /* SECTION: SPI options */ @@ -125,7 +128,10 @@ /* SECTION: ADC options */ #define RT_USING_ADC0 -#define RT_ADC0_NAME "adc" +#define RT_ADC0_NAME "adc0" +#if defined(RT_USING_ADC0) +#define RT_USING_MISC +#endif /* SECTION: TIMER options */ //#define RT_USING_TIMER2 (0x00) /* Continuous mode */ @@ -155,11 +161,16 @@ #define FINSH_USING_SYMTAB #define FINSH_USING_DESCRIPTION -/* SECTION: SPI Flash, MicroSD card and Ethernet */ +/* SECTION: Peripheral devices */ #if defined(EFM32_G290_DK) -//#define EFM32_USING_SFLASH -//#define EFM32_USING_SPISD -#define EFM32_USING_ETHERNET +//#define EFM32_USING_ACCEL /* Three axis accelerometer */ +//#define EFM32_USING_SFLASH /* SPI Flash */ +//#define EFM32_USING_SPISD /* MicroSD card */ +#define EFM32_USING_ETHERNET /* Ethernet controller */ +#endif +#if defined(EFM32_USING_ACCEL) +#define ACCEL_USING_DEVICE_NAME RT_ADC0_NAME +#define ACCEL_USING_DMA (0x3UL) #endif #if defined(EFM32_USING_SFLASH) #define SFLASH_USING_DEVICE_NAME RT_USART0_NAME @@ -171,7 +182,7 @@ #if defined(EFM32_USING_ETHERNET) #define ETH_USING_DEVICE_NAME RT_USART2_NAME #define ETH_DEVICE_NAME "spiEth" -#define ETH_ADDR_DEFAULT {0x11, 0x22, 0x33, 0x44, 0x55, 0x66} +#define ETH_ADDR_DEFAULT {0x00, 0x01, 0x02, 0x03, 0x04, 0x05} #endif /* SECTION: device filesystem */ @@ -185,21 +196,29 @@ #define DFS_FD_MAX (4) /* the max number of cached sector */ #define DFS_CACHE_MAX_NUM (4) -#endif +#endif /* defined(EFM32_USING_SPISD) */ /* SECTION: lwip, a lighwight TCP/IP protocol stack */ #if defined(EFM32_USING_ETHERNET) +#define EFM32_USING_ETH_HTTPD +//#define EFM32_USING_ETH_UTILS +//#define hostName "onelife.dyndns.org" +//#define userPwdB64 "dXNlcjpwYXNzd2Q=" + #define RT_USING_LWIP //#define RT_USING_NETUTILS -//#define RT_LWIP_DHCP /* LwIP uses RT-Thread Memory Management */ #define RT_LWIP_USING_RT_MEM /* Enable ICMP protocol*/ #define RT_LWIP_ICMP +/* Enable ICMP protocol*/ +//#define RT_LWIP_IGMP /* Enable UDP protocol*/ #define RT_LWIP_UDP /* Enable TCP protocol*/ #define RT_LWIP_TCP +/* Enable DHCP */ +//#define RT_LWIP_DHCP /* Enable DNS */ //#define RT_LWIP_DNS @@ -227,13 +246,13 @@ /* tcp thread options */ #define RT_LWIP_TCPTHREAD_PRIORITY (12) #define RT_LWIP_TCPTHREAD_MBOX_SIZE (4) -#define RT_LWIP_TCPTHREAD_STACKSIZE (512) +#define RT_LWIP_TCPTHREAD_STACKSIZE (1024) /* ethernet if thread options */ #define RT_LWIP_ETHTHREAD_PRIORITY (15) #define RT_LWIP_ETHTHREAD_MBOX_SIZE (4) #define RT_LWIP_ETHTHREAD_STACKSIZE (512) -#endif +#endif /* defined(EFM32_USING_ETHERNET) */ /* Exported functions ------------------------------------------------------- */ diff --git a/libcpu/arm/cortex-m3/context_gcc.S b/libcpu/arm/cortex-m3/context_gcc.S index 8d4bed2979..c4e2d60fb5 100644 --- a/libcpu/arm/cortex-m3/context_gcc.S +++ b/libcpu/arm/cortex-m3/context_gcc.S @@ -1,25 +1,27 @@ -/******************************************************************//** - * @file context_gcc.S +/***************************************************************************//** + * @file context_gcc.S * @brief Context switch functions * COPYRIGHT (C) 2011, RT-Thread Development Team * @author Bernard, onelife - * @version 0.4 beta - ********************************************************************** + * @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 - ********************************************************************** + * 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 - * 2009-10-11 Bernard first version + * 2009-10-11 Bernard first version * 2010-12-29 onelife Modify for EFM32 - * 2011-06-17 onelife Merge all of the assembly source code into context_gcc.S - *********************************************************************/ + * 2011-06-17 onelife Merge all of the assembly source code into + * context_gcc.S + * 2011-07-12 onelife Add interrupt context check function + ******************************************************************************/ -/******************************************************************//** +/***************************************************************************//** * @addtogroup cortex-m3 * @{ -*********************************************************************/ + ******************************************************************************/ .cpu cortex-m3 .fpu softvfp @@ -174,14 +176,24 @@ rt_hw_interrupt_thread_switch: .type HardFault_Handler, %function HardFault_Handler: /* get current context */ - MRS r0, psp /* get fault thread stack pointer */ - PUSH {lr} + MRS R0, PSP /* get fault thread stack pointer */ + PUSH {LR} BL rt_hw_hard_fault_exception - POP {lr} + POP {LR} - ORR lr, lr, #0x04 - BX lr + ORR LR, LR, #0x04 + BX LR -/******************************************************************//** +/* + * rt_uint32_t rt_hw_interrupt_check(void); + * R0 --> state + */ + .global rt_hw_interrupt_check + .type rt_hw_interrupt_check, %function +rt_hw_interrupt_check: + MRS R0, IPSR + BX LR + +/***************************************************************************//** * @} -*********************************************************************/ + ******************************************************************************/