diff options
| author | Bernard Xiong <[email protected]> | 2018-11-20 23:13:45 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2018-11-20 23:13:45 +0800 |
| commit | 46dae3f35f5cc44664a26ebd87803156033a166a (patch) | |
| tree | 47f132d0a7472768deabd2add67d990c0c6e64e7 /components/drivers | |
| parent | b31888de49408b212d2aeab4b40b2a672b958313 (diff) | |
| parent | 6b6d122e3673ca64d2171d3daf1ae940edfa699a (diff) | |
Merge branch 'master' into dev-4.0.x
Diffstat (limited to 'components/drivers')
22 files changed, 1100 insertions, 28 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index f70ed4961f..94af352410 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -72,6 +72,10 @@ config RT_USING_PIN bool "Using generic GPIO device drivers" default y +config RT_USING_ADC + bool "Using ADC device drivers" + default n + config RT_USING_PWM bool "Using PWM device drivers" default n @@ -104,6 +108,10 @@ config RT_USING_MTD default n endif +config RT_USING_PM + bool "Using Power Management device drivers" + default n + config RT_USING_RTC bool "Using RTC device drivers" default n @@ -114,9 +122,8 @@ config RT_USING_RTC default n config RTC_SYNC_USING_NTP bool "Using NTP auto sync RTC time" - select PKG_USING_NETUTILS - select PKG_NETUTILS_NTP - default n + depends on PKG_NETUTILS_NTP + default y if RTC_SYNC_USING_NTP config RTC_NTP_FIRST_SYNC_DELAY @@ -392,6 +399,23 @@ menu "Using USB" bool "Enable to use device as winusb device" default n endif + if RT_USB_DEVICE_CDC + config RT_VCOM_TASK_STK_SIZE + int "virtual com thread stack size" + default 512 + config RT_VCOM_TX_USE_DMA + bool "Enable to use dma for vcom tx" + default n + config RT_VCOM_SERNO + string "serial number of virtual com" + default "32021919830108" + config RT_VCOM_SER_LEN + int "serial number length of virtual com" + default 14 + config RT_VCOM_TX_TIMEOUT + int "tx timeout(ticks) of virtual com" + default 1000 + endif if RT_USB_DEVICE_WINUSB config RT_WINUSB_GUID string "Guid for winusb" diff --git a/components/drivers/include/drivers/adc.h b/components/drivers/include/drivers/adc.h new file mode 100644 index 0000000000..8e3498e791 --- /dev/null +++ b/components/drivers/include/drivers/adc.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-07 aozima the first version + * 2018-11-16 Ernest Chen add finsh command and update adc function + */ + +#ifndef __ADC_H__ +#define __ADC_H__ +#include <rtthread.h> + +struct rt_adc_device; +struct rt_adc_ops +{ + rt_err_t (*enabled)(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); + rt_err_t (*convert)(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value); +}; + +struct rt_adc_device +{ + struct rt_device parent; + const struct rt_adc_ops *ops; +}; +typedef struct rt_adc_device *rt_adc_device_t; + +typedef enum +{ + RT_ADC_CMD_ENABLE, + RT_ADC_CMD_DISABLE, +} rt_adc_cmd_t; + +rt_err_t rt_hw_adc_register(rt_adc_device_t adc,const char *name, const struct rt_adc_ops *ops, const void *user_data); + +rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel); +rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel); +rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel); + +#endif /* __ADC_H__ */ diff --git a/components/drivers/include/drivers/pm.h b/components/drivers/include/drivers/pm.h new file mode 100644 index 0000000000..94d4c8559b --- /dev/null +++ b/components/drivers/include/drivers/pm.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-06-02 Bernard the first version + * 2018-08-02 Tanek split run and sleep modes, support custom mode + */ + +#ifndef __PM_H__ +#define __PM_H__ + +#include <rtthread.h> + +#ifndef PM_HAS_CUSTOM_CONFIG + +/* All modes used for rt_pm_request() adn rt_pm_release() */ +enum +{ + /* run modes */ + PM_RUN_MODE_NORMAL = 0, + + /* sleep modes */ + PM_SLEEP_MODE_SLEEP, + PM_SLEEP_MODE_TIMER, + PM_SLEEP_MODE_SHUTDOWN, +}; + +/* The name of all modes used in the msh command "pm_dump" */ +#define PM_MODE_NAMES \ +{ \ + "Running Mode", \ + \ + "Sleep Mode", \ + "Timer Mode", \ + "Shutdown Mode", \ +} + +/* run mode count : 1 */ +#define PM_RUN_MODE_COUNT 1 +/* sleep mode count : 3 */ +#define PM_SLEEP_MODE_COUNT 3 + +/* support redefining default run mode */ +#ifndef PM_RUN_MODE_DEFAULT +#define PM_RUN_MODE_DEFAULT 0 +#endif + +/* support redefining default sleep mode */ +#ifndef PM_SLEEP_MODE_DEFAULT +#define PM_SLEEP_MODE_DEFAULT (PM_SLEEP_MODE_START) +#endif + +/* support redefining the minimum tick into sleep mode */ +#ifndef PM_MIN_ENTER_SLEEP_TICK +#define PM_MIN_ENTER_SLEEP_TICK (1) +#endif + +#else /* PM_HAS_CUSTOM_CONFIG */ + +#include <pm_cfg.h> + +#ifndef PM_RUN_MODE_COUNT +#error "You must defined PM_RUN_MODE_COUNT on pm_cfg.h" +#endif + +#ifndef PM_SLEEP_MODE_COUNT +#error "You must defined PM_SLEEP_MODE_COUNT on pm_cfg.h" +#endif + +#ifndef PM_MODE_DEFAULT +#error "You must defined PM_MODE_DEFAULT on pm_cfg.h" +#endif + +#ifndef PM_MODE_NAMES +#error "You must defined PM_MODE_NAMES on pm_cfg.h" +#endif + +#ifndef PM_RUN_MODE_DEFAULT +#error "You must defined PM_RUN_MODE_DEFAULT on pm_cfg.h" +#endif + +/* The default sleep mode(PM_SLEEP_MODE_DEFAULT) are not required. + * If the default mode is defined, it is requested once in rt_system_pm_init() + */ + +#endif /* PM_HAS_CUSTOM_CONFIG */ + +/* run mode must start at 0 */ +#define PM_RUN_MODE_START 0 +/* the values of the run modes and sleep mode must be consecutive */ +#define PM_SLEEP_MODE_START PM_RUN_MODE_COUNT +/* all mode count */ +#define PM_MODE_COUNT (PM_RUN_MODE_COUNT + PM_SLEEP_MODE_COUNT) +/* The last mode, will be request in rt_system_pm_init() */ +#define PM_MODE_MAX (PM_RUN_MODE_COUNT + PM_SLEEP_MODE_COUNT - 1) + +#if PM_MODE_COUNT > 32 +#error "The number of modes cannot exceed 32" +#endif + +/** + * device control flag to request or release power + */ +#define RT_PM_DEVICE_CTRL_REQUEST 0x01 +#define RT_PM_DEVICE_CTRL_RELEASE 0x02 + +struct rt_pm; + +/** + * low power mode operations + */ +struct rt_pm_ops +{ + void (*enter)(struct rt_pm *pm); + void (*exit)(struct rt_pm *pm); + +#if PM_RUN_MODE_COUNT > 1 + void (*frequency_change)(struct rt_pm *pm, rt_uint32_t frequency); +#endif + + void (*timer_start)(struct rt_pm *pm, rt_uint32_t timeout); + void (*timer_stop)(struct rt_pm *pm); + rt_tick_t (*timer_get_tick)(struct rt_pm *pm); +}; + +struct rt_device_pm_ops +{ +#if PM_RUN_MODE_COUNT > 1 + void (*frequency_change)(const struct rt_device* device); +#endif + + void (*suspend)(const struct rt_device* device); + void (*resume) (const struct rt_device* device); +}; + +struct rt_device_pm +{ + const struct rt_device* device; + const struct rt_device_pm_ops* ops; +}; + +/** + * power management + */ +struct rt_pm +{ + struct rt_device parent; + + /* modes */ + rt_uint8_t modes[PM_MODE_COUNT]; + rt_uint8_t current_mode; /* current pm mode */ + rt_uint8_t exit_count; + + /* the list of device, which has PM feature */ + rt_uint8_t device_pm_number; + struct rt_device_pm* device_pm; + struct rt_semaphore device_lock; + + /* if the mode has timer, the corresponding bit is 1*/ + rt_uint32_t timer_mask; + + const struct rt_pm_ops *ops; +}; + +void rt_pm_enter(void); +void rt_pm_exit(void); + +void rt_pm_request(rt_ubase_t mode); +void rt_pm_release(rt_ubase_t mode); + +void rt_pm_register_device(struct rt_device* device, const struct rt_device_pm_ops* ops); +void rt_pm_unregister_device(struct rt_device* device); + +void rt_system_pm_init(const struct rt_pm_ops *ops, + rt_uint8_t timer_mask, + void *user_data); + +#endif /* __PM_H__ */ diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h index 764dcd5612..c26d83391e 100644 --- a/components/drivers/include/drivers/usb_common.h +++ b/components/drivers/include/drivers/usb_common.h @@ -225,7 +225,7 @@ extern "C" { #ifndef USB_TIMEOUT_LONG #define USB_TIMEOUT_LONG (RT_TICK_PER_SECOND * 5) /* 5s */ #endif -#ifndf USB_DEBOUNCE_TIME +#ifndef USB_DEBOUNCE_TIME #define USB_DEBOUNCE_TIME (RT_TICK_PER_SECOND / 5) /* 0.2s */ #endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index e0499dcd20..d59b40cc47 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -99,10 +99,18 @@ extern "C" { #include "drivers/cputime.h" #endif +#ifdef RT_USING_ADC +#include "drivers/adc.h" +#endif + #ifdef RT_USING_PWM #include "drivers/rt_drv_pwm.h" #endif +#ifdef RT_USING_PM +#include "drivers/pm.h" +#endif + #ifdef RT_USING_WIFI #include "drivers/wlan.h" #endif diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript index 4cc5f80084..c45ba524c5 100644 --- a/components/drivers/misc/SConscript +++ b/components/drivers/misc/SConscript @@ -7,7 +7,10 @@ group = [] if GetDepend(['RT_USING_PIN']): src = src + ['pin.c'] - + +if GetDepend(['RT_USING_ADC']): + src = src + ['adc.c'] + if GetDepend(['RT_USING_PWM']): src = src + ['rt_drv_pwm.c'] diff --git a/components/drivers/misc/adc.c b/components/drivers/misc/adc.c new file mode 100644 index 0000000000..aa3a3b7801 --- /dev/null +++ b/components/drivers/misc/adc.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-07 aozima the first version + * 2018-11-16 Ernest Chen add finsh command and update adc function + */ + +#include <rtthread.h> +#include <rtdevice.h> + +#include <string.h> +#include <stdlib.h> + +#define DBG_ENABLE +#define DBG_SECTION_NAME "adc" +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include <rtdbg.h> + +static rt_size_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_err_t result = RT_EOK; + rt_size_t i; + struct rt_adc_device *adc = (struct rt_adc_device *)dev; + rt_uint32_t *value = (rt_uint32_t *)buffer; + + for (i = 0; i < size; i += sizeof(int)) + { + result = adc->ops->convert(adc, pos + i, value); + if (result != RT_EOK) + { + return 0; + } + value++; + } + + return i; +} + +static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t result = RT_EOK; + rt_adc_device_t adc = (struct rt_adc_device *)dev; + + if (adc->ops->enabled != RT_NULL) + { + return -RT_ENOSYS; + } + if (cmd == RT_ADC_CMD_ENABLE) + { + result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_TRUE); + } + else if (cmd == RT_ADC_CMD_DISABLE) + { + result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_FALSE); + } + + return result; +} + +rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data) +{ + rt_err_t result = RT_EOK; + RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL); + + device->parent.type = RT_Device_Class_Miscellaneous; + device->parent.init = RT_NULL; + device->parent.open = RT_NULL; + device->parent.close = RT_NULL; + device->parent.read = _adc_read; + device->parent.write = RT_NULL; + device->parent.control = _adc_control; + + device->ops = ops; + device->parent.user_data = (void *)user_data; + + result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + + return result; +} + +rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel) +{ + rt_uint32_t value; + + RT_ASSERT(dev); + + dev->ops->convert(dev, channel, &value); + + return value; +} + +rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel) +{ + rt_err_t result = RT_EOK; + + RT_ASSERT(dev); + if (dev->ops->enabled != RT_NULL) + { + result = dev->ops->enabled(dev, channel, RT_TRUE); + } + else + { + result = -RT_ENOSYS; + } + + return result; +} + +rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel) +{ + rt_err_t result = RT_EOK; + + RT_ASSERT(dev); + if (dev->ops->enabled != RT_NULL) + { + result = dev->ops->enabled(dev, channel, RT_FALSE); + } + else + { + result = -RT_ENOSYS; + } + + return result; +} + +#ifdef FINSH_USING_MSH + +static int adc(int argc, char **argv) +{ + int value = 0; + int result = RT_EOK; + static rt_adc_device_t adc_device = RT_NULL; + char *result_str; + + if (argc > 1) + { + if (!strcmp(argv[1], "probe")) + { + if (argc == 3) + { + adc_device = (rt_adc_device_t)rt_device_find(argv[2]); + result_str = (adc_device == RT_NULL) ? "failure" : "success"; + rt_kprintf("probe %s %s \n", argv[2], result_str); + } + else + { + rt_kprintf("adc probe <adc_name> - probe adc by name\n"); + } + } + else + { + if (adc_device == RT_NULL) + { + rt_kprintf("Please using 'adc probe <adc_name>' first\n"); + return -RT_ERROR; + } + if (!strcmp(argv[1], "enable")) + { + if (argc == 3) + { + result = rt_adc_enable(adc_device, atoi(argv[2])); + result_str = (result == RT_EOK) ? "success" : "failure"; + rt_kprintf("%s channel %d enables %s \n", adc_device->parent.parent.name, atoi(argv[2]), result_str); + } + else + { + rt_kprintf("adc enable <channel> - enable adc channel\n"); + } + } + else if (!strcmp(argv[1], "read")) + { + if (argc == 3) + { + value = rt_adc_read(adc_device, atoi(argv[2])); + rt_kprintf("%s channel %d read value is 0x%08X \n", adc_device->parent.parent.name, atoi(argv[2]), value); + } + else + { + rt_kprintf("adc read <channel> - read adc value on the channel\n"); + } + } + else if (!strcmp(argv[1], "disable")) + { + if (argc == 3) + { + result = rt_adc_disable(adc_device, atoi(argv[2])); + result_str = (result == RT_EOK) ? "success" : "failure"; + rt_kprintf("%s channel %d disable %s \n", adc_device->parent.parent.name, atoi(argv[2]), result_str); + } + else + { + rt_kprintf("adc disable <channel> - disable adc channel\n"); + } + } + else + { + rt_kprintf("Unknown command. Please enter 'adc' for help\n"); + } + } + } + else + { + rt_kprintf("Usage: \n"); + rt_kprintf("adc probe <adc_name> - probe adc by name\n"); + rt_kprintf("adc read <channel> - read adc value on the channel\n"); + rt_kprintf("adc disable <channel> - disable adc channel\n"); + rt_kprintf("adc enable <channel> - enable adc channel\n"); + result = -RT_ERROR; + } + return RT_EOK; +} +MSH_CMD_EXPORT(adc, adc function); + +#endif /* FINSH_USING_MSH */ diff --git a/components/drivers/pm/SConscript b/components/drivers/pm/SConscript new file mode 100644 index 0000000000..a94fc11f57 --- /dev/null +++ b/components/drivers/pm/SConscript @@ -0,0 +1,14 @@ +from building import * + +cwd = GetCurrentDir() +src = [] +CPPPATH = [cwd + '/../include'] +group = [] + +if GetDepend(['RT_USING_PM']): + src = src + ['pm.c'] + +if len(src): + group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c new file mode 100644 index 0000000000..655c4b4c02 --- /dev/null +++ b/components/drivers/pm/pm.c @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-06-02 Bernard the first version + * 2018-08-02 Tanek split run and sleep modes, support custom mode + */ + +#include <rthw.h> +#include <rtthread.h> +#include <drivers/pm.h> + +#ifdef RT_USING_PM + +static struct rt_pm _pm; + +/** + * This function will suspend all registered devices + */ +static void _pm_device_suspend(void) +{ + int index; + + for (index = 0; index < _pm.device_pm_number; index++) + { + if (_pm.device_pm[index].ops->suspend != RT_NULL) + { + _pm.device_pm[index].ops->suspend(_pm.device_pm[index].device); + } + } +} + +/** + * This function will resume all registered devices + */ +static void _pm_device_resume(void) +{ + int index; + + for (index = 0; index < _pm.device_pm_number; index++) + { + if (_pm.device_pm[index].ops->resume != RT_NULL) + { + _pm.device_pm[index].ops->resume(_pm.device_pm[index].device); + } + } +} + +#if PM_RUN_MODE_COUNT > 1 +/** + * This function will update the frequency of all registered devices + */ +static void _pm_device_frequency_change(void) +{ + rt_uint32_t index; + + /* make the frequency change */ + for (index = 0; index < _pm.device_pm_number; index ++) + { + if (_pm.device_pm[index].ops->frequency_change != RT_NULL) + _pm.device_pm[index].ops->frequency_change(_pm.device_pm[index].device); + } +} +#endif + +/** + * This function will enter corresponding power mode. + */ +void rt_pm_enter(void) +{ + rt_ubase_t level; + struct rt_pm *pm; + rt_uint32_t index; + rt_tick_t timeout_tick; + + pm = &_pm; + + /* disable interrupt before check run modes */ + level = rt_hw_interrupt_disable(); + /* check each run mode, and decide to swithc to run mode or sleep mode */ + for (index = 0; index < PM_RUN_MODE_COUNT; index++) + { + if (pm->modes[index]) + { + if (index > pm->current_mode) + { + pm->ops->exit(pm); + pm->current_mode = index; + pm->ops->enter(pm); +#if PM_RUN_MODE_COUNT > 1 + pm->ops->frequency_change(pm, 0); + _pm_device_frequency_change(); +#endif + } + + rt_hw_interrupt_enable(level); + /* The current mode is run mode, no need to check sleep mode */ + return ; + } + } + /* enable interrupt after check run modes */ + rt_hw_interrupt_enable(level); + + level = rt_hw_interrupt_disable(); + /* check each sleep mode to decide which mode can system sleep. */ + for (index = PM_SLEEP_MODE_START; index < PM_SLEEP_MODE_START + PM_SLEEP_MODE_COUNT; index++) + { + if (pm->modes[index]) + { + /* let mcu sleep when system is idle */ + + /* run mode to sleep mode */ + if (pm->current_mode < PM_SLEEP_MODE_START) + { + /* exit run mode */ + pm->ops->exit(pm); + } + + /* set current power mode */ + pm->current_mode = index; + pm->exit_count = 1; + + /* suspend all of devices with PM feature */ + _pm_device_suspend(); + + /* should start pm timer */ + if (pm->timer_mask & (1 << index)) + { + /* get next os tick */ + timeout_tick = rt_timer_next_timeout_tick(); + if (timeout_tick != RT_TICK_MAX) + { + timeout_tick -= rt_tick_get(); + +#if defined(PM_MIN_ENTER_SLEEP_TICK) && PM_MIN_ENTER_SLEEP_TICK > 0 + if (timeout_tick < PM_MIN_ENTER_SLEEP_TICK) + { + rt_hw_interrupt_enable(level); + /* limit the minimum time to enter timer sleep mode */ + return ; + } +#endif + } + /* startup pm timer */ + pm->ops->timer_start(pm, timeout_tick); + } + + /* enter sleep and wait to be waken up */ + pm->ops->enter(pm); + + rt_hw_interrupt_enable(level); + + /* exit from low power mode */ + rt_pm_exit(); + + return ; + } + } + + rt_hw_interrupt_enable(level); +} + +/** + * This function exits from sleep mode. + */ +void rt_pm_exit(void) +{ + rt_ubase_t level; + struct rt_pm *pm; + rt_tick_t delta_tick; + + pm = &_pm; + + level = rt_hw_interrupt_disable(); + + if (pm->exit_count) + { + pm->exit_count = 0; + + if (pm->current_mode >= PM_SLEEP_MODE_START) + { + /* sleep mode with timer */ + if (pm->timer_mask & (1 << pm->current_mode)) + { + /* get the tick of pm timer */ + delta_tick = pm->ops->timer_get_tick(pm); + + /* stop pm timer */ + pm->ops->timer_stop(pm); + + if (delta_tick) + { + /* adjust OS tick */ + rt_tick_set(rt_tick_get() + delta_tick); + /* check system timer */ + rt_timer_check(); + } + } + + /* exit from sleep mode */ + pm->ops->exit(pm); + /* resume the device with PM feature */ + _pm_device_resume(); + } + } + + rt_hw_interrupt_enable(level); +} + +/** + * Upper application or device driver requests the system + * stall in corresponding power mode. + * + * @param parameter the parameter of run mode or sleep mode + */ +void rt_pm_request(rt_ubase_t mode) +{ + rt_ubase_t level; + struct rt_pm *pm; + + pm = &_pm; + + if (mode > PM_MODE_MAX) + return; + + level = rt_hw_interrupt_disable(); + + /* update pm modes table */ + pm->modes[mode] ++; + + /* request higter mode with a smaller mode value*/ + if (mode < pm->current_mode) + { + /* the old current mode is RUN mode, need to all pm->ops->exit(), + * if not, it has already called in rt_pm_exit() + */ + if (pm->current_mode < PM_SLEEP_MODE_START) + { + pm->ops->exit(pm); + } + else if (pm->exit_count) + { + /* call exeit when global interrupt is disable */ + pm->ops->exit(pm); + pm->exit_count = 0; + } + + /* update current mode */ + pm->current_mode = mode; + + /* current mode is higher run mode */ + if (mode < PM_SLEEP_MODE_START) + { + /* enter run mode */ + pm->ops->enter(pm); +#if PM_RUN_MODE_COUNT > 1 + /* frequency change */ + pm->ops->frequency_change(pm, 0); + _pm_device_frequency_change(); +#endif + } + else + { + /* do nothing when request higher sleep mode, + * and swithc to new sleep mode in rt_pm_enter() + */ + } + } + + rt_hw_interrupt_enable(level); +} + +/** + * Upper application or device driver releases the stall + * of corresponding power mode. + * + * @param parameter the parameter of run mode or sleep mode + * + */ +void rt_pm_release(rt_ubase_t mode) +{ + rt_ubase_t level; + struct rt_pm *pm; + + pm = &_pm; + + if (mode > PM_MODE_MAX) + return; + + level = rt_hw_interrupt_disable(); + + if (pm->modes[mode] > 0) + pm->modes[mode] --; + + rt_hw_interrupt_enable(level); +} + +/** + * Register a device with PM feature + * + * @param device the device with PM feature + * @param ops the PM ops for device + */ +void rt_pm_register_device(struct rt_device *device, const struct rt_device_pm_ops *ops) +{ + rt_ubase_t level; + struct rt_device_pm *device_pm; + + RT_DEBUG_NOT_IN_INTERRUPT; + + level = rt_hw_interrupt_disable(); + + device_pm = (struct rt_device_pm *)RT_KERNEL_REALLOC(_pm.device_pm, + (_pm.device_pm_number + 1) * sizeof(struct rt_device_pm)); + if (device_pm != RT_NULL) + { + _pm.device_pm = device_pm; + _pm.device_pm[_pm.device_pm_number].device = device; + _pm.device_pm[_pm.device_pm_number].ops = ops; + _pm.device_pm_number += 1; + } + + rt_sem_release(&(_pm.device_lock)); + + rt_hw_interrupt_enable(level); +} + +/** + * Unregister device from PM manager. + * + * @param device the device with PM feature + */ +void rt_pm_unregister_device(struct rt_device *device) +{ + rt_ubase_t level; + rt_uint32_t index; + RT_DEBUG_NOT_IN_INTERRUPT; + + level = rt_hw_interrupt_disable(); + + for (index = 0; index < _pm.device_pm_number; index ++) + { + if (_pm.device_pm[index].device == device) + { + /* remove current entry */ + for (; index < _pm.device_pm_number - 1; index ++) + { + _pm.device_pm[index] = _pm.device_pm[index + 1]; + } + + _pm.device_pm[_pm.device_pm_number - 1].device = RT_NULL; + _pm.device_pm[_pm.device_pm_number - 1].ops = RT_NULL; + + _pm.device_pm_number -= 1; + /* break out and not touch memory */ + break; + } + } + + rt_hw_interrupt_enable(level); +} + +/** + * RT-Thread device interface for PM device + */ +static rt_size_t _rt_pm_device_read(rt_device_t dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_pm *pm; + rt_size_t length; + + length = 0; + pm = (struct rt_pm *)dev; + RT_ASSERT(pm != RT_NULL); + + if (pos <= PM_MODE_MAX) + { + int mode; + + mode = pm->modes[pos]; + length = rt_snprintf(buffer, size, "%d", mode); + } + + return length; +} + +static rt_size_t _rt_pm_device_write(rt_device_t dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + unsigned char request; + + if (size) + { + /* get request */ + request = *(unsigned char *)buffer; + if (request == '1') + { + rt_pm_request(pos); + } + else if (request == '0') + { + rt_pm_release(pos); + } + } + + return 1; +} + +static rt_err_t _rt_pm_device_control(rt_device_t dev, + int cmd, + void *args) +{ + rt_uint32_t mode; + + switch (cmd) + { + case RT_PM_DEVICE_CTRL_REQUEST: + mode = (rt_uint32_t)args; + rt_pm_request(mode); + break; + + case RT_PM_DEVICE_CTRL_RELEASE: + mode = (rt_uint32_t)args; + rt_pm_release(mode); + break; + } + + return RT_EOK; +} + +/** + * This function will initialize power management. + * + * @param ops the PM operations. + * @param timer_mask indicates which mode has timer feature. + * @param user_data user data + */ +void rt_system_pm_init(const struct rt_pm_ops *ops, + rt_uint8_t timer_mask, + void *user_data) +{ + struct rt_device *device; + struct rt_pm *pm; + + pm = &_pm; + device = &(_pm.parent); + + device->type = RT_Device_Class_PM; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + + device->init = RT_NULL; + device->open = RT_NULL; + device->close = RT_NULL; + device->read = _rt_pm_device_read; + device->write = _rt_pm_device_write; + device->control = _rt_pm_device_control; + device->user_data = user_data; + + /* register PM device to the system */ + rt_device_register(device, "pm", RT_DEVICE_FLAG_RDWR); + + /* todo : add to kernel source code */ + rt_thread_idle_sethook(rt_pm_enter); + + rt_memset(pm->modes, 0, sizeof(pm->modes)); + pm->current_mode = PM_RUN_MODE_DEFAULT; + + pm->timer_mask = timer_mask; + + pm->ops = ops; + + pm->device_pm = RT_NULL; + pm->device_pm_number = 0; + + /* initialize semaphore */ + rt_sem_init(&(pm->device_lock), "pm", 1, RT_IPC_FLAG_FIFO); + + /* request in default running mode */ + rt_pm_request(PM_RUN_MODE_DEFAULT); + +#ifdef PM_SLEEP_MODE_DEFAULT + /* request in default sleep mode */ + rt_pm_request(PM_SLEEP_MODE_DEFAULT); +#endif + + /* must hold on deep shutdown mode */ + rt_pm_request(PM_MODE_MAX); +} + +#ifdef RT_USING_FINSH +#include <finsh.h> + +static void rt_pm_release_mode(int argc, char **argv) +{ + int mode = 0; + if (argc >= 2) + { + mode = atoi(argv[1]); + } + + rt_pm_release(mode); +} +MSH_CMD_EXPORT_ALIAS(rt_pm_release_mode, pm_release, release power management mode); + +static void rt_pm_request_mode(int argc, char **argv) +{ + int mode = 0; + if (argc >= 2) + { + mode = atoi(argv[1]); + } + + rt_pm_request(mode); +} +MSH_CMD_EXPORT_ALIAS(rt_pm_request_mode, pm_request, request power management mode); + +static void rt_pm_dump_status(void) +{ + static const char *pm_str[] = PM_MODE_NAMES; + rt_uint32_t index; + struct rt_pm *pm; + + pm = &_pm; + + rt_kprintf("| Power Management Mode | Counter | Timer |\n"); + rt_kprintf("+-----------------------+---------+-------+\n"); + for (index = 0; index <= PM_MODE_MAX; index ++) + { + int has_timer = 0; + if (pm->timer_mask & (1 << index)) + has_timer = 1; + + rt_kprintf("| %021s | %7d | %5d |\n", pm_str[index], pm->modes[index], has_timer); + } + rt_kprintf("+-----------------------+---------+-------+\n"); + + rt_kprintf("pm current mode: %s\n", pm_str[pm->current_mode]); +} +FINSH_FUNCTION_EXPORT_ALIAS(rt_pm_dump_status, pm_dump, dump power management status); +MSH_CMD_EXPORT_ALIAS(rt_pm_dump_status, pm_dump, dump power management status); +#endif + +#endif /* RT_USING_PM */ diff --git a/components/drivers/sdio/block_dev.c b/components/drivers/sdio/block_dev.c index 9bef67d950..23be319fc6 100644 --- a/components/drivers/sdio/block_dev.c +++ b/components/drivers/sdio/block_dev.c @@ -14,7 +14,7 @@ #include <drivers/mmcsd_core.h> #define DBG_ENABLE -#define DBG_SECTION_NAME "[SDIO]" +#define DBG_SECTION_NAME "SDIO" #ifdef RT_SDIO_DEBUG #define DBG_LEVEL DBG_LOG #else diff --git a/components/drivers/sdio/mmc.c b/components/drivers/sdio/mmc.c index 7ad01e1153..bbf0ff838c 100644 --- a/components/drivers/sdio/mmc.c +++ b/components/drivers/sdio/mmc.c @@ -12,7 +12,7 @@ #include <drivers/mmc.h> #define DBG_ENABLE -#define DBG_SECTION_NAME "[SDIO]" +#define DBG_SECTION_NAME "SDIO" #ifdef RT_SDIO_DEBUG #define DBG_LEVEL DBG_LOG #else diff --git a/components/drivers/sdio/mmcsd_core.c b/components/drivers/sdio/mmcsd_core.c index 29a8ba239b..d1f5978374 100644 --- a/components/drivers/sdio/mmcsd_core.c +++ b/components/drivers/sdio/mmcsd_core.c @@ -15,7 +15,7 @@ #include <drivers/sdio.h> #define DBG_ENABLE -#define DBG_SECTION_NAME "[SDIO]" +#define DBG_SECTION_NAME "SDIO" #ifdef RT_SDIO_DEBUG #define DBG_LEVEL DBG_LOG #else diff --git a/components/drivers/sdio/sd.c b/components/drivers/sdio/sd.c index 338ecfa7c5..69a4561fb0 100644 --- a/components/drivers/sdio/sd.c +++ b/components/drivers/sdio/sd.c @@ -12,7 +12,7 @@ #include <drivers/sd.h> #define DBG_ENABLE -#define DBG_SECTION_NAME "[SDIO]" +#define DBG_SECTION_NAME "SDIO" #ifdef RT_SDIO_DEBUG #define DBG_LEVEL DBG_LOG #else diff --git a/components/drivers/sdio/sdio.c b/components/drivers/sdio/sdio.c index 7eeb312f6f..6045c4ade8 100644 --- a/components/drivers/sdio/sdio.c +++ b/components/drivers/sdio/sdio.c @@ -13,7 +13,7 @@ #include <drivers/sd.h> #define DBG_ENABLE -#define DBG_SECTION_NAME "[SDIO]" +#define DBG_SECTION_NAME "SDIO" #ifdef RT_SDIO_DEBUG #define DBG_LEVEL DBG_LOG #else diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 9cf9abf701..959d8444c1 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -70,19 +70,19 @@ static int serial_fops_open(struct dfs_fd *fd) switch (fd->flags & O_ACCMODE) { case O_RDONLY: - dbg_log(DBG_LOG, "fops open: O_RDONLY!\n"); + LOG_D("fops open: O_RDONLY!"); flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDONLY; break; case O_WRONLY: - dbg_log(DBG_LOG, "fops open: O_WRONLY!\n"); + LOG_D("fops open: O_WRONLY!"); flags = RT_DEVICE_FLAG_WRONLY; break; case O_RDWR: - dbg_log(DBG_LOG, "fops open: O_RDWR!\n"); + LOG_D("fops open: O_RDWR!"); flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDWR; break; default: - dbg_log(DBG_ERROR, "fops open: unknown mode - %d!\n", fd->flags & O_ACCMODE); + LOG_E("fops open: unknown mode - %d!", fd->flags & O_ACCMODE); break; } @@ -559,7 +559,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) RT_ASSERT(dev != RT_NULL); serial = (struct rt_serial_device *)dev; - dbg_log(DBG_LOG, "open serial device: 0x%08x with open flag: 0x%04x\n", + LOG_D("open serial device: 0x%08x with open flag: 0x%04x", dev, oflag); /* check device flag with the open flag */ if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX)) diff --git a/components/drivers/spi/spi_flash_sfud.c b/components/drivers/spi/spi_flash_sfud.c index e622527d7a..c0e42b3cd8 100644 --- a/components/drivers/spi/spi_flash_sfud.c +++ b/components/drivers/spi/spi_flash_sfud.c @@ -402,14 +402,17 @@ static void sf(uint8_t argc, char **argv) { } else { char *spi_dev_name = argv[2]; rtt_dev_bak = rtt_dev; + + /* delete the old SPI flash device */ + if(rtt_dev_bak) { + rt_sfud_flash_delete(rtt_dev_bak); + } + rtt_dev = rt_sfud_flash_probe("sf_cmd", spi_dev_name); if (!rtt_dev) { return; } - /* already probe then delete the old SPI flash device */ - if(rtt_dev_bak) { - rt_sfud_flash_delete(rtt_dev_bak); - } + sfud_dev = (sfud_flash_t)rtt_dev->user_data; if (sfud_dev->chip.capacity < 1024 * 1024) { rt_kprintf("%d KB %s is current selected device.\n", sfud_dev->chip.capacity / 1024, sfud_dev->name); diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index 119e283898..336cfcb152 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -22,7 +22,12 @@ #ifdef RT_USB_DEVICE_CDC -#define TX_TIMEOUT 1000 +#ifdef RT_VCOM_TX_TIMEOUT +#define VCOM_TX_TIMEOUT RT_VCOM_TX_TIMEOUT +#else /*!RT_VCOM_TX_TIMEOUT*/ +#define VCOM_TX_TIMEOUT 1000 +#endif /*RT_VCOM_TX_TIMEOUT*/ + #define CDC_RX_BUFSIZE 128 #define CDC_MAX_PACKET_SIZE 64 #define VCOM_DEVICE "vcom" @@ -82,6 +87,7 @@ struct vcom_tx_msg rt_size_t size; }; +ALIGN(4) static struct udevice_descriptor dev_desc = { USB_DESC_LENGTH_DEVICE, //bLength; @@ -101,6 +107,7 @@ static struct udevice_descriptor dev_desc = }; //FS and HS needed +ALIGN(4) static struct usb_qualifier_descriptor dev_qualifier = { sizeof(dev_qualifier), //bLength @@ -115,6 +122,7 @@ static struct usb_qualifier_descriptor dev_qualifier = }; /* communcation interface descriptor */ +ALIGN(4) const static struct ucdc_comm_descriptor _comm_desc = { #ifdef RT_USB_DEVICE_COMPOSITE @@ -184,6 +192,7 @@ const static struct ucdc_comm_descriptor _comm_desc = }; /* data interface descriptor */ +ALIGN(4) const static struct ucdc_data_descriptor _data_desc = { /* interface descriptor */ @@ -217,7 +226,7 @@ const static struct ucdc_data_descriptor _data_desc = 0x00, }, }; - +ALIGN(4) static char serno[_SER_NO_LEN + 1] = {'\0'}; RT_WEAK rt_err_t vcom_get_stored_serno(char *serno, int size); @@ -225,7 +234,7 @@ rt_err_t vcom_get_stored_serno(char *serno, int size) { return RT_ERROR; } - +ALIGN(4) const static char* _ustring[] = { "Language", @@ -876,7 +885,7 @@ static void vcom_tx_thread_entry(void* parameter) rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request); - if (rt_completion_wait(&data->wait, TX_TIMEOUT) != RT_EOK) + if (rt_completion_wait(&data->wait, VCOM_TX_TIMEOUT) != RT_EOK) { RT_DEBUG_LOG(RT_DEBUG_USB, ("vcom tx timeout\n")); } diff --git a/components/drivers/usb/usbdevice/class/hid.c b/components/drivers/usb/usbdevice/class/hid.c index 8f34d4c1af..aea6d802d1 100644 --- a/components/drivers/usb/usbdevice/class/hid.c +++ b/components/drivers/usb/usbdevice/class/hid.c @@ -35,6 +35,7 @@ struct hid_s }; /* CustomHID_ConfigDescriptor */ +ALIGN(4) const rt_uint8_t _report_desc[]= { #ifdef RT_USB_DEVICE_HID_KEYBOARD @@ -239,6 +240,7 @@ const rt_uint8_t _report_desc[]= #endif }; /* CustomHID_ReportDescriptor */ +ALIGN(4) static struct udevice_descriptor _dev_desc = { USB_DESC_LENGTH_DEVICE, //bLength; @@ -258,6 +260,7 @@ static struct udevice_descriptor _dev_desc = }; //FS and HS needed +ALIGN(4) static struct usb_qualifier_descriptor dev_qualifier = { sizeof(dev_qualifier), //bLength @@ -273,6 +276,7 @@ static struct usb_qualifier_descriptor dev_qualifier = /* hid interface descriptor */ +ALIGN(4) const static struct uhid_comm_descriptor _hid_comm_desc = { #ifdef RT_USB_DEVICE_COMPOSITE @@ -357,7 +361,7 @@ const static struct uhid_comm_descriptor _hid_comm_desc = }, }; - +ALIGN(4) const static char* _ustring[] = { "Language", diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c index 5131f83840..6a6e92415b 100644 --- a/components/drivers/usb/usbdevice/class/mstorage.c +++ b/components/drivers/usb/usbdevice/class/mstorage.c @@ -68,6 +68,7 @@ struct mstorage struct rt_device_blk_geometry geometry; }; +ALIGN(4) static struct udevice_descriptor dev_desc = { USB_DESC_LENGTH_DEVICE, //bLength; @@ -87,6 +88,7 @@ static struct udevice_descriptor dev_desc = }; //FS and HS needed +ALIGN(4) static struct usb_qualifier_descriptor dev_qualifier = { sizeof(dev_qualifier), //bLength @@ -101,7 +103,7 @@ static struct usb_qualifier_descriptor dev_qualifier = }; - +ALIGN(4) const static struct umass_descriptor _mass_desc = { #ifdef RT_USB_DEVICE_COMPOSITE @@ -148,6 +150,7 @@ const static struct umass_descriptor _mass_desc = }, }; +ALIGN(4) const static char* _ustring[] = { "Language", @@ -170,6 +173,7 @@ static rt_size_t _read_10(ufunction_t func, ustorage_cbw_t cbw); static rt_size_t _write_10(ufunction_t func, ustorage_cbw_t cbw); static rt_size_t _verify_10(ufunction_t func, ustorage_cbw_t cbw); +ALIGN(4) static struct scsi_cmd cmd_data[] = { {SCSI_TEST_UNIT_READY, _test_unit_ready, 6, FIXED, 0, DIR_NONE}, diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c index e07c6349d0..8996b728e6 100644 --- a/components/drivers/usb/usbdevice/class/rndis.c +++ b/components/drivers/usb/usbdevice/class/rndis.c @@ -214,6 +214,7 @@ const static char* _ustring[] = USB_STRING_OS }; +ALIGN(4) struct usb_os_function_comp_id_descriptor rndis_func_comp_id_desc = { .bFirstInterfaceNumber = USB_DYNAMIC, @@ -222,7 +223,9 @@ struct usb_os_function_comp_id_descriptor rndis_func_comp_id_desc = .subCompatibleID = {'5', '1', '6', '2', '0', '0', '1', 0x00}, .reserved2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; + //FS and HS needed +ALIGN(4) static struct usb_qualifier_descriptor dev_qualifier = { sizeof(dev_qualifier), //bLength diff --git a/components/drivers/usb/usbdevice/class/winusb.c b/components/drivers/usb/usbdevice/class/winusb.c index ff2a81a4da..bf4b353d73 100644 --- a/components/drivers/usb/usbdevice/class/winusb.c +++ b/components/drivers/usb/usbdevice/class/winusb.c @@ -24,6 +24,7 @@ struct winusb_device typedef struct winusb_device * winusb_device_t; +ALIGN(4) static struct udevice_descriptor dev_desc = { USB_DESC_LENGTH_DEVICE, //bLength; @@ -41,7 +42,9 @@ static struct udevice_descriptor dev_desc = USB_STRING_SERIAL_INDEX, //iSerialNumber; USB_DYNAMIC, //bNumConfigurations; }; + //FS and HS needed +ALIGN(4) static struct usb_qualifier_descriptor dev_qualifier = { sizeof(dev_qualifier), //bLength @@ -55,6 +58,7 @@ static struct usb_qualifier_descriptor dev_qualifier = 0, }; +ALIGN(4) struct winusb_descriptor _winusb_desc = { #ifdef RT_USB_DEVICE_COMPOSITE @@ -102,7 +106,7 @@ struct winusb_descriptor _winusb_desc = }, }; - +ALIGN(4) const static char* _ustring[] = { "Language", @@ -113,11 +117,14 @@ const static char* _ustring[] = "Interface", USB_STRING_OS//must be }; + +ALIGN(4) struct usb_os_proerty winusb_proerty[] = { USB_OS_PROERTY_DESC(USB_OS_PROERTY_TYPE_REG_SZ,"DeviceInterfaceGUID",RT_WINUSB_GUID), }; +ALIGN(4) struct usb_os_function_comp_id_descriptor winusb_func_comp_id_desc = { .bFirstInterfaceNumber = USB_DYNAMIC, diff --git a/components/drivers/wlan/wlan_dev.c b/components/drivers/wlan/wlan_dev.c index a5707d55f0..d86dfb25d3 100644 --- a/components/drivers/wlan/wlan_dev.c +++ b/components/drivers/wlan/wlan_dev.c @@ -639,7 +639,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) { int level = *((int *)args); - LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_POWERSAVE, "RT_WLAN_CMD_SET_POWERSAVE"); + LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SET_POWERSAVE, "RT_WLAN_CMD_SET_POWERSAVE"); if (wlan->ops->wlan_set_powersave) wlan->ops->wlan_set_powersave(wlan, level); break; @@ -648,7 +648,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) { int *level = args; - LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_POWERSAVE, "RT_WLAN_CMD_GET_POWERSAVE"); + LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_GET_POWERSAVE, "RT_WLAN_CMD_GET_POWERSAVE"); if (wlan->ops->wlan_get_powersave) *level = wlan->ops->wlan_get_powersave(wlan); break; |
