浏览代码

Merge pull request #41 from RT-Thread/master

update
Meco Jianting Man 4 年之前
父节点
当前提交
6d7dafe090

+ 6 - 0
bsp/bluetrum/ab32vg1-ab-prougen/.config

@@ -23,7 +23,12 @@ CONFIG_IDLE_THREAD_STACK_SIZE=512
 CONFIG_RT_USING_TIMER_SOFT=y
 CONFIG_RT_TIMER_THREAD_PRIO=4
 CONFIG_RT_TIMER_THREAD_STACK_SIZE=256
+
+#
+# kservice optimization
+#
 # CONFIG_RT_KSERVICE_USING_STDLIB is not set
+# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
 CONFIG_RT_DEBUG=y
 # CONFIG_RT_DEBUG_COLOR is not set
 # CONFIG_RT_DEBUG_INIT_CONFIG is not set
@@ -545,6 +550,7 @@ CONFIG_BSP_USING_UART0=y
 # CONFIG_BSP_USING_TIM is not set
 # CONFIG_BSP_USING_ONCHIP_RTC is not set
 # CONFIG_BSP_USING_ADC is not set
+# CONFIG_BSP_USING_IRRX is not set
 
 #
 # Board extended module Drivers

+ 1 - 1
bsp/bluetrum/ab32vg1-ab-prougen/README.md

@@ -34,7 +34,7 @@ ab32vg1-prougen 是 中科蓝讯(Bluetrum) 推出的一款基于 RISC-V 内核
 | :----------- | :----------: | :---------------------------------------- |
 | USB 转串口   |     支持     |                                           |
 | SD卡         |     支持     |                                           |
-| IRDA         |   即将支持   |                                           |
+| IRDA         |     支持     |                                           |
 | 音频接口     |     支持     | 支持音频输出                              |
 | **片上外设** | **支持情况** | **备注**                                  |
 | GPIO         |     支持     | PA PB PE PF                               |

+ 12 - 0
bsp/bluetrum/ab32vg1-ab-prougen/board/Kconfig

@@ -192,6 +192,18 @@ menu "On-chip Peripheral Drivers"
                 default y
         endif
 
+    menuconfig BSP_USING_IRRX
+        bool "Enable IRRX(HW or SW)"
+        default n
+        if BSP_USING_IRRX
+            config BSP_USING_IRRX_HW
+                bool "Enable hardware IRRX"
+                default y
+            config BSP_USING_IRRX_SW
+                bool "Enable software IRRX"
+                default n
+        endif
+
 endmenu
 
 menu "Board extended module Drivers"

+ 3 - 0
bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h

@@ -19,6 +19,9 @@
 #define RT_USING_TIMER_SOFT
 #define RT_TIMER_THREAD_PRIO 4
 #define RT_TIMER_THREAD_STACK_SIZE 256
+
+/* kservice optimization */
+
 #define RT_DEBUG
 
 /* Inter-Thread communication */

+ 3 - 0
bsp/bluetrum/libraries/hal_drivers/SConscript

@@ -34,6 +34,9 @@ if GetDepend('RT_USING_RTC'):
 if GetDepend('RT_USING_ADC'):
     src += ['drv_adc.c']
 
+if GetDepend('BSP_USING_IRRX'):
+    src += ['drv_irrx.c']
+
 group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
 
 objs = [group]

+ 219 - 0
bsp/bluetrum/libraries/hal_drivers/drv_irrx.c

