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 + +/***************************************************************************//** * @} -*********************************************************************/ + ******************************************************************************/