*** EFM32 branch ***

1. Add interrupt context check function (context_gcc.S)
2. Add lock (semaphore) for IIC, USART and Ethernet drivers to prevent simultaneously access
3. Add multiple channels support for scan mode of ADC driver
4. Modify miscellaneous drivers according to ADC driver changes
5. Add SWO output enable function (board.c)
6. Disable all interrupts in GPIO interrupt handler (hdl_interrupt.c)
7. Add two Ethernet utility functions (drv_ethernet.c)
8. Add accelerometer driver (analog output)
9. Add accelerometer demo (draft, application.c)

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1654 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
onelife.real 2011-07-29 02:47:37 +00:00
parent 36c6d994c7
commit 19e3ce5ee3
20 changed files with 2076 additions and 783 deletions

View File

@ -14,4 +14,10 @@
#define EFM32_USING_ETHERNET #define EFM32_USING_ETHERNET
#define RT_USING_LWIP #define RT_USING_LWIP
#RT_LWIP_* #RT_LWIP_*
3. and then compile 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

View File

@ -12,7 +12,7 @@ else:
src_bsp = ['application.c', 'startup.c', 'board.c'] 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_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_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_hdl = ['hdl_interrupt.c']
src_app = ['httpd.c'] src_app = ['httpd.c']

View File