@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2021-04-12     greedyhao         first version
+ */
+
+#include <board.h>
+
+#ifdef BSP_USING_IRRX
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.irrx"
+#include <drv_log.h>
+
+#ifdef BSP_USING_TIM3
+#error "IRRX is conflict with hardware timer3!"
+#endif
+
+#ifdef BSP_USING_IRRX_HW
+///硬件IR receiver参数
+#define IR32KSEL_EN         0                     //IR clock source select 32K
+#if IR32KSEL_EN
+    #define RPTERR_CNT      33                    //配置11.25ms ± (RPTERR_CNT + 1)*32K的repeat code允许范围
+    #define DATERR_CNT      33                    //配置13.5ms ± (DATERR_CNT + 1)*32K引导码允许范围
+    #define ONEERR_CNT      7                     //配置2.25ms ± (ONEERR_CNT + 1)*32K的logic "1"允许范围
+    #define ZEROERR_CNT     3                     //配置1.12ms ± (ONEERR_CNT + 1)*32K数logic "0"允许范围
+    #define TOPR_CNT        55                    //IR time out length = (TOPR + 1) * 64 *32K
+#else
+    #define RPTERR_CNT      1000                  //配置11.25ms ± (RPTERR_CNT + 1)us的repeat code允许范围
+    #define DATERR_CNT      1000                  //配置13.5ms ± (DATERR_CNT + 1)us引导码允许范围
+    #define ONEERR_CNT      250                   //配置2.25ms ± (ONEERR_CNT + 1)us的logic "1"允许范围
+    #define ZEROERR_CNT     125                   //配置1.12ms ± (ONEERR_CNT + 1)us数logic "0"允许范围
+    #define TOPR_CNT        1718                  //IR time out length = (TOPR + 1) * 64 us
+#endif // IR32KSEL_EN
+#endif // BSP_USING_IRRX_HW
+
+#define NO_KEY      (0u)
+
+struct ab32_irrx_data{
+    uint16_t cnt;                            //ir data bit counter
+    uint16_t rpt_cnt;                        //ir repeat counter
+    uint16_t addr;                           //address,  inverted address   Extended NEC: 16bits address
+    uint16_t cmd;                            //command,  inverted command
+};
+typedef struct ab32_irrx_data *ab32_irrx_data_t;
+
+static struct ab32_irrx_data _irrx = {0};
+
+/**
+ * @brief A non-zero value is returned
+ *        when IR key is detectedto be pressed.
+ *
+ * @param addr inverted address   Extended NEC: 16bits address
+ * @param cmd  inverted command
+ */
+RT_SECTION(".irq.irrx")
+uint8_t ab32_get_irkey(uint16_t *addr, uint16_t *cmd)
+{
+    if (_irrx.cnt != 32) {
+        return NO_KEY;
+    }
+    if (addr != RT_NULL) {
+        *addr = _irrx.addr;
+    }
+    if (cmd != RT_NULL) {
+        *cmd = _irrx.cmd;
+    }
+    return !NO_KEY;
+}
+
+/**
+ * @brief Invalid the current IR key.
+ *
+ */
+void ab32_clr_irkey(void)
+{
+    _irrx.cnt = 0;
+}
+
+#ifdef BSP_USING_IRRX_HW
+RT_SECTION(".irq.irrx")
+static void irrx_isr(int vector, void *param)
+{
+    rt_interrupt_enter();
+
+    //IR RX data finish interrupt
+    if (IRRXCON & BIT(16)) {
+        IRRXCPND = BIT(16);
+        _irrx.addr = (uint16_t)IRRXDAT;
+        _irrx.cmd = (uint16_t)(IRRXDAT >> 16);
+        _irrx.cnt = 32;
+    }
+
+    //IR key release interrupt
+    if (IRRXCON & BIT(17)) {
+        IRRXCPND = BIT(17);
+        _irrx.cnt = 0;
+    }
+
+    rt_interrupt_leave();
+}
+
+static void _irrx_hw_init(void)
+{
+    GPIOEDE |= BIT(6);
+    GPIOEPU |= BIT(6);
+    GPIOEDIR |= BIT(6);
+    FUNCMCON2 |= 0xf << 20;
+    FUNCMCON2 |= (7 << 20);                         //IR mapping to G6
+    rt_memset(&_irrx, 0, sizeof(_irrx));
+
+    IRRXERR0 = (RPTERR_CNT << 16) | DATERR_CNT;     //RPTERR[27:16], DATERR[11:0]
+    IRRXERR1 = (TOPR_CNT << 20) | (ONEERR_CNT << 10) | ZEROERR_CNT;    //TOPR[31:20], ONEERR[19:10], ZEROERR[9:0]
+
+#if IR32KSEL_EN
+    CLKCON1 &= ~BIT(5);
+    CLKCON1 |= BIT(4);                              //enable 26M分频32K
+    IRRXCON |= BIT(3);                              //ir clock source select 32K
+#endif // IR32KSEL_EN
+
+    rt_hw_interrupt_install(IRQ_IRRX_VECTOR, irrx_isr, RT_NULL, "irrx_isr");
+    IRRXCON = 0x03;
+
+    // LOG_D("IRRXCON:%08x", IRRXCON);
+}
+#endif
+
+#ifdef BSP_USING_IRRX_SW
+
+#define TMR3_RCLK               (1000u)            //xosc26m_div 1M
+
+RT_SECTION(".irq.irrx")
+static void irrx_isr(int vector, void *param)
+{
+    rt_uint32_t tmrcnt;
+
+    if (TMR3CON & BIT(17)) {
+        //timer1 capture interrupt
+        TMR3CNT  = TMR3CNT - TMR3CPT;
+        tmrcnt = TMR3CPT;
+        TMR3CPND = BIT(17);
+        tmrcnt /= TMR3_RCLK;                //convert to ms
+    } else if (TMR3CON & BIT(16)){
+        //timer1 overflow interrupt
+        TMR3CPND = BIT(16);
+        tmrcnt = 110;                   //110ms overflow
+    } else {
+        return;
+    }
+
+    //processing repeat code
+    if (_irrx.cnt == 32) {
+        if ((tmrcnt >= 10) && (tmrcnt <= 12)) {
+            //repeat code is simply 9ms+2.25ms
+            _irrx.rpt_cnt = 0;
+        } else {
+            _irrx.rpt_cnt += tmrcnt;
+            if (_irrx.rpt_cnt > 108) {
+                _irrx.rpt_cnt = 0;
+                _irrx.cnt = 0;          //ir key release
+            }
+        }
+        return;
+    } else if ((tmrcnt > 7) || (tmrcnt == 0)) {     //A message is started by a 9ms AGC burst
+        _irrx.rpt_cnt = 0;
+        _irrx.cnt = 0;                  //ir key message started
+        return;
+    }
+
+    _irrx.cmd >>= 1;
+    _irrx.cnt++;
+    if (tmrcnt == 2) {                  //Bit time of 1.125ms(0) or 2.25ms(1)
+        _irrx.cmd |= 0x8000;
+    }
+
+    if (_irrx.cnt == 16) {
+        _irrx.addr = _irrx.cmd;         //save address data
+    } else if (_irrx.cnt == 32) {
+        //got ir key message
+        if ((rt_uint8_t)_irrx.cmd > 96) {
+            _irrx.cmd = NO_KEY;
+        }
+    }
+}
+
+static void timer3_init(void)
+{
+    rt_hw_interrupt_install(IRQ_IRRX_VECTOR, irrx_isr, RT_NULL, "irrx_isr");
+    TMR3CNT  = 0;
+    TMR3PR   = TMR3_RCLK*110 - 1;                                //110ms Timer overflow interrupt
+    TMR3CON  = BIT(8) | BIT(7) | BIT(5) | BIT(2) | BIT(1) | BIT(0);   //capture & overflow interrupt enable, falling edge, Capture Mode
+}
+
+static void _irrx_hw_init(void)
+{
+    GPIOEDE |= BIT(6);
+    GPIOEPU |= BIT(6);
+    GPIOEDIR |= BIT(6);
+    FUNCMCON2 |= 0xf << 4;
+    FUNCMCON2 |= (7 << 4);                              // timer3 G6 PE6 capture
+    rt_memset(&_irrx, 0, sizeof(_irrx));
+
+    timer3_init();
+}
+#endif
+
+static int ab32_irrx_init(void)
+{
+    _irrx_hw_init();
+    LOG_D("irrx init success");
+    return RT_EOK;
+}
+INIT_BOARD_EXPORT(ab32_irrx_init);
+
+#endif