@ -14,6 +14,8 @@
* 2009-01-05 Bernard first version * 2009-01-05 Bernard first version
* 2010-12-29 onelife Modify for EFM32 * 2010-12-29 onelife Modify for EFM32
* 2011-05-06 onelife Add SPI Flash DEMO * 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 #endif
#include "dev_led.h" #include "dev_led.h"
#if defined(EFM32_USING_ACCEL)
#include "dev_accel.h"
#endif
#if defined(EFM32_USING_SFLASH) #if defined(EFM32_USING_SFLASH)
#include "dev_sflash.h" #include "dev_sflash.h"
#endif #endif
@ -48,12 +53,28 @@
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
rt_uint32_t rt_system_status = 0; volatile rt_uint32_t rt_system_status = 0;
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
void rt_demo_thread_entry(void* parameter) 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) #if defined(RT_USING_DFS)
/* Filesystem Initialization */ /* Filesystem Initialization */
dfs_init(); dfs_init();
@ -114,23 +135,42 @@ void rt_demo_thread_entry(void* parameter)
#endif #endif
#if defined(EFM32_USING_ETHERNET) #if defined(EFM32_USING_ETHERNET)
extern void lwip_sys_init(void);
#if defined(EFM32_USING_ETH_HTTPD)
extern void httpd_init(void); extern void httpd_init(void);
#endif
rt_device_t eth = RT_NULL; rt_device_t eth = RT_NULL;
/* find Ethernet device */
eth = rt_device_find(ETH_DEVICE_NAME); eth = rt_device_find(ETH_DEVICE_NAME);
if (eth != RT_NULL) if (eth != RT_NULL)
{ {
/* init Ethernet device */
eth->init(eth); 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(); httpd_init();
rt_kprintf("Http service init OK!\n"); rt_kprintf("Http service init OK!\n");
#endif
} }
else else
{ {
rt_kprintf("%s is not found\n"), ETH_DEVICE_NAME; rt_kprintf("%s is not found\n"), ETH_DEVICE_NAME;
} }
#endif #endif /* defined(EFM32_USING_ETHERNET) */
rt_kprintf("Demo End\n"); rt_kprintf("Demo End\n");
while(1)
{
rt_thread_sleep(10);
}
} }
void rt_led_thread_entry(void* parameter) void rt_led_thread_entry(void* parameter)
@ -158,6 +198,14 @@ int rt_application_init()
{ {
rt_thread_t demo_thread, led_thread; 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 defined(EFM32_USING_SFLASH)
if (efm_spiFlash_init() != RT_EOK) if (efm_spiFlash_init() != RT_EOK)
{ {
@ -180,7 +228,7 @@ int rt_application_init()
rt_kprintf("*** Init LED driver failed!"); rt_kprintf("*** Init LED driver failed!");
while(1); //Or do something? while(1); //Or do something?
} }
#if defined(RT_USING_ADC0) #if defined(RT_USING_MISC)
if (rt_hw_misc_init() != RT_EOK) if (rt_hw_misc_init() != RT_EOK)
{ {
rt_kprintf("*** Init miscellaneous driver failed!"); rt_kprintf("*** Init miscellaneous driver failed!");
@ -190,8 +238,6 @@ int rt_application_init()
#if defined(RT_USING_LWIP) #if defined(RT_USING_LWIP)
{ {
extern void lwip_sys_init(void);
/* Create Ethernet Threads */ /* Create Ethernet Threads */
if (eth_system_device_init() != RT_EOK) if (eth_system_device_init() != RT_EOK)
{ {
@ -205,9 +251,6 @@ int rt_application_init()
while(1); //Or do something? while(1); //Or do something?
} }
#endif #endif
/* init lwip system */
lwip_sys_init();
rt_kprintf("TCP/IP stack init OK!\n");
} }
#endif #endif
@ -216,7 +259,7 @@ int rt_application_init()
"demo", "demo",
rt_demo_thread_entry, rt_demo_thread_entry,
RT_NULL, RT_NULL,
512, 1024,
3, 3,
20); 20);

View File

@ -1,51 +1,52 @@
/******************************************************************//** /***************************************************************************//**
* @file board.c * @file board.c
* @brief USART driver of RT-Thread RTOS for EFM32 * @brief Board support of RT-Thread RTOS for EFM32
* COPYRIGHT (C) 2011, RT-Thread Development Team * COPYRIGHT (C) 2011, RT-Thread Development Team
* @author onelife * @author onelife
* @version 0.4 beta * @version 0.4 beta
********************************************************************** *******************************************************************************
* @section License * @section License
* The license and distribution terms for this file may be found in the file LICENSE in this * The license and distribution terms for this file may be found in the file
* distribution or at http://www.rt-thread.org/license/LICENSE * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
********************************************************************** *******************************************************************************
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2010-12-21 onelife Initial creation for EFM32 * 2010-12-21 onelife Initial creation for EFM32
* 2011-05-06 onelife Add EFM32 development kit and SPI Flash support * 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" #include "board.h"
/* Private typedef -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define --------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == RAM_MEM_BASE) || \ #define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == RAM_MEM_BASE) || \
((VECTTAB) == FLASH_MEM_BASE)) ((VECTTAB) == FLASH_MEM_BASE))
#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) #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_Div8 ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) #define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ #define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
((SOURCE) == SysTick_CLKSource_HCLK_Div8)) ((SOURCE) == SysTick_CLKSource_HCLK_Div8))
/******************************************************************//** /***************************************************************************//**
* @} * @}
*********************************************************************/ ******************************************************************************/
/* Private macro --------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
/* Private variables ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
/* Private function prototypes ---------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
/* Private functions ------------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Set the allocation and offset of the vector table * Set the allocation and offset of the vector table
* *
@ -58,8 +59,10 @@
* *
* @param[in] Offset * @param[in] Offset
* The vector table offset * The vector table offset
*********************************************************************/ ******************************************************************************/
static void NVIC_SetVectorTable(rt_uint32_t NVIC_VectTab, rt_uint32_t Offset) static void NVIC_SetVectorTable(
rt_uint32_t NVIC_VectTab,
rt_uint32_t Offset)
{ {
/* Check the parameters */ /* Check the parameters */
RT_ASSERT(IS_NVIC_VECTTAB(NVIC_VectTab)); RT_ASSERT(IS_NVIC_VECTTAB(NVIC_VectTab));
@ -68,7 +71,7 @@ static void NVIC_SetVectorTable(rt_uint32_t NVIC_VectTab, rt_uint32_t Offset)
SCB->VTOR = NVIC_VectTab | (Offset & (rt_uint32_t)0x1FFFFF80); SCB->VTOR = NVIC_VectTab | (Offset & (rt_uint32_t)0x1FFFFF80);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Configure the address of vector table * Configure the address of vector table
* *
@ -76,7 +79,7 @@ static void NVIC_SetVectorTable(rt_uint32_t NVIC_VectTab, rt_uint32_t Offset)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
static void NVIC_Configuration(void) static void NVIC_Configuration(void)
{ {
#ifdef VECT_TAB_RAM #ifdef VECT_TAB_RAM
@ -87,23 +90,24 @@ static void NVIC_Configuration(void)
NVIC_SetVectorTable(FLASH_MEM_BASE, 0x0); NVIC_SetVectorTable(FLASH_MEM_BASE, 0x0);
#endif #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); NVIC_SetPriorityGrouping(0x7UL);
/* Set Base Priority Mask Register */ /* Set Base Priority Mask Register */
__set_BASEPRI(EFM32_BASE_PRI_DEFAULT); __set_BASEPRI(EFM32_BASE_PRI_DEFAULT);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Enable high frequency crystal oscillator (HFXO), and set HFCLK domain to use HFXO as * Enable high frequency crystal oscillator (HFXO), and set HFCLK domain to
* source. * use HFXO as source.
* *
* @details * @details
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
static void switchToHFXO(void) static void switchToHFXO(void)
{ {
CMU_TypeDef *cmu = CMU; CMU_TypeDef *cmu = CMU;
@ -122,7 +126,7 @@ static void switchToHFXO(void)
cmu->OSCENCMD = CMU_OSCENCMD_HFRCODIS; cmu->OSCENCMD = CMU_OSCENCMD_HFRCODIS;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Configure the SysTick clock source * Configure the SysTick clock source
* *
@ -138,7 +142,7 @@ static void switchToHFXO(void)
* *
* @arg SysTick_CLKSource_HCLK * @arg SysTick_CLKSource_HCLK
* AHB clock selected as SysTick clock source. * AHB clock selected as SysTick clock source.
*********************************************************************/ ******************************************************************************/
static void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) static void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{ {
/* Check the parameters */ /* Check the parameters */
@ -154,7 +158,7 @@ static void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
} }
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Configure the SysTick for OS tick. * Configure the SysTick for OS tick.
* *
@ -162,7 +166,7 @@ static void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
static void SysTick_Configuration(void) static void SysTick_Configuration(void)
{ {
rt_uint32_t core_clock; rt_uint32_t core_clock;
@ -176,7 +180,50 @@ static void SysTick_Configuration(void)
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
} }
/******************************************************************//** /***************************************************************************//**
* @brief
* 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 * @brief
* Initialize the board. * Initialize the board.
* *
@ -184,7 +231,7 @@ static void SysTick_Configuration(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void rt_hw_board_init(void) void rt_hw_board_init(void)
{ {
/* Chip errata */ /* Chip errata */
@ -205,7 +252,7 @@ void rt_hw_board_init(void)
SysTick_Configuration(); SysTick_Configuration();
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Initialize the hardware drivers. * Initialize the hardware drivers.
* *
@ -213,7 +260,7 @@ void rt_hw_board_init(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void rt_hw_driver_init(void) void rt_hw_driver_init(void)
{ {
CMU_ClockEnable(cmuClock_HFPER, true); 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 */ /* Enabling clock to the interface of the low energy modules */
CMU_ClockEnable(cmuClock_CORELE, true); CMU_ClockEnable(cmuClock_CORELE, true);
#ifdef EFM32_SWO_ENABLE
/* Enable SWO */
setupSWO();
#endif
/* Initialize DMA */ /* Initialize DMA */
rt_hw_dma_init(); rt_hw_dma_init();
@ -265,7 +317,6 @@ void rt_hw_driver_init(void)
#endif #endif
} }
/******************************************************************//** /***************************************************************************//**
* @} * @}
*********************************************************************/ ******************************************************************************/

View File

@ -1,19 +1,21 @@
/******************************************************************//** /***************************************************************************//**
* @file drv_dma.h * @file board.h
* @brief USART driver of RT-Thread RTOS for EFM32 * @brief Board support of RT-Thread RTOS for EFM32
* COPYRIGHT (C) 2011, RT-Thread Development Team * COPYRIGHT (C) 2011, RT-Thread Development Team
* @author onelife * @author onelife
* @version 0.4 beta * @version 0.4 beta
********************************************************************** *******************************************************************************
* @section License * @section License
* The license and distribution terms for this file may be found in the file LICENSE in this * The license and distribution terms for this file may be found in the file
* distribution or at http://www.rt-thread.org/license/LICENSE * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
********************************************************************** *******************************************************************************
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2010-12-21 onelife Initial creation for EFM32 * 2010-12-21 onelife Initial creation for EFM32
* 2011-05-06 onelife Add EFM32 development kit and SPI Flash support * 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__ #ifndef __BOARD_H__
#define __BOARD_H__ #define __BOARD_H__
@ -24,7 +26,7 @@
#error Unknown MCU type #error Unknown MCU type
#endif #endif
/* Includes -------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include <efm32.h> #include <efm32.h>
#include <efm32_chip.h> #include <efm32_chip.h>
#include <efm32_cmu.h> #include <efm32_cmu.h>
@ -44,18 +46,22 @@
#include <dvk.h> #include <dvk.h>
#endif #endif
/* Exported types -------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
/* Exported constants ---------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/
/* Exported variables ----------------------------------------------------------*/ /* Exported variables --------------------------------------------------------*/
extern rt_uint32_t rt_system_status; extern volatile rt_uint32_t rt_system_status;
/* Exported macro -------------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/
#ifdef EFM32_DEBUG
#define DEBUG_EFM #define DEBUG_EFM
#define DEBUG_EFM_USER #define DEBUG_EFM_USER
#define EFM32_SWO_ENABLE
#endif
#define EFM32_NO_DATA (0) #define EFM32_NO_DATA (0)
#define EFM32_NO_OFFSET (-1)
#define EFM32_NO_POINTER (RT_NULL) #define EFM32_NO_POINTER (RT_NULL)
#define EFM32_NO_OFFSET (-1)
#define EFM32_NO_DMA (-1)
/* SECTION: SPI Flash */ /* SECTION: SPI Flash */
#if defined(EFM32_USING_SFLASH) #if defined(EFM32_USING_SFLASH)
@ -79,7 +85,7 @@ extern rt_uint32_t rt_system_status;
#endif #endif
/* SECTION: SYSTEM */ /* 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_BASE_PRI_DEFAULT (0x0UL << 5)
#define EFM32_IRQ_PRI_DEFAULT (0x4UL << 5) #define EFM32_IRQ_PRI_DEFAULT (0x4UL << 5)
#if (defined(EFM32_G890_STK) || defined(EFM32_G290_DK)) #if (defined(EFM32_G890_STK) || defined(EFM32_G290_DK))
@ -95,6 +101,7 @@ extern rt_uint32_t rt_system_status;
#define UART_BAUDRATE (115200) #define UART_BAUDRATE (115200)
/* SUBSECTION: SPI */ /* SUBSECTION: SPI */
/* Max SPI clock: HFPERCLK/2 for master, HFPERCLK/8 for slave */
#define SPI_BAUDRATE (4000000) #define SPI_BAUDRATE (4000000)
#ifndef USART_0_AUTOCS #ifndef USART_0_AUTOCS
@ -107,7 +114,9 @@ extern rt_uint32_t rt_system_status;
#define USART_2_AUTOCS (0) #define USART_2_AUTOCS (0)
#endif #endif
/* Auto Slave Select */ /* 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 */ /* SECTION: I2C */
#define IIC_RX_BUFFER_SIZE (32) #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_INIT (0xF6) /*!< Initialize ACMP */
#define RT_DEVICE_CTRL_ACMP_OUTPUT (0xF7) /*!< get ACMP output */ #define RT_DEVICE_CTRL_ACMP_OUTPUT (0xF7) /*!< get ACMP output */
/* Exported functions --------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */
void rt_hw_board_init(void); void rt_hw_board_init(void);
void rt_hw_driver_init(void); void rt_hw_driver_init(void);
rt_uint32_t rt_hw_interrupt_check(void);
#endif /*__BOARD_H__ */ #endif /*__BOARD_H__ */

266
bsp/efm32/dev_accel.c Normal file
View File

@ -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 <finsh.h>
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
/***************************************************************************//**
* @}
******************************************************************************/

40
bsp/efm32/dev_accel.h Normal file
View File

@ -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__ */

View File

@ -12,6 +12,7 @@
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2011-02-22 onelife Initial creation for EFM32 * 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 "board.h"
#include "drv_adc.h" #include "drv_adc.h"
#if defined(RT_USING_MISC)
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
@ -34,7 +36,8 @@
/* Private constants ---------------------------------------------------------*/ /* Private constants ---------------------------------------------------------*/
static rt_device_t adc0; static rt_device_t adc0;
static struct efm32_adc_control_t control = {ADC_MODE_SINGLE}; static struct efm32_adc_control_t control = \
{ADC_MODE_SINGLE, {}, {0, (rt_uint8_t)EFM32_NO_DMA}};
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
@ -56,6 +59,7 @@ rt_int32_t efm32_misc_getCelsius(rt_uint32_t adcSample);
rt_int32_t rt_hw_get_temp(void) rt_int32_t rt_hw_get_temp(void)
{ {
ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
struct efm32_adc_result_t result;
rt_uint32_t temp; rt_uint32_t temp;
/* Set input to temperature sensor. Acquisition time must be 256 cycles. /* Set input to temperature sensor. Acquisition time must be 256 cycles.
@ -64,10 +68,12 @@ rt_int32_t rt_hw_get_temp(void)
singleInit.reference = adcRef1V25; singleInit.reference = adcRef1V25;
singleInit.input = adcSingleInpTemp; 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_ADC_MODE, &control);
adc0->control(adc0, RT_DEVICE_CTRL_RESUME, EFM32_NO_POINTER); result.mode = control.mode;
adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &temp); 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); return efm32_misc_getCelsius(temp);
} }
@ -87,6 +93,7 @@ rt_int32_t rt_hw_get_temp(void)
rt_uint32_t rt_hw_get_vdd(void) rt_uint32_t rt_hw_get_vdd(void)
{ {
ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
struct efm32_adc_result_t result;
rt_uint32_t vdd; rt_uint32_t vdd;
/* Set input to temperature sensor. Reference must be 1.25V */ /* Set input to temperature sensor. Reference must be 1.25V */
@ -94,10 +101,12 @@ rt_uint32_t rt_hw_get_vdd(void)
singleInit.reference = adcRef1V25; singleInit.reference = adcRef1V25;
singleInit.input = adcSingleInpVDDDiv3; 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_ADC_MODE, &control);
adc0->control(adc0, RT_DEVICE_CTRL_RESUME, EFM32_NO_POINTER); result.mode = control.mode;
adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &vdd); 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; 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) rt_err_t rt_hw_misc_init(void)
{ {
do
{
/* Find ADC device */
adc0 = rt_device_find(RT_ADC0_NAME); adc0 = rt_device_find(RT_ADC0_NAME);
if (adc0 == RT_NULL) if (adc0 == RT_NULL)
{ {
misc_debug("Batt err: Can't find device: %s!\n", RT_ADC0_NAME); misc_debug("Batt err: Can't find device: %s!\n", RT_ADC0_NAME);
goto MISC_INIT_ERROR; break;
} }
return RT_EOK; 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"); misc_debug("Misc err: Init failed!\n");
return -RT_ERROR; 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); return (cal_temp - (cal_value - (rt_int32_t)adcResult * 10000) / t_grad);
} }
/***************************************************************************//** /*******************************************************************************
* Export to FINSH * Export to FINSH
******************************************************************************/ ******************************************************************************/
#ifdef RT_USING_FINSH #ifdef RT_USING_FINSH
@ -183,8 +196,9 @@ void list_vdd(void)
} }
FINSH_FUNCTION_EXPORT(list_vdd, list current VDD value.) FINSH_FUNCTION_EXPORT(list_vdd, list current VDD value.)
#endif #endif /* RT_USING_FINSH */
#endif /* defined(RT_USING_MISC) */
/***************************************************************************//** /***************************************************************************//**
* @} * @}
******************************************************************************/ ******************************************************************************/

View File

@ -12,6 +12,7 @@
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2011-02-21 onelife Initial creation for EFM32 * 2011-02-21 onelife Initial creation for EFM32
* 2011-07-14 onelife Add multiple channels support for scan mode
******************************************************************************/ ******************************************************************************/
/***************************************************************************//** /***************************************************************************//**
@ -37,310 +38,10 @@
#ifdef RT_USING_ADC0 #ifdef RT_USING_ADC0
static struct rt_device adc0_device; static struct rt_device adc0_device;
#endif #endif
static rt_uint32_t adcErrataShift = 0;
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
rt_uint32_t efm32_adc_calibration(
ADC_TypeDef *adc,
ADC_Ref_TypeDef ref,
ADC_SingleInput_TypeDef input);
/* Private functions ---------------------------------------------------------*/ /* 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 * @brief
* Calibrate offset and gain for the specified reference. * Calibrate offset and gain for the specified reference.
@ -498,6 +199,635 @@ rt_uint32_t efm32_adc_calibration(
return adc->CAL; 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 #endif
/***************************************************************************//** /***************************************************************************//**
* @} * @}

View File

@ -12,6 +12,7 @@
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2011-02-21 onelife Initial creation for EFM32 * 2011-02-21 onelife Initial creation for EFM32
* 2011-07-14 onelife Add multiple channels support for scan mode
******************************************************************************/ ******************************************************************************/
#ifndef __DRV_ADC_H__ #ifndef __DRV_ADC_H__
#define __DRV_ADC_H__ #define __DRV_ADC_H__
@ -21,21 +22,49 @@
struct efm32_adc_device_t struct efm32_adc_device_t
{ {
ADC_TypeDef *adc_device; 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 struct efm32_adc_control_t
{ {
rt_uint32_t mode; rt_uint8_t mode;
ADC_InitSingle_TypeDef *singleInit; struct efm32_adc_control_scan_t scan;
ADC_InitScan_TypeDef *scanInit; struct efm32_adc_control_single_t single;
};
struct efm32_adc_result_t
{
rt_uint8_t mode;
void *buffer;
}; };
/* Exported constants --------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/
#define ADC_MODE_SINGLE 0x00UL #define ADC_MODE_SINGLE (0x01)
#define ADC_MODE_SCAN 0x01UL #define ADC_MODE_SCAN (0x02)
#define ADC_MODE_TAILGATE 0x02UL #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 ------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */
void rt_hw_adc_init(void); void rt_hw_adc_init(void);

View File

@ -15,6 +15,9 @@
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2011-06-22 onelife Initial creation for using EFM32 USART module * 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; rt_uint8_t reg_eir, data;
volatile rt_uint8_t cnt; volatile rt_uint8_t cnt;
/* Disable RX interrutp */ /* Disable RX and other interrutps */
data = EIE_PKTIE; data = EIE_PKTIE | EIE_INTIE;
efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data); efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
/* Get interrupt flag */ /* Get interrupt flag */
@ -410,6 +413,10 @@ void efm_eth_isr(rt_device_t dev)
/* Inform Ethernet thread */ /* Inform Ethernet thread */
eth_device_ready(&eth_dev); eth_device_ready(&eth_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(EPMM1, 0x30);
efm_eth_writeReg(EPMCSL, 0xf9); efm_eth_writeReg(EPMCSL, 0xf9);
efm_eth_writeReg(EPMCSH, 0xf7); efm_eth_writeReg(EPMCSH, 0xf7);
efm_eth_writeReg(ERXFCON, efm_eth_writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);
ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);
//efm_eth_writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); //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) /* 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 */ 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; rt_uint16_t len_rx, sta_rx;
struct pbuf* p; struct pbuf* p;
p = RT_NULL;
/* Lock device */ /* Lock device */
rt_sem_take(&ethLock, RT_WAITING_FOREVER); rt_sem_take(&ethLock, RT_WAITING_FOREVER);
/* Disable interrupts */ /* Disable interrupts */
data = EIE_INTIE; data = EIE_INTIE;
efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data); efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data);
p = RT_NULL;
reg_eie = 0; reg_eie = 0;
if (efm_eth_readReg(EPKTCNT)) 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); eth_debug("ETH: ***** read RX (q->len %x) *****\n", q->len);
for (i = 0; i < q->len; i += 8) 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], temp[i + 1], temp[i + 2], temp[i + 3],
temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7], 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 #endif
@ -820,6 +827,7 @@ struct pbuf *efm_eth_rx(rt_device_t dev)
/* Enable interrupts */ /* Enable interrupts */
reg_eie |= EIE_INTIE; reg_eie |= EIE_INTIE;
efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &reg_eie); efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &reg_eie);
/* Unlock device */ /* Unlock device */
rt_sem_release(&ethLock); rt_sem_release(&ethLock);
@ -850,6 +858,7 @@ rt_err_t efm_eth_tx(rt_device_t dev, struct pbuf* p)
/* Lock device */ /* Lock device */
rt_sem_take(&ethLock, RT_WAITING_FOREVER); rt_sem_take(&ethLock, RT_WAITING_FOREVER);
/* Disable interrupts */ /* Disable interrupts */
data = EIE_INTIE; data = EIE_INTIE;
efm_eth_sendCmd(ENC28J60_BIT_FIELD_CLR, EIE, &data); 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); eth_debug("ETH: ***** write TX (len %d) *****\n", p->len);
for (i = 0; i < q->len; i += 8) 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], temp[i + 1], temp[i + 2], temp[i + 3],
temp[i + 4], temp[i + 5], temp[i + 6], temp[i + 7], 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 #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); efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, ECON1, &data);
} }
/* Waiting for a while */
rt_thread_delay(ETH_PERIOD_WAIT_INIT);
/* Enable interrupts */ /* Enable interrupts */
data = EIE_INTIE; data = EIE_INTIE;
efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data); efm_eth_sendCmd(ENC28J60_BIT_FIELD_SET, EIE, &data);
/* Unlock device */ /* Unlock device */
rt_sem_release(&ethLock); rt_sem_release(&ethLock);
@ -983,7 +996,7 @@ rt_err_t efm_hw_eth_init(void)
USART_BaudrateSyncSet(usart->usart_device, 0, ETH_CLK_MAX); USART_BaudrateSyncSet(usart->usart_device, 0, ETH_CLK_MAX);
/* Initialize semaphore */ /* Initialize semaphore */
rt_sem_init(&ethLock, "lck_eth", 1, RT_IPC_FLAG_FIFO); rt_sem_init(&ethLock, ETH_DEVICE_NAME, 1, RT_IPC_FLAG_FIFO);
/* Register Ethernet device */ /* Register Ethernet device */
eth_dev.parent.init = efm_eth_init; eth_dev.parent.init = efm_eth_init;
@ -1011,6 +1024,7 @@ rt_err_t efm_hw_eth_init(void)
/***************************************************************************//** /***************************************************************************//**
* Export to FINSH * Export to FINSH
******************************************************************************/ ******************************************************************************/
#if defined(EFM32_USING_ETH_UTILS)
#ifdef RT_USING_FINSH #ifdef RT_USING_FINSH
#include <finsh.h> #include <finsh.h>
@ -1021,9 +1035,6 @@ void list_eth(void)
rt_kprintf(" ENC28J60 on %s\n", ETH_USING_DEVICE_NAME); rt_kprintf(" ENC28J60 on %s\n", ETH_USING_DEVICE_NAME);
rt_kprintf(" ------------------------------\n"); 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); reg_phy = efm_eth_readPhy(PHSTAT2);
if (reg_phy & PHSTAT2_PLRITY) if (reg_phy & PHSTAT2_PLRITY)
{ {
@ -1075,8 +1086,244 @@ void list_eth(void)
} }
} }
FINSH_FUNCTION_EXPORT(list_eth, list the Ethernet device status.) 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 #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) */ #endif /* defined(EFM32_USING_ETHERNET) */
/******************************************************************//** /******************************************************************//**
* @} * @}

View File

@ -30,9 +30,9 @@
//#define ETH_HALF_DUPLEX //#define ETH_HALF_DUPLEX
#define ETH_PERIOD_WAIT_INIT (RT_TICK_PER_SECOND/100) #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_SPI_RX_SKIP (1)
#define ETH_RESET_PORT (gpioPortB) #define ETH_RESET_PORT (gpioPortB)
#define ETH_RESET_PIN (9) #define ETH_RESET_PIN (9)
#define ETH_INT_PORT (gpioPortB) #define ETH_INT_PORT (gpioPortB)

View File

@ -1,47 +1,49 @@
/******************************************************************//** /***************************************************************************//**
* @file drv_iic.c * @file drv_iic.c
* @brief Serial API of RT-Thread RTOS for EFM32 * @brief Serial API of RT-Thread RTOS for EFM32
* COPYRIGHT (C) 2011, RT-Thread Development Team * COPYRIGHT (C) 2011, RT-Thread Development Team
* @author onelife * @author onelife
* @version 0.4 beta * @version 0.4 beta
********************************************************************** *******************************************************************************
* @section License * @section License
* The license and distribution terms for this file may be found in the file LICENSE in this * The license and distribution terms for this file may be found in the file
* distribution or at http://www.rt-thread.org/license/LICENSE * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
********************************************************************** *******************************************************************************
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2011-01-06 onelife Initial creation for EFM32 * 2011-01-06 onelife Initial creation for EFM32
* 2011-06-17 onelife Modify init function for efm32lib v2 upgrading * 2011-06-17 onelife Modify init function for efm32lib v2 upgrading
*********************************************************************/ * 2011-07-11 onelife Add lock (semaphore) to prevent simultaneously
* access
******************************************************************************/
/******************************************************************//** /***************************************************************************//**
* @addtogroup efm32 * @addtogroup efm32
* @{ * @{
*********************************************************************/ ******************************************************************************/
/* Includes -------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "board.h" #include "board.h"
#include "hdl_interrupt.h" #include "hdl_interrupt.h"
#include "drv_iic.h" #include "drv_iic.h"
#if (defined(RT_USING_IIC0) || defined(RT_USING_IIC1)) #if (defined(RT_USING_IIC0) || defined(RT_USING_IIC1))
/* Private typedef -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define --------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
/* Private macro --------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
#ifdef RT_IIC_DEBUG #ifdef RT_IIC_DEBUG
#define iic_debug(format,args...) rt_kprintf(format, ##args) #define iic_debug(format,args...) rt_kprintf(format, ##args)
#else #else
#define iic_debug(format,args...) #define iic_debug(format,args...)
#endif #endif
/* Private variables ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
#ifdef RT_USING_IIC0 #ifdef RT_USING_IIC0
#if (RT_USING_IIC0 > 3) #if (RT_USING_IIC0 > 3)
#error "The location number range of IIC is 0~3" #error "The location number range of IIC is 0~3"
#endif #endif
struct rt_device iic0_device; struct rt_device iic0_device;
static struct rt_device iic0_rx_index; static struct rt_semaphore iic0_lock;
#endif #endif
#ifdef RT_USING_IIC1 #ifdef RT_USING_IIC1
@ -49,12 +51,12 @@
#error "The location number range of IIC is 0~3" #error "The location number range of IIC is 0~3"
#endif #endif
struct rt_device iic1_device; struct rt_device iic1_device;
static struct rt_device iic1_rx_index; static struct rt_semaphore iic1_lock;
#endif #endif
/* Private function prototypes ---------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
/* Private functions ------------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Initialize IIC device * Initialize IIC device
* *
@ -67,7 +69,7 @@
* *
* @return * @return
* Error code * Error code
*********************************************************************/ ******************************************************************************/
static rt_err_t rt_iic_init (rt_device_t dev) static rt_err_t rt_iic_init (rt_device_t dev)
{ {
struct efm32_iic_device_t* iic; struct efm32_iic_device_t* iic;
@ -87,7 +89,7 @@ static rt_err_t rt_iic_init (rt_device_t dev)
return RT_EOK; return RT_EOK;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Open IIC device * Open IIC device
* *
@ -103,16 +105,21 @@ static rt_err_t rt_iic_init (rt_device_t dev)
* *
* @return * @return
* Error code * Error code
*********************************************************************/ ******************************************************************************/
static rt_err_t rt_iic_open(rt_device_t dev, rt_uint16_t oflag) static rt_err_t rt_iic_open(rt_device_t dev, rt_uint16_t oflag)
{ {
RT_ASSERT(dev != RT_NULL); 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); iic_debug("IIC: Open with flag %x\n", oflag);
return RT_EOK; return RT_EOK;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Close IIC device * Close IIC device
* *
@ -125,21 +132,24 @@ static rt_err_t rt_iic_open(rt_device_t dev, rt_uint16_t oflag)
* *
* @return * @return
* Error code * Error code
*********************************************************************/ ******************************************************************************/
static rt_err_t rt_iic_close(rt_device_t dev) static rt_err_t rt_iic_close(rt_device_t dev)
{ {
RT_ASSERT(dev != RT_NULL);
struct efm32_iic_device_t *iic; struct efm32_iic_device_t *iic;
iic = (struct efm32_iic_device_t *)(dev->user_data); iic = (struct efm32_iic_device_t *)(dev->user_data);
if (--iic->counter == 0)
{
rt_free(iic->rx_buffer->data_ptr); rt_free(iic->rx_buffer->data_ptr);
rt_free(iic->rx_buffer); rt_free(iic->rx_buffer);
iic->rx_buffer = RT_NULL; iic->rx_buffer = RT_NULL;
}
return RT_EOK; return RT_EOK;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Read from IIC device * Read from IIC device
* *
@ -161,7 +171,7 @@ static rt_err_t rt_iic_close(rt_device_t dev)
* *
* @return * @return
* Error code * Error code
*********************************************************************/ ******************************************************************************/
static rt_size_t rt_iic_read ( static rt_size_t rt_iic_read (
rt_device_t dev, rt_device_t dev,
rt_off_t pos, rt_off_t pos,
@ -185,6 +195,20 @@ static rt_size_t rt_iic_read (
iic = (struct efm32_iic_device_t*)dev->user_data; iic = (struct efm32_iic_device_t*)dev->user_data;
data[0] = (rt_uint8_t)(pos & 0x000000FF); 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) if (iic->state & IIC_STATE_MASTER)
{ {
seq.addr = iic->slave_address; 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); iic_debug("IIC0 slave read size: %d\n", read_size);
} }
/* Unlock device */
rt_sem_release(iic->lock);
/* set error code */ /* set error code */
rt_set_errno(err_code); rt_set_errno(err_code);
return read_size; return read_size;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Write to IIC device * Write to IIC device
* *
@ -294,7 +321,7 @@ static rt_size_t rt_iic_read (
* *
* @return * @return
* Error code * Error code
*********************************************************************/ ******************************************************************************/
static rt_size_t rt_iic_write ( static rt_size_t rt_iic_write (
rt_device_t dev, rt_device_t dev,
rt_off_t pos, rt_off_t pos,
@ -306,7 +333,6 @@ static rt_size_t rt_iic_write (
struct efm32_iic_device_t* iic; struct efm32_iic_device_t* iic;
I2C_TransferSeq_TypeDef seq; I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret; I2C_TransferReturn_TypeDef ret;
//rt_uint8_t data[1];
if (!size) if (!size)
{ {
@ -316,7 +342,20 @@ static rt_size_t rt_iic_write (
err_code = RT_EOK; err_code = RT_EOK;
write_size = 0; write_size = 0;
iic = (struct efm32_iic_device_t*)dev->user_data; 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) if (iic->state & IIC_STATE_MASTER)
{ {
@ -360,12 +399,15 @@ static rt_size_t rt_iic_write (
write_size = size; write_size = size;
} }
/* Unlock device */
rt_sem_release(iic->lock);
/* set error code */ /* set error code */
rt_set_errno(err_code); rt_set_errno(err_code);
return write_size; return write_size;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Configure IIC device * Configure IIC device
* *
@ -384,7 +426,7 @@ static rt_size_t rt_iic_write (
* *
* @return * @return
* Error code * Error code
*********************************************************************/ ******************************************************************************/
static rt_err_t rt_iic_control ( static rt_err_t rt_iic_control (
rt_device_t dev, rt_device_t dev,
rt_uint8_t cmd, rt_uint8_t cmd,
@ -392,9 +434,25 @@ static rt_err_t rt_iic_control (
{ {
RT_ASSERT(dev != RT_NULL); RT_ASSERT(dev != RT_NULL);
rt_err_t ret;
struct efm32_iic_device_t *iic; struct efm32_iic_device_t *iic;
iic = (struct efm32_iic_device_t*)dev->user_data; 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) switch (cmd)
{ {
case RT_DEVICE_CTRL_SUSPEND: case RT_DEVICE_CTRL_SUSPEND:
@ -475,10 +533,13 @@ static rt_err_t rt_iic_control (
break; break;
} }
/* Unlock device */
rt_sem_release(iic->lock);
return RT_EOK; return RT_EOK;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Register IIC device * Register IIC device
* *
@ -500,7 +561,7 @@ static rt_err_t rt_iic_control (
* *
* @return * @return
* Error code * Error code
*********************************************************************/ ******************************************************************************/
rt_err_t rt_hw_iic_register( rt_err_t rt_hw_iic_register(
rt_device_t device, rt_device_t device,
const char *name, 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); return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* IIC slave mode RX data valid interrupt handler * IIC slave mode RX data valid interrupt handler
* *
@ -540,7 +601,7 @@ rt_err_t rt_hw_iic_register(
* *
* @param[in] dev * @param[in] dev
* Pointer to device descriptor * Pointer to device descriptor
*********************************************************************/ ******************************************************************************/
static void rt_hw_iic_slave_isr(rt_device_t dev) static void rt_hw_iic_slave_isr(rt_device_t dev)
{ {
struct efm32_iic_device_t *iic; struct efm32_iic_device_t *iic;
@ -607,7 +668,7 @@ static void rt_hw_iic_slave_isr(rt_device_t dev)
} }
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Initialize the specified IIC unit * Initialize the specified IIC unit
* *
@ -620,7 +681,7 @@ static void rt_hw_iic_slave_isr(rt_device_t dev)
* *
* @param[in] location * @param[in] location
* Pin location number * Pin location number
*********************************************************************/ ******************************************************************************/
static struct efm32_iic_device_t *rt_hw_iic_unit_init( static struct efm32_iic_device_t *rt_hw_iic_unit_init(
rt_device_t device, rt_device_t device,
rt_uint8_t unitNumber, 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)); iic = rt_malloc(sizeof(struct efm32_iic_device_t));
if (iic == RT_NULL) 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; break;
} }
iic->counter = 0;
iic->state |= IIC_STATE_MASTER; iic->state |= IIC_STATE_MASTER;
iic->master_address = 0x0000; iic->master_address = 0x0000;
iic->slave_address = 0x0000; iic->slave_address = 0x0000;
@ -653,12 +715,14 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init(
switch (unitNumber) switch (unitNumber)
{ {
case 0: case 0:
iic->lock = &iic0_lock;
iic->iic_device = I2C0; iic->iic_device = I2C0;
iicClock = (CMU_Clock_TypeDef)cmuClock_I2C0; iicClock = (CMU_Clock_TypeDef)cmuClock_I2C0;
break; break;
#if (I2C_COUNT > 1) #if (I2C_COUNT > 1)
case 1: case 1:
iic->lock = &iic1_lock;
iic->iic_device = I2C1; iic->iic_device = I2C1;
iicClock = (CMU_Clock_TypeDef)cmuClock_I2C1; iicClock = (CMU_Clock_TypeDef)cmuClock_I2C1;
break; break;
@ -710,43 +774,71 @@ static struct efm32_iic_device_t *rt_hw_iic_unit_init(
{ {
rt_free(iic); rt_free(iic);
} }
rt_kprintf("IIC: Init failed!\n");
iic_debug("IIC: Unit %d init failed!\n", unitNumber);
return RT_NULL; return RT_NULL;
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Initialize all IIC module related hardware and register IIC device to kernel * Initialize all IIC module related hardware and register IIC device to kernel
* *
* @details * @details
* *
* @note * @note
*********************************************************************/ ******************************************************************************/
void rt_hw_iic_init(void) void rt_hw_iic_init(void)
{ {
struct efm32_iic_device_t *iic; struct efm32_iic_device_t *iic;
rt_uint32_t flag; rt_uint32_t flag;
do
{
flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
/* register iic0 */
#ifdef RT_USING_IIC0 #ifdef RT_USING_IIC0
/* Initialize and register iic0 */
if ((iic = rt_hw_iic_unit_init(&iic0_device, 0, RT_USING_IIC0)) != RT_NULL) 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); 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 #endif
/* register iic1 */
#ifdef RT_USING_IIC1 #ifdef RT_USING_IIC1
/* Initialize and register iic1 */
if ((iic = rt_hw_iic_unit_init(&iic1_device, 1, RT_USING_IIC1)) != RT_NULL) 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); rt_hw_iic_register(&iic1_device, RT_IIC1_NAME, flag, iic);
} }
#endif else
{
break;
} }
/* Initialize lock for iic1 */
if (rt_sem_init(iic->lock, RT_IIC1_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
{
break;
}
#endif #endif
/******************************************************************//**
iic_debug("IIC: H/W init OK!\n");
return;
} while (0);
rt_kprintf("IIC: H/W init failed!\n");
}
#endif /* (defined(RT_USING_IIC0) || defined(RT_USING_IIC1)) */
/***************************************************************************//**
* @} * @}
*********************************************************************/ ******************************************************************************/

View File

@ -1,23 +1,25 @@
/******************************************************************//** /***************************************************************************//**
* @file drv_iic.h * @file drv_iic.h
* @brief IIC driver of RT-Thread RTOS for EFM32 * @brief IIC driver of RT-Thread RTOS for EFM32
* COPYRIGHT (C) 2011, RT-Thread Development Team * COPYRIGHT (C) 2011, RT-Thread Development Team
* @author onelife * @author onelife
* @version 0.4 beta * @version 0.4 beta
********************************************************************** *******************************************************************************
* @section License * @section License
* The license and distribution terms for this file may be found in the file LICENSE in this * The license and distribution terms for this file may be found in the file
* distribution or at http://www.rt-thread.org/license/LICENSE * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
********************************************************************** *******************************************************************************
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2011-01-07 onelife Initial creation for EFM32 * 2011-01-07 onelife Initial creation for EFM32
*********************************************************************/ * 2011-07-11 onelife Add lock (semaphore) to prevent simultaneously
* access
******************************************************************************/
#ifndef __DRV_IIC_H__ #ifndef __DRV_IIC_H__
#define __DRV_IIC_H__ #define __DRV_IIC_H__
/* Includes -------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
/* Exported types -------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
struct efm32_iic_int_mode_t struct efm32_iic_int_mode_t
{ {
rt_uint8_t *data_ptr; rt_uint8_t *data_ptr;
@ -27,6 +29,10 @@ struct efm32_iic_int_mode_t
struct efm32_iic_device_t struct efm32_iic_device_t
{ {
/* Counter */
rt_uint32_t counter;
/* Lock */
struct rt_semaphore *lock;
/* State */ /* State */
rt_uint8_t state; rt_uint8_t state;
/* Pointer to IIC device structure */ /* Pointer to IIC device structure */
@ -46,14 +52,14 @@ struct efm32_iic_control_t
rt_uint16_t slave_address; rt_uint16_t slave_address;
}; };
/* Exported constants ---------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/
/* Exported macro -------------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/
#define IIC_STATE_MASTER (1 << 0) #define IIC_STATE_MASTER (1 << 0)
#define IIC_STATE_BROADCAST (1 << 1) #define IIC_STATE_BROADCAST (1 << 1)
//#define IIC_STATE_TX_BUSY (1 << 2) //#define IIC_STATE_TX_BUSY (1 << 2)
#define IIC_STATE_RX_BUSY (1 << 3) #define IIC_STATE_RX_BUSY (1 << 3)
/* Exported functions --------------------------------------------------------- */ /* Exported functions --------------------------------------------------------*/
void rt_hw_iic_init(void); void rt_hw_iic_init(void);
#endif /* __DRV_IIC_H__ */ #endif /* __DRV_IIC_H__ */

View File

@ -17,6 +17,8 @@
* 2011-06-14 onelife Fix a bug of TX by DMA * 2011-06-14 onelife Fix a bug of TX by DMA
* 2011-06-16 onelife Modify init function for efm32lib v2 upgrading * 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-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 * @section Change Logs of serial.c
* 2009-02-05 Bernard first version * 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" #error "The location number range of usart is 0~3"
#endif #endif
struct rt_device usart0_device; struct rt_device usart0_device;
static struct rt_semaphore usart0_lock;
#endif #endif
#ifdef RT_USING_USART1 #ifdef RT_USING_USART1
@ -64,6 +67,7 @@ union efm32_usart_init_t
#error "The location number range of usart is 0~3" #error "The location number range of usart is 0~3"
#endif #endif
struct rt_device usart1_device; struct rt_device usart1_device;
static struct rt_semaphore usart1_lock;
#endif #endif
#ifdef RT_USING_USART2 #ifdef RT_USING_USART2
@ -71,6 +75,7 @@ union efm32_usart_init_t
#error "The location number range of usart is 0~3" #error "The location number range of usart is 0~3"
#endif #endif
struct rt_device usart2_device; struct rt_device usart2_device;
static struct rt_semaphore usart2_lock;
#endif #endif
/* Private function prototypes -----------------------------------------------*/ /* 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); NVIC_SetPriority(DMA_IRQn, EFM32_IRQ_PRI_DEFAULT);
} }
usart->counter++;
usart_debug("USART%d: Open with flag %x\n", usart->unit, oflag); usart_debug("USART%d: Open with flag %x\n", usart->unit, oflag);
return RT_EOK; return RT_EOK;
} }
@ -222,17 +228,26 @@ static rt_err_t rt_usart_open(rt_device_t dev, rt_uint16_t oflag)
* Error code * Error code
******************************************************************************/ ******************************************************************************/
static rt_err_t rt_usart_close(rt_device_t dev) static rt_err_t rt_usart_close(rt_device_t dev)
{
RT_ASSERT(dev != 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) if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{ {
struct efm32_usart_int_mode_t *int_rx; struct efm32_usart_int_mode_t *int_rx;
int_rx = (struct efm32_usart_int_mode_t *)\ int_rx = (struct efm32_usart_int_mode_t *)usart->rx_mode;
(((struct efm32_usart_device_t *)(dev->user_data))->rx_mode);
rt_free(int_rx->data_ptr); rt_free(int_rx->data_ptr);
int_rx->data_ptr = RT_NULL; int_rx->data_ptr = RT_NULL;
} }
}
return RT_EOK; return RT_EOK;
} }
@ -265,11 +280,27 @@ static rt_size_t rt_usart_read (
void *buffer, void *buffer,
rt_size_t size) rt_size_t size)
{ {
struct efm32_usart_device_t *usart;
rt_uint8_t *ptr; rt_uint8_t *ptr;
rt_err_t err_code; rt_err_t err_code;
rt_size_t read_len; rt_size_t read_len;
err_code = RT_EOK; 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_INT_RX) if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{ {
@ -384,6 +415,9 @@ static rt_size_t rt_usart_read (
read_len = size; read_len = size;
} }
/* Unlock device */
rt_sem_release(usart->lock);
/* set error code */ /* set error code */
rt_set_errno(err_code); rt_set_errno(err_code);
return read_len; return read_len;
@ -422,10 +456,24 @@ static rt_size_t rt_usart_write (
rt_size_t write_size; rt_size_t write_size;
struct efm32_usart_device_t* usart; struct efm32_usart_device_t* usart;
err_code = RT_EOK;
write_size = 0; write_size = 0;
usart = (struct efm32_usart_device_t*)(dev->user_data); 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)) if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (size > 2))
{ /* DMA mode Tx */ { /* DMA mode Tx */
struct efm32_usart_dma_mode_t *dma_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; write_size = (rt_size_t)ptr - (rt_size_t)buffer;
} }
/* Unlock device */
rt_sem_release(usart->lock);
/* set error code */ /* set error code */
rt_set_errno(err_code); rt_set_errno(err_code);
return write_size; return write_size;
@ -535,10 +586,25 @@ static rt_err_t rt_usart_control (
{ {
RT_ASSERT(dev != RT_NULL); RT_ASSERT(dev != RT_NULL);
rt_err_t err_code;
struct efm32_usart_device_t *usart; struct efm32_usart_device_t *usart;
usart = (struct efm32_usart_device_t *)(dev->user_data); 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) switch (cmd)
{ {
case RT_DEVICE_CTRL_SUSPEND: case RT_DEVICE_CTRL_SUSPEND:
@ -577,7 +643,8 @@ static rt_err_t rt_usart_control (
== RT_NULL) == RT_NULL)
{ {
usart_debug("USART: no memory for RX buffer\n"); usart_debug("USART: no memory for RX buffer\n");
return -RT_ENOMEM; err_code = -RT_ENOMEM;
break;
} }
// TODO: Is the following line necessary? // TODO: Is the following line necessary?
//rt_memset(int_rx->data_ptr, 0, size); //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) if ((int_rx->data_ptr = rt_malloc(size)) == RT_NULL)
{ {
usart_debug("USART: no memory for RX buffer\n"); usart_debug("USART: no memory for RX buffer\n");
return -RT_ENOMEM; err_code = -RT_ENOMEM;
break;
} }
} }
int_rx->data_size = size; 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); usart_debug("USART: no memory for USART%d device\n", unitNumber);
break; break;
} }
usart->counter = 0;
usart->unit = unitNumber; usart->unit = unitNumber;
usart->state = config; usart->state = config;
usart->tx_mode = RT_NULL; usart->tx_mode = RT_NULL;
@ -848,18 +920,21 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init(
switch (unitNumber) switch (unitNumber)
{ {
case 0: case 0:
usart->lock = &usart0_lock;
usart->usart_device = USART0; usart->usart_device = USART0;
usartClock = (CMU_Clock_TypeDef)cmuClock_USART0; usartClock = (CMU_Clock_TypeDef)cmuClock_USART0;
txDmaSelect = DMAREQ_USART0_TXBL; txDmaSelect = DMAREQ_USART0_TXBL;
break; break;
case 1: case 1:
usart->lock = &usart1_lock;
usart->usart_device = USART1; usart->usart_device = USART1;
usartClock = (CMU_Clock_TypeDef)cmuClock_USART1; usartClock = (CMU_Clock_TypeDef)cmuClock_USART1;
txDmaSelect = DMAREQ_USART1_TXBL; txDmaSelect = DMAREQ_USART1_TXBL;
break; break;
case 2: case 2:
usart->lock = &usart2_lock;
usart->usart_device = USART2; usart->usart_device = USART2;
usartClock = (CMU_Clock_TypeDef)cmuClock_USART2; usartClock = (CMU_Clock_TypeDef)cmuClock_USART2;
txDmaSelect = DMAREQ_USART2_TXBL; txDmaSelect = DMAREQ_USART2_TXBL;
@ -1017,6 +1092,8 @@ static struct efm32_usart_device_t *rt_hw_usart_unit_init(
{ {
rt_free(usart); rt_free(usart);
} }
usart_debug("USART: Unit %d init failed!\n", unitNumber);
return RT_NULL; return RT_NULL;
} }
@ -1035,7 +1112,8 @@ void rt_hw_usart_init(void)
rt_uint32_t flag; rt_uint32_t flag;
rt_uint8_t config; rt_uint8_t config;
/* Register usart0 */ do
{
#ifdef RT_USING_USART0 #ifdef RT_USING_USART0
config = 0x00; config = 0x00;
flag = RT_DEVICE_FLAG_RDWR; flag = RT_DEVICE_FLAG_RDWR;
@ -1067,6 +1145,7 @@ void rt_hw_usart_init(void)
#define RT_USART0_USING_DMA EFM32_NO_DATA #define RT_USART0_USING_DMA EFM32_NO_DATA
#endif #endif
/* Initialize and Register usart0 */
if ((usart = rt_hw_usart_unit_init( if ((usart = rt_hw_usart_unit_init(
&usart0_device, &usart0_device,
0, 0,
@ -1077,9 +1156,17 @@ void rt_hw_usart_init(void)
{ {
rt_hw_usart_register(&usart0_device, RT_USART0_NAME, flag, usart); 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 #endif
/* Register usart1 */
#ifdef RT_USING_USART1 #ifdef RT_USING_USART1
config = 0x00; config = 0x00;
flag = RT_DEVICE_FLAG_RDWR; flag = RT_DEVICE_FLAG_RDWR;
@ -1112,6 +1199,7 @@ void rt_hw_usart_init(void)
#define RT_USART1_USING_DMA EFM32_NO_DATA #define RT_USART1_USING_DMA EFM32_NO_DATA
#endif #endif
/* Initialize and Register usart1 */
if ((usart = rt_hw_usart_unit_init( if ((usart = rt_hw_usart_unit_init(
&usart1_device, &usart1_device,
1, 1,
@ -1122,9 +1210,17 @@ void rt_hw_usart_init(void)
{ {
rt_hw_usart_register(&usart1_device, RT_USART1_NAME, flag, usart); 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 #endif
/* Register usart2 */
#ifdef RT_USING_USART2 #ifdef RT_USING_USART2
config = 0x00; config = 0x00;
flag = RT_DEVICE_FLAG_RDWR; flag = RT_DEVICE_FLAG_RDWR;
@ -1158,6 +1254,7 @@ void rt_hw_usart_init(void)
#define RT_USART2_USING_DMA EFM32_NO_DATA #define RT_USART2_USING_DMA EFM32_NO_DATA
#endif #endif
/* Initialize and Register usart2 */
if ((usart = rt_hw_usart_unit_init( if ((usart = rt_hw_usart_unit_init(
&usart2_device, &usart2_device,
2, 2,
@ -1168,10 +1265,25 @@ void rt_hw_usart_init(void)
{ {
rt_hw_usart_register(&usart2_device, RT_USART2_NAME, flag, usart); 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 #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)) */
/***************************************************************************//** /***************************************************************************//**
* @} * @}
******************************************************************************/ ******************************************************************************/

View File

@ -13,6 +13,8 @@
* Date Author Notes * Date Author Notes
* 2010-12-22 onelife Initial creation for EFM32 * 2010-12-22 onelife Initial creation for EFM32
* 2011-06-27 onelife Fix a bug when using compiler optimization * 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__ #ifndef __DRV_USART_H__
#define __DRV_USART_H__ #define __DRV_USART_H__
@ -38,6 +40,10 @@ struct efm32_usart_dma_mode_t
struct efm32_usart_device_t struct efm32_usart_device_t
{ {
/* Counter */
rt_uint32_t counter;
/* Lock */
struct rt_semaphore *lock;
/* Unit number */ /* Unit number */
rt_uint8_t unit; rt_uint8_t unit;
/* State */ /* State */

View File

@ -1,27 +1,28 @@
/******************************************************************//** /***************************************************************************//**
* @file hdl_interrupt.c * @file hdl_interrupt.c
* @brief USART driver of RT-Thread RTOS for EFM32 * @brief USART driver of RT-Thread RTOS for EFM32
* COPYRIGHT (C) 2011, RT-Thread Development Team * COPYRIGHT (C) 2011, RT-Thread Development Team
* @author onelife * @author onelife
* @version 0.4 beta * @version 0.4 beta
********************************************************************** *******************************************************************************
* @section License * @section License
* The license and distribution terms for this file may be found in the file LICENSE in this * The license and distribution terms for this file may be found in the file
* distribution or at http://www.rt-thread.org/license/LICENSE * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
********************************************************************** *******************************************************************************
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2010-12-29 onelife Initial creation for EFM32 * 2010-12-29 onelife Initial creation for EFM32
*********************************************************************/ * 2011-07-12 onelife Disable interrupts in GPIO handler
******************************************************************************/
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "board.h" #include "board.h"
#include "hdl_interrupt.h" #include "hdl_interrupt.h"
/******************************************************************//** /***************************************************************************//**
* @addtogroup efm32 * @addtogroup efm32
* @{ * @{
*********************************************************************/ ******************************************************************************/
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
@ -44,88 +45,88 @@ efm32_irq_hook_t iicCbTable[I2C_COUNT] = {RT_NULL};
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* NMI exception handler * NMI exception handler
* *
* @details * @details
* *
* @note * @note
*********************************************************************/ ******************************************************************************/
void NMI_Handler(void) void NMI_Handler(void)
{ {
hdl_debug("[NMI_Handler: NOP]\n"); hdl_debug("[NMI_Handler: NOP]\n");
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Memory manage exception handler * Memory manage exception handler
* *
* @details * @details
* *
* @note * @note
*********************************************************************/ ******************************************************************************/
void MemManage_Handler(void) void MemManage_Handler(void)
{ {
hdl_debug("[MemManage_Handler: infinite loop]\n"); hdl_debug("[MemManage_Handler: infinite loop]\n");
while (1); while (1);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Bus fault exception handler * Bus fault exception handler
* *
* @details * @details
* *
* @note * @note
*********************************************************************/ ******************************************************************************/
void BusFault_Handler(void) void BusFault_Handler(void)
{ {
hdl_debug("[BusFault_Handler: infinite loop]\n"); hdl_debug("[BusFault_Handler: infinite loop]\n");
while (1); while (1);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Usage fault exception handler * Usage fault exception handler
* *
* @details * @details
* *
* @note * @note
*********************************************************************/ ******************************************************************************/
void UsageFault_Handler(void) void UsageFault_Handler(void)
{ {
hdl_debug("[UsageFault_Handler: infinite loop]\n"); hdl_debug("[UsageFault_Handler: infinite loop]\n");
while (1); while (1);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Supervisor call exception handler * Supervisor call exception handler
* *
* @details * @details
* *
* @note * @note
*********************************************************************/ ******************************************************************************/
void SVC_Handler(void) void SVC_Handler(void)
{ {
hdl_debug("[SVC_Handler: NOP]\n"); hdl_debug("[SVC_Handler: NOP]\n");
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Debug monitor exception handler * Debug monitor exception handler
* *
* @details * @details
* *
* @note * @note
*********************************************************************/ ******************************************************************************/
void DebugMon_Handler(void) void DebugMon_Handler(void)
{ {
hdl_debug("[DebugMon_Handler: NOP]\n"); hdl_debug("[DebugMon_Handler: NOP]\n");
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* System tick timer interrupt handler * System tick timer interrupt handler
* *
@ -133,7 +134,7 @@ void DebugMon_Handler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void SysTick_Handler(void) void SysTick_Handler(void)
{ {
/* enter interrupt */ /* enter interrupt */
@ -145,14 +146,14 @@ void SysTick_Handler(void)
rt_interrupt_leave(); rt_interrupt_leave();
} }
/********************************************************************** /*******************************************************************************
* STM32F10x Peripherals Interrupt Handlers * STM32F10x Peripherals Interrupt Handlers
* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the * Add here the Interrupt Handler for the used peripheral(s) (PPP), for the
* available peripheral interrupt handler's name please refer to the startup * available peripheral interrupt handler's name please refer to the startup
* file (startup_stm32f10x_xx.s). * file (startup_stm32f10x_xx.s).
/*********************************************************************/ /******************************************************************************/
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common DMA interrupt handler * Common DMA interrupt handler
* *
@ -160,7 +161,7 @@ void SysTick_Handler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user) void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user)
{ {
/* enter interrupt */ /* enter interrupt */
@ -176,7 +177,7 @@ void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user)
rt_interrupt_leave(); rt_interrupt_leave();
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common Timer1 interrupt handler * Common Timer1 interrupt handler
* *
@ -185,7 +186,7 @@ void DMA_IRQHandler_All(unsigned int channel, bool primary, void *user)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void TIMER1_IRQHandler(void) void TIMER1_IRQHandler(void)
{ {
if (TIMER1->IF & TIMER_IF_OF) if (TIMER1->IF & TIMER_IF_OF)
@ -201,7 +202,7 @@ void TIMER1_IRQHandler(void)
} }
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common Timer2 interrupt handler * Common Timer2 interrupt handler
* *
@ -210,7 +211,7 @@ void TIMER1_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void TIMER2_IRQHandler(void) void TIMER2_IRQHandler(void)
{ {
if (TIMER2->IF & TIMER_IF_OF) if (TIMER2->IF & TIMER_IF_OF)
@ -226,7 +227,7 @@ void TIMER2_IRQHandler(void)
} }
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common RTC interrupt handler * Common RTC interrupt handler
* *
@ -235,7 +236,7 @@ void TIMER2_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void RTC_IRQHandler(void) void RTC_IRQHandler(void)
{ {
/* enter interrupt */ /* enter interrupt */
@ -254,7 +255,7 @@ void RTC_IRQHandler(void)
rt_interrupt_leave(); rt_interrupt_leave();
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common even number GPIO interrupt handler * Common even number GPIO interrupt handler
* *
@ -262,12 +263,15 @@ void RTC_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void GPIO_EVEN_IRQHandler(void) void GPIO_EVEN_IRQHandler(void)
{ {
rt_uint16_t flag, n; rt_uint16_t flag, n;
rt_base_t level;
/* enter interrupt */ /* Disable interrupt */
level = rt_hw_interrupt_disable();
/* Enter ISR */
rt_interrupt_enter(); rt_interrupt_enter();
/* invoke callback function */ /* invoke callback function */
@ -283,11 +287,13 @@ void GPIO_EVEN_IRQHandler(void)
/* clear interrupt */ /* clear interrupt */
GPIO->IFC = 0x5555UL; GPIO->IFC = 0x5555UL;
/* leave interrupt */ /* Leave ISR */
rt_interrupt_leave(); rt_interrupt_leave();
/* Enable interrupt */
rt_hw_interrupt_enable(level);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common odd number GPIO interrupt handler * Common odd number GPIO interrupt handler
* *
@ -295,12 +301,15 @@ void GPIO_EVEN_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void GPIO_ODD_IRQHandler(void) void GPIO_ODD_IRQHandler(void)
{ {
rt_uint16_t flag, n; rt_uint16_t flag, n;
rt_base_t level;
/* enter interrupt */ /* Disable interrupt */
level = rt_hw_interrupt_disable();
/* Enter ISR */
rt_interrupt_enter(); rt_interrupt_enter();
/* invoke callback function */ /* invoke callback function */
@ -316,11 +325,13 @@ void GPIO_ODD_IRQHandler(void)
/* clear interrupt */ /* clear interrupt */
GPIO->IFC = 0xAAAAUL; GPIO->IFC = 0xAAAAUL;
/* leave interrupt */ /* Leave ISR */
rt_interrupt_leave(); rt_interrupt_leave();
/* Enable interrupt */
rt_hw_interrupt_enable(level);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common ACMP interrupt handler * Common ACMP interrupt handler
* *
@ -329,7 +340,7 @@ void GPIO_ODD_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void ACMP0_IRQHandler(void) void ACMP0_IRQHandler(void)
{ {
/* enter interrupt */ /* enter interrupt */
@ -363,7 +374,7 @@ void ACMP0_IRQHandler(void)
rt_interrupt_leave(); rt_interrupt_leave();
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common USART0 TX interrupt handler * Common USART0 TX interrupt handler
* *
@ -372,7 +383,7 @@ void ACMP0_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void USART0_TX_IRQHandler(void) void USART0_TX_IRQHandler(void)
{ {
/* enter interrupt */ /* enter interrupt */
@ -394,7 +405,7 @@ void USART0_TX_IRQHandler(void)
rt_interrupt_leave(); rt_interrupt_leave();
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common USART0 RX interrupt handler * Common USART0 RX interrupt handler
* *
@ -403,7 +414,7 @@ void USART0_TX_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void USART0_RX_IRQHandler(void) void USART0_RX_IRQHandler(void)
{ {
if (USART0->IF & USART_IF_RXDATAV) if (USART0->IF & USART_IF_RXDATAV)
@ -416,7 +427,7 @@ void USART0_RX_IRQHandler(void)
} }
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common USART1 TX interrupt handler * Common USART1 TX interrupt handler
* *
@ -425,7 +436,7 @@ void USART0_RX_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void USART1_TX_IRQHandler(void) void USART1_TX_IRQHandler(void)
{ {
/* enter interrupt */ /* enter interrupt */
@ -447,7 +458,7 @@ void USART1_TX_IRQHandler(void)
rt_interrupt_leave(); rt_interrupt_leave();
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common USART1 RX interrupt handler * Common USART1 RX interrupt handler
* *
@ -456,7 +467,7 @@ void USART1_TX_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void USART1_RX_IRQHandler(void) void USART1_RX_IRQHandler(void)
{ {
if (USART1->IF & USART_IF_RXDATAV) if (USART1->IF & USART_IF_RXDATAV)
@ -469,7 +480,7 @@ void USART1_RX_IRQHandler(void)
} }
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common USART2 TX interrupt handler * Common USART2 TX interrupt handler
* *
@ -478,7 +489,7 @@ void USART1_RX_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void USART2_TX_IRQHandler(void) void USART2_TX_IRQHandler(void)
{ {
/* enter interrupt */ /* enter interrupt */
@ -500,7 +511,7 @@ void USART2_TX_IRQHandler(void)
rt_interrupt_leave(); rt_interrupt_leave();
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common USART2 RX interrupt handler * Common USART2 RX interrupt handler
* *
@ -509,7 +520,7 @@ void USART2_TX_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void USART2_RX_IRQHandler(void) void USART2_RX_IRQHandler(void)
{ {
if (USART2->IF & USART_IF_RXDATAV) if (USART2->IF & USART_IF_RXDATAV)
@ -522,7 +533,7 @@ void USART2_RX_IRQHandler(void)
} }
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* Common IIC0 interrupt handler * Common IIC0 interrupt handler
* *
@ -531,7 +542,7 @@ void USART2_RX_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void I2C0_IRQHandler(void) void I2C0_IRQHandler(void)
{ {
if ((I2C0->IF & I2C_IF_ADDR) || \ if ((I2C0->IF & I2C_IF_ADDR) || \
@ -548,7 +559,7 @@ void I2C0_IRQHandler(void)
I2C_IntClear(I2C0, I2C_IFC_ADDR | I2C_IFC_SSTOP); I2C_IntClear(I2C0, I2C_IFC_ADDR | I2C_IFC_SSTOP);
} }
/******************************************************************//** /***************************************************************************//**
* @brief * @brief
* EFM32 common interrupt handlers register function * EFM32 common interrupt handlers register function
* *
@ -556,7 +567,7 @@ void I2C0_IRQHandler(void)
* *
* @note * @note
* *
*********************************************************************/ ******************************************************************************/
void efm32_irq_hook_register(efm32_irq_hook_init_t *hook) void efm32_irq_hook_register(efm32_irq_hook_init_t *hook)
{ {
switch (hook->type) 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); hook->type, hook->unit, hook->cbFunc, hook->userPtr);
} }
/******************************************************************//** /***************************************************************************//**
* @} * @}
*********************************************************************/ ******************************************************************************/

View File

@ -82,7 +82,7 @@
#include "rtthread.h" #include "rtthread.h"
#include "dev_misc.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\tcp.h"
#include "lwip\ip_addr.h" #include "lwip\ip_addr.h"
@ -230,8 +230,7 @@ void httpd_init(void)
tcp_accept(pcb, http_accept); tcp_accept(pcb, http_accept);
} }
#endif #endif /* defined(RT_USING_LWIP) && defined(EFM32_USING_ETH_HTTPD) */
/***************************************************************************//** /***************************************************************************//**
* @} * @}
******************************************************************************/ ******************************************************************************/

View File

@ -32,6 +32,7 @@
#define RT_DEBUG #define RT_DEBUG
//#define RT_DEBUG_MEM (1) //#define RT_DEBUG_MEM (1)
//#define RT_DEBUG_SCHEDULER (1) //#define RT_DEBUG_SCHEDULER (1)
//#define RT_DEBUG_IPC (1)
//#define THREAD_DEBUG //#define THREAD_DEBUG
//#define IRQ_DEBUG //#define IRQ_DEBUG
#define RT_USING_OVERFLOW_CHECK #define RT_USING_OVERFLOW_CHECK
@ -47,9 +48,11 @@
//#define RT_TIMER_DEBUG //#define RT_TIMER_DEBUG
//#define RT_RTC_DEBUG //#define RT_RTC_DEBUG
#define EFM32_DEBUG
#define RT_ACCEL_DEBUG
#define EFM32_SFLASH_DEBUG #define EFM32_SFLASH_DEBUG
//#define EFM32_SDCARD_DEBUG //#define EFM32_SDCARD_DEBUG
#define EFM32_ETHERNET_DEBUG //#define EFM32_ETHERNET_DEBUG
/* Using Hook */ /* Using Hook */
@ -94,7 +97,7 @@
#elif defined(EFM32_G890_STK) #elif defined(EFM32_G890_STK)
#define RT_USING_USART1 (0x1UL) #define RT_USING_USART1 (0x1UL)
#define RT_USART1_NAME "debug" #define RT_USART1_NAME "debug"
#define RT_USART1_USING_DMA (0x0UL) //#define RT_USART1_USING_DMA (0x0UL)
#endif #endif
/* SECTION: SPI options */ /* SECTION: SPI options */
@ -125,7 +128,10 @@
/* SECTION: ADC options */ /* SECTION: ADC options */
#define RT_USING_ADC0 #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 */ /* SECTION: TIMER options */
//#define RT_USING_TIMER2 (0x00) /* Continuous mode */ //#define RT_USING_TIMER2 (0x00) /* Continuous mode */
@ -155,11 +161,16 @@
#define FINSH_USING_SYMTAB #define FINSH_USING_SYMTAB
#define FINSH_USING_DESCRIPTION #define FINSH_USING_DESCRIPTION
/* SECTION: SPI Flash, MicroSD card and Ethernet */ /* SECTION: Peripheral devices */
#if defined(EFM32_G290_DK) #if defined(EFM32_G290_DK)
//#define EFM32_USING_SFLASH //#define EFM32_USING_ACCEL /* Three axis accelerometer */
//#define EFM32_USING_SPISD //#define EFM32_USING_SFLASH /* SPI Flash */
#define EFM32_USING_ETHERNET //#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 #endif
#if defined(EFM32_USING_SFLASH) #if defined(EFM32_USING_SFLASH)
#define SFLASH_USING_DEVICE_NAME RT_USART0_NAME #define SFLASH_USING_DEVICE_NAME RT_USART0_NAME
@ -171,7 +182,7 @@
#if defined(EFM32_USING_ETHERNET) #if defined(EFM32_USING_ETHERNET)
#define ETH_USING_DEVICE_NAME RT_USART2_NAME #define ETH_USING_DEVICE_NAME RT_USART2_NAME
#define ETH_DEVICE_NAME "spiEth" #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 #endif
/* SECTION: device filesystem */ /* SECTION: device filesystem */
@ -185,21 +196,29 @@
#define DFS_FD_MAX (4) #define DFS_FD_MAX (4)
/* the max number of cached sector */ /* the max number of cached sector */
#define DFS_CACHE_MAX_NUM (4) #define DFS_CACHE_MAX_NUM (4)
#endif #endif /* defined(EFM32_USING_SPISD) */
/* SECTION: lwip, a lighwight TCP/IP protocol stack */ /* SECTION: lwip, a lighwight TCP/IP protocol stack */
#if defined(EFM32_USING_ETHERNET) #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_LWIP
//#define RT_USING_NETUTILS //#define RT_USING_NETUTILS
//#define RT_LWIP_DHCP
/* LwIP uses RT-Thread Memory Management */ /* LwIP uses RT-Thread Memory Management */
#define RT_LWIP_USING_RT_MEM #define RT_LWIP_USING_RT_MEM
/* Enable ICMP protocol*/ /* Enable ICMP protocol*/
#define RT_LWIP_ICMP #define RT_LWIP_ICMP
/* Enable ICMP protocol*/
//#define RT_LWIP_IGMP
/* Enable UDP protocol*/ /* Enable UDP protocol*/
#define RT_LWIP_UDP #define RT_LWIP_UDP
/* Enable TCP protocol*/ /* Enable TCP protocol*/
#define RT_LWIP_TCP #define RT_LWIP_TCP
/* Enable DHCP */
//#define RT_LWIP_DHCP
/* Enable DNS */ /* Enable DNS */
//#define RT_LWIP_DNS //#define RT_LWIP_DNS
@ -227,13 +246,13 @@
/* tcp thread options */ /* tcp thread options */
#define RT_LWIP_TCPTHREAD_PRIORITY (12) #define RT_LWIP_TCPTHREAD_PRIORITY (12)
#define RT_LWIP_TCPTHREAD_MBOX_SIZE (4) #define RT_LWIP_TCPTHREAD_MBOX_SIZE (4)
#define RT_LWIP_TCPTHREAD_STACKSIZE (512) #define RT_LWIP_TCPTHREAD_STACKSIZE (1024)
/* ethernet if thread options */ /* ethernet if thread options */
#define RT_LWIP_ETHTHREAD_PRIORITY (15) #define RT_LWIP_ETHTHREAD_PRIORITY (15)
#define RT_LWIP_ETHTHREAD_MBOX_SIZE (4) #define RT_LWIP_ETHTHREAD_MBOX_SIZE (4)
#define RT_LWIP_ETHTHREAD_STACKSIZE (512) #define RT_LWIP_ETHTHREAD_STACKSIZE (512)
#endif #endif /* defined(EFM32_USING_ETHERNET) */
/* Exported functions ------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */

View File

@ -1,25 +1,27 @@
/******************************************************************//** /***************************************************************************//**
* @file context_gcc.S * @file context_gcc.S
* @brief Context switch functions * @brief Context switch functions
* COPYRIGHT (C) 2011, RT-Thread Development Team * COPYRIGHT (C) 2011, RT-Thread Development Team
* @author Bernard, onelife * @author Bernard, onelife
* @version 0.4 beta * @version 0.4 beta
********************************************************************** *******************************************************************************
* @section License * @section License
* The license and distribution terms for this file may be found in the file LICENSE in this * The license and distribution terms for this file may be found in the file
* distribution or at http://www.rt-thread.org/license/LICENSE * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
********************************************************************** *******************************************************************************
* @section Change Logs * @section Change Logs
* Date Author Notes * Date Author Notes
* 2009-10-11 Bernard first version * 2009-10-11 Bernard first version
* 2010-12-29 onelife Modify for EFM32 * 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 * @addtogroup cortex-m3
* @{ * @{
*********************************************************************/ ******************************************************************************/
.cpu cortex-m3 .cpu cortex-m3
.fpu softvfp .fpu softvfp
@ -174,14 +176,24 @@ rt_hw_interrupt_thread_switch:
.type HardFault_Handler, %function .type HardFault_Handler, %function
HardFault_Handler: HardFault_Handler:
/* get current context */ /* get current context */
MRS r0, psp /* get fault thread stack pointer */ MRS R0, PSP /* get fault thread stack pointer */
PUSH {lr} PUSH {LR}
BL rt_hw_hard_fault_exception BL rt_hw_hard_fault_exception
POP {lr} POP {LR}
ORR lr, lr, #0x04 ORR LR, LR, #0x04
BX lr 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
/***************************************************************************//**
* @} * @}
*********************************************************************/ ******************************************************************************/