+ 21 - 5
bsp/simulator/drivers/drv_rtc.c

@@ -48,7 +48,7 @@ static void soft_rtc_alarm_update(struct rt_rtc_wkalarm *palarm)
 static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
 {
     __time32_t *t;
-    struct tm *newtime;
+    struct tm newtime;
 
     RT_ASSERT(dev != RT_NULL);
 
@@ -57,10 +57,16 @@ static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
     case RT_DEVICE_CTRL_RTC_GET_TIME:
     {
         t = (__time32_t *)args;
-        _time32(t);
-        /* TODO The libc time module not support timezone now. So get the time from locatime. */
-        newtime = _localtime32(t);
-        *t = _mkgmtime32(newtime);
+        SYSTEMTIME sys_time;
+
+        GetSystemTime(&sys_time);
+        newtime.tm_year = sys_time.wYear - 1900;
+        newtime.tm_mon = sys_time.wMonth - 1;
+        newtime.tm_mday = sys_time.wDay;
+        newtime.tm_hour = sys_time.wHour;
+        newtime.tm_min = sys_time.wMinute;
+        newtime.tm_sec = sys_time.wSecond;
+        *t = timegm(&newtime);
         break;
     }
     case RT_DEVICE_CTRL_RTC_SET_TIME:
@@ -79,6 +85,16 @@ static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
         soft_rtc_alarm_update(&wkalarm);
         break;
 #endif
+    case RT_DEVICE_CTRL_RTC_GET_TIME_US:
+    {
+        long *tv_usec = (long *)args;
+        SYSTEMTIME sys_time;
+        GetSystemTime(&sys_time);
+        *tv_usec = sys_time.wMilliseconds * 1000UL;
+        break;
+    }
+    default:
+        return -RT_ERROR;
     }
 
     return RT_EOK;

+ 58 - 32
components/libc/compilers/common/time.c

@@ -120,7 +120,7 @@ struct tm* localtime_r(const time_t* t, struct tm* r)
     time_t local_tz;
     int utc_plus;
 
-    utc_plus = 0; /* GTM: UTC+0 */
+    utc_plus = 8; /* GMT: UTC+8 */
     local_tz = *t + utc_plus * 3600;
     return gmtime_r(&local_tz, r);
 }
@@ -183,18 +183,16 @@ char* ctime(const time_t *tim_p)
 }
 RTM_EXPORT(ctime);
 
-/**
- * Returns the current time.
- *
- * @param time_t * t the timestamp pointer, if not used, keep NULL.
- *
- * @return The value ((time_t)-1) is returned if the calendar time is not available.
- *         If timer is not a NULL pointer, the return value is also stored in timer.
- *
- */
-RT_WEAK time_t time(time_t *t)
+/*-1 failure; 1 success*/
+static int get_timeval(struct timeval *tv)
 {
-    time_t time_now = ((time_t)-1); /* default is not available */
+    if (tv == RT_NULL)
+        return -1;
+
+    /* default is not available */
+    tv->tv_sec = -1;
+    /* default is 0 */
+    tv->tv_usec = 0;
 
 #ifdef RT_USING_RTC
     static rt_device_t device = RT_NULL;
@@ -210,26 +208,50 @@ RT_WEAK time_t time(time_t *t)
     {
         if (rt_device_open(device, 0) == RT_EOK)
         {
-            rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time_now);
+            rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &tv->tv_sec);
+            rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME_US, &tv->tv_usec);
             rt_device_close(device);
         }
     }
 #endif /* RT_USING_RTC */
 
-    /* if t is not NULL, write timestamp to *t */
-    if (t != RT_NULL)
-    {
-        *t = time_now;
-    }
-
-    if(time_now == (time_t)-1)
+    if (tv->tv_sec == (time_t) -1)
     {
         /* LOG_W will cause a recursive printing if ulog timestamp function is turned on */
         rt_kprintf("Cannot find a RTC device to provide time!\r\n");
-        errno = ENOSYS;
+        tv->tv_sec = 0;
+        return -1;
     }
 
-    return time_now;
+    return 1;
+}
+
+/**
+ * Returns the current time.
+ *
+ * @param time_t * t the timestamp pointer, if not used, keep NULL.
+ *
+ * @return The value ((time_t)-1) is returned if the calendar time is not available.
+ *         If timer is not a NULL pointer, the return value is also stored in timer.
+ *
+ */
+RT_WEAK time_t time(time_t *t)
+{
+    struct timeval now;
+
+    if(get_timeval(&now)>0)
+    {
+        if (t)
+        {
+            *t = now.tv_sec;
+        }
+        return now.tv_sec;
+    }
+    else
+    {
+        errno = EFAULT;
+        return -1;
+    }
 }
 RTM_EXPORT(time);
 
@@ -254,13 +276,13 @@ int stime(const time_t *t)
     else
     {
         LOG_W("Cannot find a RTC device to provide time!");
-        errno = ENOSYS;
+        errno = EFAULT;
         return -1;
     }
     return 0;
 #else
     LOG_W("Cannot find a RTC device to provide time!");
-    errno = ENOSYS;
+    errno = EFAULT;
     return -1;
 #endif /* RT_USING_RTC */
 }
@@ -344,17 +366,13 @@ RTM_EXPORT(timegm);
 /* TODO: timezone */
 int gettimeofday(struct timeval *tv, struct timezone *tz)
 {
-    time_t t = time(RT_NULL);
-
-    if (tv != RT_NULL && t != (time_t)-1)
+    if (tv != RT_NULL && get_timeval(tv)>0)
     {
-        tv->tv_sec = t;
-        tv->tv_usec = 0;
         return 0;
     }
     else
     {
-        errno = ENOSYS;
+        errno = EFAULT;
         return -1;
     }
 }
@@ -365,11 +383,19 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz)
 {
     if (tv != RT_NULL)
     {
-        return stime((const time_t *)&tv->tv_sec);
+        if(tv->tv_sec >= 0 && tv->tv_usec >= 0)
+        {
+            return stime((const time_t *)&tv->tv_sec);
+        }
+        else
+        {
+            errno = EINVAL;
+            return -1;
+        }
     }
     else
     {
-        errno = ENOSYS;
+        errno = EFAULT;
         return -1;
     }
 }

+ 4 - 2
include/rtdef.h

@@ -962,10 +962,12 @@ enum rt_device_class_type
 #define RT_DEVICE_CTRL_BLK_AUTOREFRESH  0x13            /**< block device : enter/exit auto refresh mode */
 #define RT_DEVICE_CTRL_NETIF_GETMAC     0x10            /**< get mac address */
 #define RT_DEVICE_CTRL_MTD_FORMAT       0x10            /**< format a MTD device */
-#define RT_DEVICE_CTRL_RTC_GET_TIME     0x10            /**< get time */
-#define RT_DEVICE_CTRL_RTC_SET_TIME     0x11            /**< set time */
+#define RT_DEVICE_CTRL_RTC_GET_TIME     0x10            /**< get second time */
+#define RT_DEVICE_CTRL_RTC_SET_TIME     0x11            /**< set second time */
 #define RT_DEVICE_CTRL_RTC_GET_ALARM    0x12            /**< get alarm */
 #define RT_DEVICE_CTRL_RTC_SET_ALARM    0x13            /**< set alarm */
+#define RT_DEVICE_CTRL_RTC_GET_TIME_US  0x14            /**< get microsecond time */
+#define RT_DEVICE_CTRL_RTC_SET_TIME_US  0x15            /**< set microsecond time */
 
 typedef struct rt_device *rt_device_t;