diff options
| author | yangjie11 <[email protected]> | 2020-11-18 09:56:35 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-11-18 09:56:35 +0800 |
| commit | d4a682e8d97fa131e5a8d795f8c5451d55cdd5b0 (patch) | |
| tree | 4773b40cb012475c5daf74bfd55707e141477669 /components/drivers | |
| parent | 2b98f4720c827ae1850df78299f6b273d568c8c7 (diff) | |
| parent | 2ef3c9d861f55253620996a94831a4be31ca6620 (diff) | |
Merge pull request #3 from RT-Thread/master
sync
Diffstat (limited to 'components/drivers')
135 files changed, 10570 insertions, 8085 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index d8dc5e7458..db4455160e 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -8,6 +8,20 @@ if RT_USING_DEVICE_IPC config RT_PIPE_BUFSZ int "Set pipe buffer size" default 512 + + config RT_USING_SYSTEM_WORKQUEUE + bool "Using system default workqueue" + default n + + if RT_USING_SYSTEM_WORKQUEUE + config RT_SYSTEM_WORKQUEUE_STACKSIZE + int "The stack size for system workqueue thread" + default 2048 + + config RT_SYSTEM_WORKQUEUE_PRIORITY + int "The priority level of system workqueue thread" + default 23 + endif endif config RT_USING_SERIAL @@ -20,7 +34,12 @@ if RT_USING_SERIAL config RT_SERIAL_USING_DMA bool "Enable serial DMA mode" default y -endif + + config RT_SERIAL_RB_BUFSZ + int "Set RX buffer size" + default 64 + +endif config RT_USING_CAN bool "Using CAN device drivers" @@ -29,7 +48,7 @@ config RT_USING_CAN if RT_USING_CAN config RT_CAN_USING_HDR bool "Enable CAN hardware filter" - default y + default n endif config RT_USING_HWTIMER @@ -69,11 +88,25 @@ config RT_USING_I2C default n if RT_USING_I2C + config RT_I2C_DEBUG + bool "Use I2C debug message" + default n + config RT_USING_I2C_BITOPS bool "Use GPIO to simulate I2C" default y + + if RT_USING_I2C_BITOPS + config RT_I2C_BITOPS_DEBUG + bool "Use simulate I2C debug message" + default n + endif endif +config RT_USING_PHY + bool "Using ethernet phy device drivers" + default n + config RT_USING_PIN bool "Using generic GPIO device drivers" default y @@ -82,6 +115,10 @@ config RT_USING_ADC bool "Using ADC device drivers" default n +config RT_USING_DAC + bool "Using DAC device drivers" + default n + config RT_USING_PWM bool "Using PWM device drivers" default n @@ -100,20 +137,6 @@ config RT_USING_MTD_NAND default n endif -config RT_USING_MTD - bool "Using Memory Technology Device (MTD)" - default n - - if RT_USING_MTD - config MTD_USING_NOR - bool "Using MTD Nor Flash device" - default n - - config MTD_USING_NAND - bool "Using MTD Nand Flash device" - default n - endif - config RT_USING_PM bool "Using Power Management device drivers" default n @@ -123,22 +146,27 @@ config RT_USING_RTC default n if RT_USING_RTC - config RT_USING_SOFT_RTC - bool "Using software simulation RTC device" - default n - config RTC_SYNC_USING_NTP - bool "Using NTP auto sync RTC time" - depends on PKG_NETUTILS_NTP - default y + config RT_USING_ALARM + bool "Using RTC alarm" + default n + + config RT_USING_SOFT_RTC + bool "Using software simulation RTC device" + default n + + config RTC_SYNC_USING_NTP + bool "Using NTP auto sync RTC time" + depends on PKG_NETUTILS_NTP + default y - if RTC_SYNC_USING_NTP - config RTC_NTP_FIRST_SYNC_DELAY - int "NTP first sync delay time(second) for network connect" - default 30 - config RTC_NTP_SYNC_PERIOD - int "NTP auto sync period(second)" - default 3600 - endif + if RTC_SYNC_USING_NTP + config RTC_NTP_FIRST_SYNC_DELAY + int "NTP first sync delay time(second) for network connect" + default 30 + config RTC_NTP_SYNC_PERIOD + int "NTP auto sync period(second)" + default 3600 + endif endif config RT_USING_SDIO @@ -187,6 +215,9 @@ config RT_USING_SPI config RT_USING_SFUD bool "Using Serial Flash Universal Driver" default n + help + An using JEDEC's SFDP standard serial (SPI) flash universal driver library + if RT_USING_SFUD config RT_SFUD_USING_SFDP bool "Using auto probe flash JEDEC SFDP parameter" @@ -201,19 +232,18 @@ config RT_USING_SPI select RT_USING_QSPI default n + config RT_SFUD_SPI_MAX_HZ + int "Default spi maximum speed(HZ)" + range 0 50000000 + default 50000000 + help + Read the JEDEC SFDP command must run at 50 MHz or less,and you also can use rt_spi_configure(); to config spi speed. + config RT_DEBUG_SFUD bool "Show more SFUD debug information" default n endif - config RT_USING_W25QXX - bool "Using W25QXX SPI NorFlash" - default n - - config RT_USING_GD - bool "Using GD SPI NorFlash" - default n - config RT_USING_ENC28J60 bool "Using ENC28J60 SPI Ethernet network interface" select RT_USING_LWIP @@ -232,68 +262,335 @@ config RT_USING_WDT config RT_USING_AUDIO bool "Using Audio device drivers" default n + + if RT_USING_AUDIO + config RT_AUDIO_REPLAY_MP_BLOCK_SIZE + int "Replay memory pool block size" + default 4096 + + config RT_AUDIO_REPLAY_MP_BLOCK_COUNT + int "Replay memory pool block count" + default 2 + + config RT_AUDIO_RECORD_PIPE_SIZE + int "Record pipe size" + default 2048 + endif + +config RT_USING_SENSOR + bool "Using Sensor device drivers" + select RT_USING_PIN + default n + +if RT_USING_SENSOR + config RT_USING_SENSOR_CMD + bool "Using Sensor cmd" + default y +endif + +config RT_USING_TOUCH + bool "Using Touch device drivers" + default n + +menuconfig RT_USING_HWCRYPTO + bool "Using Hardware Crypto drivers" + default n + + if RT_USING_HWCRYPTO + config RT_HWCRYPTO_DEFAULT_NAME + string "Hardware crypto device name" + default "hwcryto" + + config RT_HWCRYPTO_IV_MAX_SIZE + int "IV max size" + default "16" + + config RT_HWCRYPTO_KEYBIT_MAX_SIZE + int "Key max bit length" + default 256 + + config RT_HWCRYPTO_USING_GCM + bool "Using Hardware GCM" + default n + + config RT_HWCRYPTO_USING_AES + bool "Using Hardware AES" + default n + + if RT_HWCRYPTO_USING_AES + config RT_HWCRYPTO_USING_AES_ECB + bool "Using Hardware AES ECB mode" + default y + + config RT_HWCRYPTO_USING_AES_CBC + bool "Using Hardware AES CBC mode" + default n + + config RT_HWCRYPTO_USING_AES_CFB + bool "Using Hardware AES CFB mode" + default n + + config RT_HWCRYPTO_USING_AES_CTR + bool "Using Hardware AES CTR mode" + default n + + config RT_HWCRYPTO_USING_AES_OFB + bool "Using Hardware AES OFB mode" + default n + endif + + config RT_HWCRYPTO_USING_DES + bool "Using Hardware DES" + default n + + if RT_HWCRYPTO_USING_DES + config RT_HWCRYPTO_USING_DES_ECB + bool "Using Hardware DES ECB mode" + default y + + config RT_HWCRYPTO_USING_DES_CBC + bool "Using Hardware DES CBC mode" + default n + endif + + config RT_HWCRYPTO_USING_3DES + bool "Using Hardware 3DES" + default n + + if RT_HWCRYPTO_USING_3DES + config RT_HWCRYPTO_USING_3DES_ECB + bool "Using Hardware 3DES ECB mode" + default y + + config RT_HWCRYPTO_USING_3DES_CBC + bool "Using Hardware 3DES CBC mode" + default n + endif + + config RT_HWCRYPTO_USING_RC4 + bool "Using Hardware RC4" + default n + + config RT_HWCRYPTO_USING_MD5 + bool "Using Hardware MD5" + default n + + config RT_HWCRYPTO_USING_SHA1 + bool "Using Hardware SHA1" + default n + + config RT_HWCRYPTO_USING_SHA2 + bool "Using Hardware SHA2" + default n + + if RT_HWCRYPTO_USING_SHA2 + config RT_HWCRYPTO_USING_SHA2_224 + bool "Using Hardware SHA2_224 mode" + default n + + config RT_HWCRYPTO_USING_SHA2_256 + bool "Using Hardware SHA2_256 mode" + default y + + config RT_HWCRYPTO_USING_SHA2_384 + bool "Using Hardware SHA2_384 mode" + default n + + config RT_HWCRYPTO_USING_SHA2_512 + bool "Using Hardware SHA2_512 mode" + default n + endif + + config RT_HWCRYPTO_USING_RNG + bool "Using Hardware RNG" + default n + + config RT_HWCRYPTO_USING_CRC + bool "Using Hardware CRC" + default n + + if RT_HWCRYPTO_USING_CRC + config RT_HWCRYPTO_USING_CRC_07 + bool "Using Hardware CRC-8 0x07 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_8005 + bool "Using Hardware CRC-16 0x8005 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_1021 + bool "Using Hardware CRC-16 0x1021 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_3D65 + bool "Using Hardware CRC-16 0x3D65 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_04C11DB7 + bool "Using Hardware CRC-32 0x04C11DB7 polynomial" + default n + endif + + config RT_HWCRYPTO_USING_BIGNUM + bool "Using Hardware bignum" + default n + + if RT_HWCRYPTO_USING_BIGNUM + config RT_HWCRYPTO_USING_BIGNUM_EXPTMOD + bool "Using Hardware bignum expt_mod operation" + default y + + config RT_HWCRYPTO_USING_BIGNUM_MULMOD + bool "Using Hardware bignum mul_mod operation" + default y + + config RT_HWCRYPTO_USING_BIGNUM_MUL + bool "Using Hardware bignum mul operation" + default n + + config RT_HWCRYPTO_USING_BIGNUM_ADD + bool "Using Hardware bignum add operation" + default n + + config RT_HWCRYPTO_USING_BIGNUM_SUB + bool "Using Hardware bignum sub operation" + default n + endif + endif + +config RT_USING_PULSE_ENCODER + bool "Using PULSE ENCODER device drivers" + default n -menu "Using WiFi" - config RT_USING_WIFI +config RT_USING_INPUT_CAPTURE + bool "Using INPUT CAPTURE device drivers" + default n + +if RT_USING_INPUT_CAPTURE + config RT_INPUT_CAPTURE_RB_SIZE + int "Set input capture ringbuffer size" + default 100 +endif + +menuconfig RT_USING_WIFI bool "Using Wi-Fi framework" default n if RT_USING_WIFI config RT_WLAN_DEVICE_STA_NAME - string "The WiFi device name for station" + string "The device name for station" default "wlan0" config RT_WLAN_DEVICE_AP_NAME - string "The WiFi device name for ap" + string "The device name for ap" default "wlan1" - config RT_WLAN_DEFAULT_PROT - string "Default transport protocol" - default "lwip" - - config RT_WLAN_SCAN_WAIT_MS - int "Set scan timeout time(ms)" - default 10000 - - config RT_WLAN_CONNECT_WAIT_MS - int "Set connect timeout time(ms)" - default 10000 - config RT_WLAN_SSID_MAX_LENGTH - int "SSID name maximum length" + int "SSID maximum length" default 32 config RT_WLAN_PASSWORD_MAX_LENGTH - int "Maximum password length" + int "Password maximum length" default 32 - config RT_WLAN_SCAN_SORT - bool "Automatic sorting of scan results" + config RT_WLAN_DEV_EVENT_NUM + int "Driver events maxcount" + default 2 + + config RT_WLAN_MANAGE_ENABLE + bool "Connection management Enable" default y - config RT_WLAN_CFG_INFO_MAX - int "Maximum number of WiFi information automatically saved" - default 3 + if RT_WLAN_MANAGE_ENABLE + config RT_WLAN_SCAN_WAIT_MS + int "Set scan timeout time(ms)" + default 10000 - config RT_WLAN_WORKQUEUE_THREAD_NAME - string "WiFi work queue thread name" - default "wlan_job" + config RT_WLAN_CONNECT_WAIT_MS + int "Set connect timeout time(ms)" + default 10000 - config RT_WLAN_WORKQUEUE_THREAD_SIZE - int "wifi work queue thread size" - default 2048 + config RT_WLAN_SCAN_SORT + bool "Automatic sorting of scan results" + default y - config RT_WLAN_WORKQUEUE_THREAD_PRIO - int "WiFi work queue thread priority" - default 22 + config RT_WLAN_MSH_CMD_ENABLE + bool "MSH command Enable" + default y - config RT_WLAN_DEV_EVENT_NUM - int "Maximum number of driver events" - default 2 + config RT_WLAN_AUTO_CONNECT_ENABLE + bool "Auto connect Enable" + select RT_WLAN_CFG_ENABLE + select RT_WLAN_WORK_THREAD_ENABLE + default y - config RT_WLAN_PROT_LWIP_PBUF_FORCE - bool "Forced use of PBUF transmission" - default n + if RT_WLAN_AUTO_CONNECT_ENABLE + config AUTO_CONNECTION_PERIOD_MS + int "Auto connect period(ms)" + default 2000 + endif + endif + + config RT_WLAN_CFG_ENABLE + bool "WiFi information automatically saved Enable" + default y + + if RT_WLAN_CFG_ENABLE + config RT_WLAN_CFG_INFO_MAX + int "Maximum number of WiFi information automatically saved" + default 3 + endif + + config RT_WLAN_PROT_ENABLE + bool "Transport protocol manage Enable" + default y + + if RT_WLAN_PROT_ENABLE + config RT_WLAN_PROT_NAME_LEN + int "Transport protocol name length" + default 8 + + config RT_WLAN_PROT_MAX + int "Transport protocol maxcount" + default 2 + + config RT_WLAN_DEFAULT_PROT + string "Default transport protocol" + default "lwip" + + config RT_WLAN_PROT_LWIP_ENABLE + bool "LWIP transport protocol Enable" + select RT_USING_LWIP + default y + + if RT_WLAN_PROT_LWIP_ENABLE + config RT_WLAN_PROT_LWIP_NAME + string "LWIP transport protocol name" + default "lwip" + + config RT_WLAN_PROT_LWIP_PBUF_FORCE + bool "Forced use of PBUF transmission" + default n + endif + endif + + config RT_WLAN_WORK_THREAD_ENABLE + bool "WLAN work queue thread Enable" + default y + + if RT_WLAN_WORK_THREAD_ENABLE + config RT_WLAN_WORKQUEUE_THREAD_NAME + string "WLAN work queue thread name" + default "wlan" + + config RT_WLAN_WORKQUEUE_THREAD_SIZE + int "WLAN work queue thread size" + default 2048 + + config RT_WLAN_WORKQUEUE_THREAD_PRIO + int "WLAN work queue thread priority" + default 15 + endif menuconfig RT_WLAN_DEBUG bool "Enable WLAN Debugging Options" @@ -325,7 +622,6 @@ menu "Using WiFi" default n endif endif -endmenu menu "Using USB" config RT_USING_USB_HOST @@ -388,6 +684,9 @@ menu "Using USB" config _RT_USB_DEVICE_WINUSB bool "Enable to use device as winusb device" select RT_USB_DEVICE_WINUSB + config _RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio device" + select RT_USB_DEVICE_AUDIO endchoice if RT_USB_DEVICE_COMPOSITE config RT_USB_DEVICE_CDC @@ -413,11 +712,17 @@ menu "Using USB" config RT_USB_DEVICE_WINUSB bool "Enable to use device as winusb device" default n + config RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio 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_CDC_RX_BUFSIZE + int "virtual com rx buffer size" + default 128 config RT_VCOM_TX_USE_DMA bool "Enable to use dma for vcom tx" default n @@ -441,6 +746,14 @@ menu "Using USB" string "msc class disk name" default "flash0" endif + + if RT_USB_DEVICE_RNDIS + config RNDIS_DELAY_LINK_UP + bool "Delay linkup media connection" + select RT_USING_TIMER_SOFT + default n + endif + if RT_USB_DEVICE_HID config RT_USB_DEVICE_HID_KEYBOARD bool "Use to HID device as Keyboard" @@ -472,6 +785,24 @@ menu "Using USB" bool "Use to HID device as media keyboard" default y endif + if RT_USB_DEVICE_AUDIO + config RT_USB_DEVICE_AUDIO_MIC + bool "Use usb mic device as audio device" + default n + if RT_USB_DEVICE_AUDIO_MIC + config RT_USBD_MIC_DEVICE_NAME + string "audio mic device name" + default "mic0" + endif + config RT_USB_DEVICE_AUDIO_SPEAKER + bool "Use usb speaker device as audio device" + default n + if RT_USB_DEVICE_AUDIO_SPEAKER + config RT_USBD_SPEAKER_DEVICE_NAME + string "audio speaker device name" + default "sound0" + endif + endif endif endmenu endmenu diff --git a/components/drivers/audio/audio.c b/components/drivers/audio/audio.c index 6a5ebc8741..4cec8a4a9c 100644 --- a/components/drivers/audio/audio.c +++ b/components/drivers/audio/audio.c @@ -5,83 +5,208 @@ * * Change Logs: * Date Author Notes - * 2017-05-09 Urey first version + * 2017-05-09 Urey first version + * 2019-07-09 Zero-Free improve device ops interface and data flows */ #include <stdio.h> +#include <string.h> #include <rthw.h> #include <rtthread.h> #include <rtdevice.h> -#include <drivers/audio.h> +#define DBG_TAG "audio" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> -#include "audio_pipe.h" +#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#define AUDIO_DEBUG 0 -#if AUDIO_DEBUG -#define AUDIO_DBG(...) printf("[AUDIO]:"),printf(__VA_ARGS__) -#else -#define AUDIO_DBG(...) -#endif - -static struct rt_audio_pipe audio_pipe; +enum +{ + REPLAY_EVT_NONE = 0x00, + REPLAY_EVT_START = 0x01, + REPLAY_EVT_STOP = 0x02, +}; static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio) { rt_err_t result = RT_EOK; - rt_base_t level; - struct rt_audio_frame frame; + rt_uint8_t *data; + rt_size_t dst_size, src_size; + rt_uint16_t position, remain_bytes = 0, index = 0; + struct rt_audio_buf_info *buf_info; RT_ASSERT(audio != RT_NULL); - //check repaly queue is empty - if (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) != RT_EOK) + buf_info = &audio->replay->buf_info; + /* save current pos */ + position = audio->replay->pos; + dst_size = buf_info->block_size; + + /* check repaly queue is empty */ + if (rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size) != RT_EOK) { - AUDIO_DBG("TX queue is empty\n"); - result = -RT_EEMPTY; + /* ack stop event */ + if (audio->replay->event & REPLAY_EVT_STOP) + rt_completion_done(&audio->replay->cmp); - level = rt_hw_interrupt_disable(); - audio->replay->activated = RT_FALSE; - rt_hw_interrupt_enable(level); + /* send zero frames */ + memset(&buf_info->buffer[audio->replay->pos], 0, dst_size); - goto _exit; + audio->replay->pos += dst_size; + audio->replay->pos %= buf_info->total_size; } - - if (audio->ops->transmit != RT_NULL) + else { - AUDIO_DBG("audio transmit...\n"); - if (audio->ops->transmit(audio, frame.data_ptr, RT_NULL, frame.data_size) != frame.data_size) + memset(&buf_info->buffer[audio->replay->pos], 0, dst_size); + + /* copy data from memory pool to hardware device fifo */ + while (index < dst_size) { - result = -RT_EBUSY; + result = rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size); + if (result != RT_EOK) + { + LOG_D("under run %d, remain %d", audio->replay->pos, remain_bytes); + audio->replay->pos -= remain_bytes; + audio->replay->pos += dst_size; + audio->replay->pos %= buf_info->total_size; + audio->replay->read_index = 0; + result = -RT_EEMPTY; + break; + } + + remain_bytes = MIN((dst_size - index), (src_size - audio->replay->read_index)); + memcpy(&buf_info->buffer[audio->replay->pos], + &data[audio->replay->read_index], remain_bytes); + + index += remain_bytes; + audio->replay->read_index += remain_bytes; + audio->replay->pos += remain_bytes; + audio->replay->pos %= buf_info->total_size; + + if (audio->replay->read_index == src_size) + { + /* free memory */ + audio->replay->read_index = 0; + rt_data_queue_pop(&audio->replay->queue, (const void **)&data, &src_size, RT_WAITING_NO); + rt_mp_free(data); - goto _exit; + /* notify transmitted complete. */ + if (audio->parent.tx_complete != RT_NULL) + audio->parent.tx_complete(&audio->parent, (void *)data); + } } } - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); + if (audio->ops->transmit != RT_NULL) + { + if (audio->ops->transmit(audio, &buf_info->buffer[position], RT_NULL, dst_size) != dst_size) + result = -RT_ERROR; + } - _exit: return result; + return result; } static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio) { - struct rt_audio_frame frame; + rt_err_t result = RT_EOK; - if (audio->replay == RT_NULL) - return -RT_EIO; - while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK) + if (audio->replay->write_index) { - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); + result = rt_data_queue_push(&audio->replay->queue, + (const void **)audio->replay->write_data, + audio->replay->write_index, + RT_WAITING_FOREVER); - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); + audio->replay->write_index = 0; } - return RT_EOK; + return result; +} + +static rt_err_t _aduio_replay_start(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->replay->activated != RT_TRUE) + { + /* start playback hardware device */ + if (audio->ops->start) + result = audio->ops->start(audio, AUDIO_STREAM_REPLAY); + + audio->replay->activated = RT_TRUE; + LOG_D("start audio replay device"); + } + + return result; +} + +static rt_err_t _aduio_replay_stop(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->replay->activated == RT_TRUE) + { + /* flush replay remian frames */ + _audio_flush_replay_frame(audio); + + /* notify irq(or thread) to stop the data transmission */ + audio->replay->event |= REPLAY_EVT_STOP; + + /* waiting for the remaining data transfer to complete */ + rt_completion_init(&audio->replay->cmp); + rt_completion_wait(&audio->replay->cmp, RT_WAITING_FOREVER); + audio->replay->event &= ~REPLAY_EVT_STOP; + + /* stop playback hardware device */ + if (audio->ops->stop) + result = audio->ops->stop(audio, AUDIO_STREAM_REPLAY); + + audio->replay->activated = RT_FALSE; + LOG_D("stop audio replay device"); + } + + return result; +} + +static rt_err_t _audio_record_start(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->record->activated != RT_TRUE) + { + /* open audio record pipe */ + rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY); + + /* start record hardware device */ + if (audio->ops->start) + result = audio->ops->start(audio, AUDIO_STREAM_RECORD); + + audio->record->activated = RT_TRUE; + LOG_D("start audio record device"); + } + + return result; +} + +static rt_err_t _audio_record_stop(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->record->activated == RT_TRUE) + { + /* stop record hardware device */ + if (audio->ops->stop) + result = audio->ops->stop(audio, AUDIO_STREAM_RECORD); + + /* close audio record pipe */ + rt_device_close(RT_DEVICE(&audio->record->pipe)); + + audio->record->activated = RT_FALSE; + LOG_D("stop audio record device"); + } + + return result; } static rt_err_t _audio_dev_init(struct rt_device *dev) @@ -96,9 +221,68 @@ static rt_err_t _audio_dev_init(struct rt_device *dev) audio->replay = RT_NULL; audio->record = RT_NULL; - /* apply configuration */ + /* initialize replay */ + if (dev->flag & RT_DEVICE_FLAG_WRONLY) + { + struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay)); + + if (replay == RT_NULL) + return -RT_ENOMEM; + memset(replay, 0, sizeof(struct rt_audio_replay)); + + /* init memory pool for replay */ + replay->mp = rt_mp_create("adu_mp", RT_AUDIO_REPLAY_MP_BLOCK_COUNT, RT_AUDIO_REPLAY_MP_BLOCK_SIZE); + if (replay->mp == RT_NULL) + { + rt_free(replay); + LOG_E("create memory pool for repaly failed"); + return -RT_ENOMEM; + } + + /* init queue for audio replay */ + rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, 0, RT_NULL); + + /* init mutex lock for audio replay */ + rt_mutex_init(&replay->lock, "replay", RT_IPC_FLAG_PRIO); + + replay->activated = RT_FALSE; + audio->replay = replay; + } + + /* initialize record */ + if (dev->flag & RT_DEVICE_FLAG_RDONLY) + { + struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record)); + rt_uint8_t *buffer; + + if (record == RT_NULL) + return -RT_ENOMEM; + memset(record, 0, sizeof(struct rt_audio_record)); + + /* init pipe for record*/ + buffer = rt_malloc(RT_AUDIO_RECORD_PIPE_SIZE); + if (buffer == RT_NULL) + { + rt_free(record); + LOG_E("malloc memory for for record pipe failed"); + return -RT_ENOMEM; + } + rt_audio_pipe_init(&record->pipe, "record", + (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), + buffer, + RT_AUDIO_RECORD_PIPE_SIZE); + + record->activated = RT_FALSE; + audio->record = record; + } + + /* initialize hardware configuration */ if (audio->ops->init) - result = audio->ops->init(audio); + audio->ops->init(audio); + + /* get replay buffer information */ + if (audio->ops->buffer_info) + audio->ops->buffer_info(audio, &audio->replay->buf_info); return result; } @@ -122,65 +306,27 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag) /* initialize the Rx/Tx structure according to open flag */ if (oflag & RT_DEVICE_OFLAG_WRONLY) { - AUDIO_DBG("open audio device ,oflag = %x\n",oflag); - if (audio->replay == RT_NULL) + if (audio->replay->activated != RT_TRUE) { - struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay)); - - if (replay == RT_NULL) - { - AUDIO_DBG("request memory for replay error\n"); - return -RT_ENOMEM; - } - - //init queue for audio replay - rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, CFG_AUDIO_REPLAY_QUEUE_COUNT / 2, RT_NULL); - - replay->activated = RT_FALSE; - audio->replay = replay; + LOG_D("open audio replay device, oflag = %x\n", oflag); + audio->replay->write_index = 0; + audio->replay->read_index = 0; + audio->replay->pos = 0; + audio->replay->event = REPLAY_EVT_NONE; } - dev->open_flag |= RT_DEVICE_OFLAG_WRONLY; } if (oflag & RT_DEVICE_OFLAG_RDONLY) { - if (audio->record == RT_NULL) + /* open record pipe */ + if (audio->record->activated != RT_TRUE) { - struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record)); - - if (record == RT_NULL) - { - AUDIO_DBG("request memory for record error\n"); - return -RT_ENOMEM; - } - - //init pipe for record - { - rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE); - - if (buf == RT_NULL) - { - rt_free(record); - AUDIO_DBG("request pipe memory error\n"); + LOG_D("open audio record device ,oflag = %x\n", oflag); - return -RT_ENOMEM; - } - - rt_audio_pipe_init(&audio_pipe, "recpipe", (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), buf, - CFG_AUDIO_RECORD_PIPE_SIZE); - } - - record->activated = RT_FALSE; - audio->record = record; - } - - //open record pipe - if (audio->record != RT_NULL) - { - rt_device_open(RT_DEVICE(&audio_pipe), RT_DEVICE_OFLAG_RDONLY); + _audio_record_start(audio); + audio->record->activated = RT_TRUE; } - dev->open_flag |= RT_DEVICE_OFLAG_RDONLY; } @@ -193,39 +339,17 @@ static rt_err_t _audio_dev_close(struct rt_device *dev) RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; - //shutdown the lower device - if (audio->ops->shutdown != RT_NULL) - audio->ops->shutdown(audio); - if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY) { - struct rt_audio_frame frame; - //stop replay stream - audio->ops->stop(audio, AUDIO_STREAM_REPLAY); - - //flush all frame - while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK) - { - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); - - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); - } - + /* stop replay stream */ + _aduio_replay_stop(audio); dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY; } if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY) { - //stop record stream - audio->ops->stop(audio, AUDIO_STREAM_RECORD); - - //close record pipe - if (audio->record != RT_NULL) - rt_device_close(RT_DEVICE(&audio_pipe)); - + /* stop record stream */ + _audio_record_stop(audio); dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY; } @@ -237,17 +361,19 @@ static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buff struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; + if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL)) return 0; - return rt_device_read(RT_DEVICE(&audio_pipe), pos, buffer, size); + return rt_device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size); } static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) { - rt_err_t result = RT_EOK; - rt_base_t level; + struct rt_audio_device *audio; + rt_uint8_t *ptr; + rt_uint16_t block_size, remain_bytes, index = 0; RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; @@ -255,34 +381,46 @@ static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const voi if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL)) return 0; - AUDIO_DBG("audio write : pos = %d,buffer = %x,size = %d\n",pos,(rt_uint32_t)buffer,size); - //push a new frame to tx queue + /* push a new frame to replay data queue */ + ptr = (rt_uint8_t *)buffer; + block_size = RT_AUDIO_REPLAY_MP_BLOCK_SIZE; + + rt_mutex_take(&audio->replay->lock, RT_WAITING_FOREVER); + while (index < size) { - result = rt_data_queue_push(&audio->replay->queue, buffer, size, - RT_WAITING_FOREVER); - if (result != RT_EOK) + /* request buffer from replay memory pool */ + if (audio->replay->write_index % block_size == 0) { - AUDIO_DBG("TX frame queue push error\n"); - rt_set_errno(-RT_EFULL); - return 0; + audio->replay->write_data = rt_mp_alloc(audio->replay->mp, RT_WAITING_FOREVER); + memset(audio->replay->write_data, 0, block_size); + } + + /* copy data to replay memory pool */ + remain_bytes = MIN((block_size - audio->replay->write_index), (size - index)); + memcpy(&audio->replay->write_data[audio->replay->write_index], &ptr[index], remain_bytes); + + index += remain_bytes; + audio->replay->write_index += remain_bytes; + audio->replay->write_index %= block_size; + + if (audio->replay->write_index == 0) + { + rt_data_queue_push(&audio->replay->queue, + audio->replay->write_data, + block_size, + RT_WAITING_FOREVER); } } + rt_mutex_release(&audio->replay->lock); - //check tx state... - level = rt_hw_interrupt_disable(); + /* check replay state */ if (audio->replay->activated != RT_TRUE) { + _aduio_replay_start(audio); audio->replay->activated = RT_TRUE; - rt_hw_interrupt_enable(level); - - _audio_send_replay_frame(audio); - } - else - { - rt_hw_interrupt_enable(level); } - return size; + return index; } static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args) @@ -292,112 +430,70 @@ static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args) RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; - //dev stat... + /* dev stat...*/ switch (cmd) { - case AUDIO_CTL_GETCAPS: - { - struct rt_audio_caps *caps = (struct rt_audio_caps *) args; + case AUDIO_CTL_GETCAPS: + { + struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - AUDIO_DBG("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type); - if (audio->ops->getcaps != RT_NULL) - { - result = audio->ops->getcaps(audio, caps); - } - } - break; - case AUDIO_CTL_CONFIGURE: + LOG_D("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type); + if (audio->ops->getcaps != RT_NULL) { - struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - - AUDIO_DBG("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type); - if (audio->ops->configure != RT_NULL) - { - result = audio->ops->configure(audio, caps); - } + result = audio->ops->getcaps(audio, caps); } break; - case AUDIO_CTL_SHUTDOWN: - { - AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n"); - - if (audio->ops->shutdown != RT_NULL) - result = audio->ops->shutdown(audio); + } - //flush replay frame... - _audio_flush_replay_frame(audio); - } - break; + case AUDIO_CTL_CONFIGURE: + { + struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - case AUDIO_CTL_START: + LOG_D("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type); + if (audio->ops->configure != RT_NULL) { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_START: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->start(audio, stream); + result = audio->ops->configure(audio, caps); } + break; - case AUDIO_CTL_STOP: - { - int stream = *(int *) args; + } - AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->stop(audio, stream); + case AUDIO_CTL_START: + { + int stream = *(int *) args; - if (stream == AUDIO_STREAM_REPLAY) - { - _audio_flush_replay_frame(audio); - } - } - break; - case AUDIO_CTL_PAUSE: + LOG_D("AUDIO_CTL_START: stream = %d", stream); + if (stream == AUDIO_STREAM_REPLAY) { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_PAUSE: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->suspend(audio, stream); + result = _aduio_replay_start(audio); } - break; - case AUDIO_CTL_RESUME: + else { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_RESUME: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->resume(audio, stream); - - //resume tx frame... - if (stream == AUDIO_STREAM_REPLAY) - _audio_send_replay_frame(audio); + result = _audio_record_start(audio); } + break; - case AUDIO_CTL_ALLOCBUFFER: - { - struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *) args; + } - if (desc) - { - desc->data_size = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2; - desc->data_ptr = rt_mp_alloc(&audio->mp, RT_WAITING_FOREVER); + case AUDIO_CTL_STOP: + { + int stream = *(int *) args; - result = RT_EOK; - } - else result = -RT_EIO; + LOG_D("AUDIO_CTL_STOP: stream = %d", stream); + if (stream == AUDIO_STREAM_REPLAY) + { + result = _aduio_replay_stop(audio); } - break; - case AUDIO_CTL_FREEBUFFER: + else { - rt_uint8_t *data_ptr = (rt_uint8_t *) args; - if (data_ptr) - rt_mp_free(data_ptr); + result = _audio_record_stop(audio); } + break; - default: - result = audio->ops->control(audio, cmd, args); + } + + default: break; } @@ -418,7 +514,9 @@ const static struct rt_device_ops audio_ops = rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data) { + rt_err_t result = RT_EOK; struct rt_device *device; + RT_ASSERT(audio != RT_NULL); device = &(audio->parent); @@ -438,15 +536,14 @@ rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_u #endif device->user_data = data; - //init memory pool for replay - { - rt_uint8_t *mempool = rt_malloc(AUDIO_DEVICE_DECODE_MP_SZ); - rt_mp_init(&audio->mp, "adu_mp", mempool, AUDIO_DEVICE_DECODE_MP_SZ, - AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2); - } - /* register a character device */ - return rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE); + result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE); + + /* initialize audio device */ + if (result == RT_EOK) + result = rt_device_init(device); + + return result; } int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) @@ -454,43 +551,43 @@ int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) int speed = 0; switch (bitValue) { - case AUDIO_SAMP_RATE_8K: - speed = 8000; + case AUDIO_SAMP_RATE_8K: + speed = 8000; break; - case AUDIO_SAMP_RATE_11K: - speed = 11052; + case AUDIO_SAMP_RATE_11K: + speed = 11052; break; - case AUDIO_SAMP_RATE_16K: - speed = 16000; + case AUDIO_SAMP_RATE_16K: + speed = 16000; break; - case AUDIO_SAMP_RATE_22K: - speed = 22050; + case AUDIO_SAMP_RATE_22K: + speed = 22050; break; - case AUDIO_SAMP_RATE_32K: - speed = 32000; + case AUDIO_SAMP_RATE_32K: + speed = 32000; break; - case AUDIO_SAMP_RATE_44K: - speed = 44100; + case AUDIO_SAMP_RATE_44K: + speed = 44100; break; - case AUDIO_SAMP_RATE_48K: - speed = 48000; + case AUDIO_SAMP_RATE_48K: + speed = 48000; break; - case AUDIO_SAMP_RATE_96K: - speed = 96000; + case AUDIO_SAMP_RATE_96K: + speed = 96000; break; - case AUDIO_SAMP_RATE_128K: - speed = 128000; + case AUDIO_SAMP_RATE_128K: + speed = 128000; break; - case AUDIO_SAMP_RATE_160K: - speed = 160000; + case AUDIO_SAMP_RATE_160K: + speed = 160000; break; - case AUDIO_SAMP_RATE_172K: - speed = 176400; + case AUDIO_SAMP_RATE_172K: + speed = 176400; break; - case AUDIO_SAMP_RATE_192K: - speed = 192000; + case AUDIO_SAMP_RATE_192K: + speed = 192000; break; - default: + default: break; } @@ -498,46 +595,18 @@ int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) return speed; } -rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format) +void rt_audio_tx_complete(struct rt_audio_device *audio) { - switch (format) - { - case AUDIO_FMT_PCM_U8: - case AUDIO_FMT_PCM_S8: - return 8; - case AUDIO_FMT_PCM_S16_LE: - case AUDIO_FMT_PCM_S16_BE: - case AUDIO_FMT_PCM_U16_LE: - case AUDIO_FMT_PCM_U16_BE: - return 16; - default: - return 32; - }; -} - -void rt_audio_tx_complete(struct rt_audio_device *audio, rt_uint8_t *pbuf) -{ - rt_err_t result; - AUDIO_DBG("audio tx complete ptr=%x...\n",(rt_uint32_t)pbuf); - - //try to send all frame - do - { - result = _audio_send_replay_frame(audio); - } while (result == RT_EOK); - - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) pbuf); + /* try to send next frame */ + _audio_send_replay_frame(audio); } void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len) { - //save data to record pipe - rt_device_write(RT_DEVICE(RT_DEVICE(&audio_pipe)), 0, pbuf, len); + /* save data to record pipe */ + rt_device_write(RT_DEVICE(&audio->record->pipe), 0, pbuf, len); /* invoke callback */ if (audio->parent.rx_indicate != RT_NULL) audio->parent.rx_indicate(&audio->parent, len); } - diff --git a/components/drivers/audio/audio_pipe.c b/components/drivers/audio/audio_pipe.c index 4df9fd8a49..d7c37009b6 100644 --- a/components/drivers/audio/audio_pipe.c +++ b/components/drivers/audio/audio_pipe.c @@ -24,8 +24,8 @@ static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe) /* get suspended thread */ thread = rt_list_entry(pipe->suspended_write_list.next, - struct rt_thread, - tlist); + struct rt_thread, + tlist); /* resume the write thread */ rt_thread_resume(thread); @@ -50,7 +50,7 @@ static rt_size_t rt_pipe_read(rt_device_t dev, if (!(pipe->flag & RT_PIPE_FLAG_BLOCK_RD)) { level = rt_hw_interrupt_disable(); - read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); + read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size); /* if the ringbuffer is empty, there won't be any writer waiting */ if (read_nbytes) @@ -66,9 +66,10 @@ static rt_size_t rt_pipe_read(rt_device_t dev, /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do { + do + { level = rt_hw_interrupt_disable(); - read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); + read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size); if (read_nbytes == 0) { rt_thread_suspend(thread); @@ -85,7 +86,8 @@ static rt_size_t rt_pipe_read(rt_device_t dev, rt_hw_interrupt_enable(level); break; } - } while (read_nbytes == 0); + } + while (read_nbytes == 0); return read_nbytes; } @@ -104,8 +106,8 @@ static void _rt_pipe_resume_reader(struct rt_audio_pipe *pipe) /* get suspended thread */ thread = rt_list_entry(pipe->suspended_read_list.next, - struct rt_thread, - tlist); + struct rt_thread, + tlist); /* resume the read thread */ rt_thread_resume(thread); @@ -128,16 +130,16 @@ static rt_size_t rt_pipe_write(rt_device_t dev, RT_ASSERT(pipe != RT_NULL); if ((pipe->flag & RT_PIPE_FLAG_FORCE_WR) || - !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) + !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) { level = rt_hw_interrupt_disable(); if (pipe->flag & RT_PIPE_FLAG_FORCE_WR) write_nbytes = rt_ringbuffer_put_force(&(pipe->ringbuffer), - buffer, size); + (const rt_uint8_t *)buffer, size); else write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), - buffer, size); + (const rt_uint8_t *)buffer, size); _rt_pipe_resume_reader(pipe); @@ -151,9 +153,10 @@ static rt_size_t rt_pipe_write(rt_device_t dev, /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do { + do + { level = rt_hw_interrupt_disable(); - write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), buffer, size); + write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), (const rt_uint8_t *)buffer, size); if (write_nbytes == 0) { /* pipe full, waiting on suspended write list */ @@ -171,7 +174,8 @@ static rt_size_t rt_pipe_write(rt_device_t dev, rt_hw_interrupt_enable(level); break; } - } while (write_nbytes == 0); + } + while (write_nbytes == 0); return write_nbytes; } @@ -183,7 +187,7 @@ static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args) pipe = (struct rt_audio_pipe *)dev; if (cmd == PIPE_CTRL_GET_SPACE && args) - *(rt_size_t*)args = rt_ringbuffer_space_len(&pipe->ringbuffer); + *(rt_size_t *)args = rt_ringbuffer_space_len(&pipe->ringbuffer); return RT_EOK; } @@ -212,10 +216,10 @@ const static struct rt_device_ops audio_pipe_ops = * @return the operation status, RT_EOK on successful */ rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe, - const char *name, - rt_int32_t flag, - rt_uint8_t *buf, - rt_size_t size) + const char *name, + rt_int32_t flag, + rt_uint8_t *buf, + rt_size_t size) { RT_ASSERT(pipe); RT_ASSERT(buf); @@ -270,7 +274,7 @@ rt_err_t rt_audio_pipe_create(const char *name, rt_int32_t flag, rt_size_t size) return -RT_ENOMEM; /* create ring buffer of pipe */ - rb_memptr = rt_malloc(size); + rb_memptr = (rt_uint8_t *)rt_malloc(size); if (rb_memptr == RT_NULL) { rt_free(pipe); diff --git a/components/drivers/can/can.c b/components/drivers/can/can.c index e20fcddcff..9f4612355b 100644 --- a/components/drivers/can/can.c +++ b/components/drivers/can/can.c @@ -27,10 +27,15 @@ static rt_err_t rt_can_init(struct rt_device *dev) /* initialize rx/tx */ can->can_rx = RT_NULL; can->can_tx = RT_NULL; +#ifdef RT_CAN_USING_HDR + can->hdr = RT_NULL; +#endif /* apply configuration */ if (can->ops->configure) result = can->ops->configure(can, &can->config); + else + result = -RT_ENOSYS; return result; } @@ -53,7 +58,7 @@ rt_inline int _can_int_rx(struct rt_can_device *can, struct rt_can_msg *data, in { rt_base_t level; #ifdef RT_CAN_USING_HDR - rt_int32_t hdr; + rt_int8_t hdr; #endif /*RT_CAN_USING_HDR*/ struct rt_can_msg_list *listmsg = RT_NULL; @@ -293,7 +298,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) can->can_rx = rx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_RX; - /* configure low level device */ + /* open can rx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); } } @@ -311,7 +316,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) tx_fifo->buffer = (struct rt_can_sndbxinx_list *)(tx_fifo + 1); rt_memset(tx_fifo->buffer, 0, - can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); + can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); rt_list_init(&tx_fifo->freelist); for (i = 0; i < can->config.sndboxnumber; i++) { @@ -325,7 +330,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) can->can_tx = tx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_TX; - /* configure low level device */ + /* open can tx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX); } } @@ -405,7 +410,8 @@ static rt_err_t rt_can_close(struct rt_device *dev) rt_free(rx_fifo); dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; - /* configure low level device */ + can->can_rx = RT_NULL; + /* clear can rx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); } @@ -416,9 +422,11 @@ static rt_err_t rt_can_close(struct rt_device *dev) tx_fifo = (struct rt_can_tx_fifo *)can->can_tx; RT_ASSERT(tx_fifo != RT_NULL); + rt_sem_detach(&(tx_fifo->sem)); rt_free(tx_fifo); dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; - /* configure low level device */ + can->can_tx = RT_NULL; + /* clear can tx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_TX); } @@ -482,6 +490,7 @@ static rt_err_t rt_can_control(struct rt_device *dev, struct rt_can_device *can; rt_err_t res; + res = RT_EOK; RT_ASSERT(dev != RT_NULL); can = (struct rt_can_device *)dev; @@ -499,8 +508,9 @@ static rt_err_t rt_can_control(struct rt_device *dev, case RT_DEVICE_CTRL_CONFIG: /* configure device */ - can->ops->configure(can, (struct can_configure *)args); + res = can->ops->configure(can, (struct can_configure *)args); break; + case RT_CAN_CMD_SET_PRIV: /* configure device */ if ((rt_uint32_t)args != can->config.privmode) @@ -511,7 +521,6 @@ static rt_err_t rt_can_control(struct rt_device *dev, res = can->ops->control(can, cmd, args); if (res != RT_EOK) return res; - tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; if (can->config.privmode) { @@ -520,11 +529,11 @@ static rt_err_t rt_can_control(struct rt_device *dev, level = rt_hw_interrupt_disable(); if(rt_list_isempty(&tx_fifo->buffer[i].list)) { - rt_sem_release(&(tx_fifo->sem)); + rt_sem_release(&(tx_fifo->sem)); } else { - rt_list_remove(&tx_fifo->buffer[i].list); + rt_list_remove(&tx_fifo->buffer[i].list); } rt_hw_interrupt_enable(level); } @@ -542,7 +551,6 @@ static rt_err_t rt_can_control(struct rt_device *dev, rt_hw_interrupt_enable(level); } } - return RT_EOK; } break; @@ -559,74 +567,73 @@ static rt_err_t rt_can_control(struct rt_device *dev, return res; } - { - struct rt_can_filter_config *pfilter; - struct rt_can_filter_item *pitem; - rt_uint32_t count; - rt_base_t level; + struct rt_can_filter_config *pfilter; + struct rt_can_filter_item *pitem; + rt_uint32_t count; + rt_base_t level; - pfilter = (struct rt_can_filter_config *)args; - count = pfilter->count; - pitem = pfilter->items; - if (pfilter->actived) + pfilter = (struct rt_can_filter_config *)args; + RT_ASSERT(pfilter); + count = pfilter->count; + pitem = pfilter->items; + if (pfilter->actived) + { + while (count) { - while (count) + if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) { - if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) - { - count--; - pitem++; - continue; - } - - level = rt_hw_interrupt_disable(); - if (!can->hdr[pitem->hdr].connected) - { - rt_hw_interrupt_enable(level); - rt_memcpy(&can->hdr[pitem->hdr].filter, pitem, - sizeof(struct rt_can_filter_item)); - level = rt_hw_interrupt_disable(); - can->hdr[pitem->hdr].connected = 1; - can->hdr[pitem->hdr].msgs = 0; - rt_list_init(&can->hdr[pitem->hdr].list); - } - rt_hw_interrupt_enable(level); - count--; pitem++; + continue; } + + level = rt_hw_interrupt_disable(); + if (!can->hdr[pitem->hdr].connected) + { + rt_hw_interrupt_enable(level); + rt_memcpy(&can->hdr[pitem->hdr].filter, pitem, + sizeof(struct rt_can_filter_item)); + level = rt_hw_interrupt_disable(); + can->hdr[pitem->hdr].connected = 1; + can->hdr[pitem->hdr].msgs = 0; + rt_list_init(&can->hdr[pitem->hdr].list); + } + rt_hw_interrupt_enable(level); + + count--; + pitem++; } - else + } + else + { + while (count) { - while (count) + if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) { - if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) - { - count--; - pitem++; - continue; - } - level = rt_hw_interrupt_disable(); + count--; + pitem++; + continue; + } + level = rt_hw_interrupt_disable(); - if (can->hdr[pitem->hdr].connected) + if (can->hdr[pitem->hdr].connected) + { + can->hdr[pitem->hdr].connected = 0; + can->hdr[pitem->hdr].msgs = 0; + if (!rt_list_isempty(&can->hdr[pitem->hdr].list)) { - can->hdr[pitem->hdr].connected = 0; - can->hdr[pitem->hdr].msgs = 0; - if (!rt_list_isempty(&can->hdr[pitem->hdr].list)) - { - rt_list_remove(can->hdr[pitem->hdr].list.next); - } - rt_hw_interrupt_enable(level); - rt_memset(&can->hdr[pitem->hdr].filter, 0, - sizeof(struct rt_can_filter_item)); + rt_list_remove(can->hdr[pitem->hdr].list.next); } - else - { - rt_hw_interrupt_enable(level); - } - count--; - pitem++; + rt_hw_interrupt_enable(level); + rt_memset(&can->hdr[pitem->hdr].filter, 0, + sizeof(struct rt_can_filter_item)); + } + else + { + rt_hw_interrupt_enable(level); } + count--; + pitem++; } } break; @@ -640,12 +647,16 @@ static rt_err_t rt_can_control(struct rt_device *dev, /* control device */ if (can->ops->control != RT_NULL) { - can->ops->control(can, cmd, args); + res = can->ops->control(can, cmd, args); + } + else + { + res = -RT_ENOSYS; } break; } - return RT_EOK; + return res; } /* @@ -653,8 +664,10 @@ static rt_err_t rt_can_control(struct rt_device *dev, */ static void cantimeout(void *arg) { - rt_can_t can = (rt_can_t)arg; + rt_can_t can; + can = (rt_can_t)arg; + RT_ASSERT(can); rt_device_control((rt_device_t)can, RT_CAN_CMD_GET_STATUS, (void *)&can->status); if (can->status_indicate.ind != RT_NULL) @@ -688,7 +701,7 @@ const static struct rt_device_ops can_device_ops = /* * can register */ -rt_err_t rt_hw_can_register(struct rt_can_device *can, +rt_err_t rt_hw_can_register(struct rt_can_device *can, const char *name, const struct rt_can_ops *ops, void *data) @@ -758,7 +771,7 @@ void rt_hw_can_isr(struct rt_can_device *can, int event) struct rt_can_rx_fifo *rx_fifo; struct rt_can_msg_list *listmsg = RT_NULL; #ifdef RT_CAN_USING_HDR - rt_int32_t hdr; + rt_int8_t hdr; #endif int ch = -1; rt_base_t level; @@ -841,7 +854,10 @@ void rt_hw_can_isr(struct rt_can_device *can, int event) level = rt_hw_interrupt_disable(); rx_length = can->hdr[hdr].msgs * sizeof(struct rt_can_msg); rt_hw_interrupt_enable(level); - can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length); + if (rx_length) + { + can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length); + } } else #endif @@ -852,10 +868,13 @@ void rt_hw_can_isr(struct rt_can_device *can, int event) level = rt_hw_interrupt_disable(); /* get rx length */ - rx_length = rx_fifo->freenumbers * sizeof(struct rt_can_msg); + rx_length = rt_list_len(&rx_fifo->uselist)* sizeof(struct rt_can_msg); rt_hw_interrupt_enable(level); - can->parent.rx_indicate(&can->parent, rx_length); + if (rx_length) + { + can->parent.rx_indicate(&can->parent, rx_length); + } } } break; diff --git a/components/drivers/hwcrypto/SConscript b/components/drivers/hwcrypto/SConscript new file mode 100644 index 0000000000..90feff50b3 --- /dev/null +++ b/components/drivers/hwcrypto/SConscript @@ -0,0 +1,34 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +CPPPATH = [cwd, str(Dir('#'))] + +src = ['hwcrypto.c'] + +if (GetDepend(['RT_HWCRYPTO_USING_AES']) or + GetDepend(['RT_HWCRYPTO_USING_DES']) or + GetDepend(['RT_HWCRYPTO_USING_3DES']) or + GetDepend(['RT_HWCRYPTO_USING_RC4'])): + src += ['hw_symmetric.c'] + if GetDepend(['RT_HWCRYPTO_USING_GCM']): + src += ['hw_gcm.c'] + +if (GetDepend(['RT_HWCRYPTO_USING_MD5']) or + GetDepend(['RT_HWCRYPTO_USING_SHA1']) or + GetDepend(['RT_HWCRYPTO_USING_SHA2'])): + src += ['hw_hash.c'] + +if GetDepend(['RT_HWCRYPTO_USING_RNG']): + src += ['hw_rng.c'] + +if GetDepend(['RT_HWCRYPTO_USING_CRC']): + src += ['hw_crc.c'] + +if GetDepend(['RT_HWCRYPTO_USING_BIGNUM']): + src += ['hw_bignum.c'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_HWCRYPTO'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/hwcrypto/hw_bignum.c b/components/drivers/hwcrypto/hw_bignum.c new file mode 100644 index 0000000000..88813566b1 --- /dev/null +++ b/components/drivers/hwcrypto/hw_bignum.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_bignum.h> + +static struct rt_hwcrypto_ctx *bignum_default; + +rt_inline rt_err_t hwcrypto_bignum_dev_is_init(void) +{ + struct rt_hwcrypto_device *dev; + + if (bignum_default) + { + return RT_EOK; + } + dev = rt_hwcrypto_dev_default(); + if (dev == RT_NULL) + { + return -RT_ERROR; + } + return rt_hwcrypto_bignum_default(dev); +} + +/** + * @brief Setting bignum default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device) +{ + if (bignum_default) + { + rt_hwcrypto_ctx_destroy(bignum_default); + bignum_default = RT_NULL; + } + if (device == RT_NULL) + { + return RT_EOK; + } + bignum_default = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_BIGNUM, sizeof(struct hwcrypto_bignum)); + if (bignum_default == RT_NULL) + { + return -RT_ERROR; + } + return RT_EOK; +} + +/** + * @brief Init bignum obj + * + * @param n bignum obj + */ +void rt_hwcrypto_bignum_init(struct hw_bignum_mpi *n) +{ + if(n == RT_NULL) + return; + + n->sign = 1; + n->total = 0; + n->p = RT_NULL; +} + +/** + * @brief free a bignum obj + * + * @param Pointer to bignum obj + */ +void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n) +{ + if (n) + { + rt_free(n->p); + n->sign = 0; + n->total = 0; + n->p = RT_NULL; + } +} + +/** + * @brief Get length of bignum as an unsigned binary buffer + * + * @param n bignum obj + * + * @return binary buffer length + */ +int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n) +{ + int tmp_len, total; + + if (n == RT_NULL || n->p == RT_NULL) + { + return 0; + } + tmp_len = 0; + total = n->total; + while ((total > 0) && (n->p[total - 1] == 0)) + { + tmp_len++; + total--; + } + return n->total - tmp_len; +} + +/** + * @brief Export n into unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return export bin length + */ +int rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len) +{ + int cp_len, i, j; + + if (n == RT_NULL || buf == RT_NULL) + { + return 0; + } + rt_memset(buf, 0, len); + cp_len = n->total > len ? len : n->total; + for(i = cp_len, j = 0; i > 0; i--, j++) + { + buf[i - 1] = n->p[j]; + } + + return cp_len; +} + +/** + * @brief Import n from unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len) +{ + int cp_len, i, j; + void *temp_p; + + if (n == RT_NULL || buf == RT_NULL) + { + return 0; + } + if (n->total < len) + { + temp_p = rt_malloc(len); + if (temp_p == RT_NULL) + { + return 0; + } + rt_memset(temp_p, 0, len); + rt_free(n->p); + n->p = temp_p; + n->total = len; + } + cp_len = n->total > len ? len : n->total; + + for(i = cp_len, j = 0; i > 0; i--, j++) + { + n->p[j] = buf[i - 1]; + } + + return cp_len; +} + +/** + * @brief x = a + b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->add) + { + return bignum_ctx->ops->add(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a - b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->sub) + { + return bignum_ctx->ops->sub(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a * b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->mul) + { + return bignum_ctx->ops->mul(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a * b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->mulmod) + { + return bignum_ctx->ops->mulmod(bignum_ctx, x, a, b, c); + } + return -RT_ERROR; +} + +/** + * @brief x = a ^ b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->exptmod) + { + return bignum_ctx->ops->exptmod(bignum_ctx, x, a, b, c); + } + return -RT_ERROR; +} diff --git a/components/drivers/hwcrypto/hw_bignum.h b/components/drivers/hwcrypto/hw_bignum.h new file mode 100644 index 0000000000..a1f567e68f --- /dev/null +++ b/components/drivers/hwcrypto/hw_bignum.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_BIGNUM_H__ +#define __HW_BIGNUM_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_bignum; + +/* bignum obj */ +struct hw_bignum_mpi +{ + int sign; /**< integer sign */ + rt_size_t total; /**< total of limbs */ + rt_uint8_t *p; /**< pointer to limbs */ +}; + +struct hwcrypto_bignum_ops +{ + rt_err_t (*add)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a + b */ + rt_err_t (*sub)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a - b */ + rt_err_t (*mul)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a * b */ + rt_err_t (*mulmod)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); /**< x = a * b (mod c) */ + rt_err_t (*exptmod)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); /**< x = a ^ b (mod c) */ +}; + +/** + * @brief bignum context. Hardware driver usage + */ +struct hwcrypto_bignum +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_bignum_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Setting bignum default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device); + +/** + * @brief Init bignum obj + */ +void rt_hwcrypto_bignum_init(struct hw_bignum_mpi *n); + +/** + * @brief free a bignum obj + * + * @param Pointer to bignum obj + */ +void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n); + +/** + * @brief Get length of bignum as an unsigned binary buffer + * + * @param n bignum obj + * + * @return binary buffer Length + */ +int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n); + +/** + * @brief Export n into unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return export bin length + */ +int rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len); + +/** + * @brief Import n from unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len); + +/** + * @brief x = a + b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a - b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a * b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a * b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); + +/** + * @brief x = a ^ b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_crc.c b/components/drivers/hwcrypto/hw_crc.c new file mode 100644 index 0000000000..20579711e2 --- /dev/null +++ b/components/drivers/hwcrypto/hw_crc.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_crc.h> + +/** + * @brief Creating CRC Context + * + * @param device Hardware crypto device + * @param mode Setting default mode or custom mode + * + * @return CRC context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_crc_create(struct rt_hwcrypto_device *device, + hwcrypto_crc_mode mode) +{ + struct hwcrypto_crc *crc_ctx; + + crc_ctx = (struct hwcrypto_crc *)rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_CRC, sizeof(struct hwcrypto_crc)); + if (crc_ctx == RT_NULL) + { + return RT_NULL; + } + + switch (mode) + { + case HWCRYPTO_CRC_CRC8: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC8_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CRC16: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC16_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CRC32: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC32_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CCITT: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC_CCITT_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_DNP: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC_DNP_CFG; + crc_ctx->crc_cfg = temp; + break; + } + default: + break; + } + + return &crc_ctx->parent; +} + +/** + * @brief Destroy CRC Context + * + * @param ctx CRC context + */ +void rt_hwcrypto_crc_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Processing a packet of data + * + * @param ctx CRC context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_uint32_t rt_hwcrypto_crc_update(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *input, + rt_size_t length) +{ + struct hwcrypto_crc *crc_ctx = (struct hwcrypto_crc *)ctx; + if (ctx && crc_ctx->ops->update) + { + return crc_ctx->ops->update(crc_ctx, input, length); + } + return 0; +} + +/** + * @brief CRC context configuration + * + * @param ctx CRC context + * @param cfg CRC config + */ +void rt_hwcrypto_crc_cfg(struct rt_hwcrypto_ctx *ctx, + struct hwcrypto_crc_cfg *cfg) +{ + if (cfg) + { + ((struct hwcrypto_crc *)ctx)->crc_cfg = *cfg; + } +} diff --git a/components/drivers/hwcrypto/hw_crc.h b/components/drivers/hwcrypto/hw_crc.h new file mode 100644 index 0000000000..a6df92a2ef --- /dev/null +++ b/components/drivers/hwcrypto/hw_crc.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_CRC_H__ +#define __HW_CRC_H__ + +#include <hwcrypto.h> + +#define CRC_FLAG_REFIN (0x1 << 0) +#define CRC_FLAG_REFOUT (0x1 << 1) + +#define HWCRYPTO_CRC8_CFG \ +{ \ + .last_val = 0x00, \ + .poly = 0x07, \ + .width = 8, \ + .xorout = 0x00, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC16_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x8005, \ + .width = 16, \ + .xorout = 0x0000, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC32_CFG \ +{ \ + .last_val = 0x00000000, \ + .poly = 0x04C11DB7, \ + .width = 32, \ + .xorout = 0x00000000, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC_CCITT_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x1021, \ + .width = 16, \ + .xorout = 0x0000, \ + .flags = CRC_FLAG_REFIN | CRC_FLAG_REFOUT, \ +} + +#define HWCRYPTO_CRC_DNP_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x3D65, \ + .width = 16, \ + .xorout = 0xffff, \ + .flags = CRC_FLAG_REFIN | CRC_FLAG_REFOUT, \ +} + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_crc; + +typedef enum +{ + HWCRYPTO_CRC_CUSTOM, /**< Custom CRC mode */ + HWCRYPTO_CRC_CRC8, /**< poly : 0x07 */ + HWCRYPTO_CRC_CRC16, /**< poly : 0x8005 */ + HWCRYPTO_CRC_CRC32, /**< poly : 0x04C11DB7 */ + HWCRYPTO_CRC_CCITT, /**< poly : 0x1021 */ + HWCRYPTO_CRC_DNP, /**< poly : 0x3D65 */ +} hwcrypto_crc_mode; + +struct hwcrypto_crc_cfg +{ + rt_uint32_t last_val; /**< Last CRC value cache */ + rt_uint32_t poly; /**< CRC polynomial */ + rt_uint16_t width; /**< CRC value width */ + rt_uint32_t xorout; /**< Result XOR Value */ + rt_uint16_t flags; /**< Input or output data reverse. CRC_FLAG_REFIN or CRC_FLAG_REFOUT */ +}; + +struct hwcrypto_crc_ops +{ + rt_uint32_t (*update)(struct hwcrypto_crc *ctx, + const rt_uint8_t *in, rt_size_t length); /**< Perform a CRC calculation. return CRC value */ +}; + +/** + * @brief CRC context. Hardware driver usage + */ +struct hwcrypto_crc +{ + struct rt_hwcrypto_ctx parent; /**< Inherited from the standard device */ + struct hwcrypto_crc_cfg crc_cfg; /**< CRC configure */ + const struct hwcrypto_crc_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating CRC Context + * + * @param device Hardware crypto device + * @param mode Setting default mode or custom mode + * + * @return CRC context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_crc_create(struct rt_hwcrypto_device *device, + hwcrypto_crc_mode mode); + +/** + * @brief Destroy CRC Context + * + * @param ctx CRC context + */ +void rt_hwcrypto_crc_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Processing a packet of data + * + * @param ctx CRC context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return CRC value + */ +rt_uint32_t rt_hwcrypto_crc_update(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *input, rt_size_t length); + +/** + * @brief CRC context configuration + * + * @param ctx CRC context + * @param cfg CRC config + */ +void rt_hwcrypto_crc_cfg(struct rt_hwcrypto_ctx *ctx, + struct hwcrypto_crc_cfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_gcm.c b/components/drivers/hwcrypto/hw_gcm.c new file mode 100644 index 0000000000..8d0f49149a --- /dev/null +++ b/components/drivers/hwcrypto/hw_gcm.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-14 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_gcm.h> + +/** + * @brief Creating GCM Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return GCM context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_gcm_create(struct rt_hwcrypto_device *device, + hwcrypto_type crypt_type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_GCM, sizeof(struct hwcrypto_gcm)); + if (ctx) + { + ((struct hwcrypto_gcm *)ctx)->crypt_type = crypt_type; + } + return ctx; +} + +/** + * @brief Destroy GCM Context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief This function starts a GCM encryption or decryption operation + * + * @param ctx GCM context + * @param add The buffer holding the additional data + * @param add_len The length of the additional data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_start(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *add, + rt_size_t add_len) +{ + struct hwcrypto_gcm *gcm_ctx = (struct hwcrypto_gcm *)ctx; + + if (gcm_ctx && gcm_ctx->ops->start) + { + return gcm_ctx->ops->start(gcm_ctx, add, add_len); + } + return -RT_EINVAL; +} + +/** + * @brief This function finishes the GCM operation and generates the authentication tag + * + * @param ctx GCM context + * @param tag The buffer for holding the tag + * @param tag_len The length of the tag to generate + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_finish(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *tag, + rt_size_t tag_len) +{ + struct hwcrypto_gcm *gcm_ctx = (struct hwcrypto_gcm *)ctx; + + if (gcm_ctx && gcm_ctx->ops->finish) + { + return gcm_ctx->ops->finish(gcm_ctx, tag, tag_len); + } + return -RT_EINVAL; +} + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx GCM context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out) +{ + return rt_hwcrypto_symmetric_crypt(ctx, mode, length, in, out); +} + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setkey(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *key, rt_uint32_t bitlen) +{ + return rt_hwcrypto_symmetric_setkey(ctx, key, bitlen); +} + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +rt_err_t rt_hwcrypto_gcm_getkey(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *key, rt_uint32_t bitlen) +{ + return rt_hwcrypto_symmetric_getkey(ctx, key, bitlen); +} + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setiv(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *iv, rt_size_t len) +{ + return rt_hwcrypto_symmetric_setiv(ctx, iv, len); +} + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +rt_err_t rt_hwcrypto_gcm_getiv(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *iv, rt_size_t len) +{ + return rt_hwcrypto_symmetric_getiv(ctx, iv, len); +} + +/** + * @brief Set offset in initialization vector + * + * @param ctx GCM context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_gcm_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off) +{ + rt_hwcrypto_symmetric_set_ivoff(ctx, iv_off); +} + +/** + * @brief Get offset in initialization vector + * + * @param ctx GCM context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_gcm_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off) +{ + rt_hwcrypto_symmetric_get_ivoff(ctx, iv_off); +} + +/** + * @brief This function copy GCM context + * + * @param des The destination GCM context + * @param src The GCM context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_cpy(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src) +{ + struct hwcrypto_gcm *gcm_des = (struct hwcrypto_gcm *)des; + struct hwcrypto_gcm *gcm_src = (struct hwcrypto_gcm *)src; + + if (des != RT_NULL && src != RT_NULL) + { + gcm_des->crypt_type = gcm_src->crypt_type; + /* symmetric crypto context copy */ + return rt_hwcrypto_symmetric_cpy(des, src); + } + return -RT_EINVAL; +} + +/** + * @brief Reset GCM context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_reset(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_symmetric_reset(ctx); +} diff --git a/components/drivers/hwcrypto/hw_gcm.h b/components/drivers/hwcrypto/hw_gcm.h new file mode 100644 index 0000000000..a73b2b0634 --- /dev/null +++ b/components/drivers/hwcrypto/hw_gcm.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-14 tyx the first version + */ + +#ifndef __HW_GCM_H__ +#define __HW_GCM_H__ + +#include "hw_symmetric.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_gcm; + +struct hwcrypto_gcm_ops +{ + rt_err_t (*start)(struct hwcrypto_gcm *gcm_ctx, + const unsigned char *add, size_t add_len); /**< Set additional data. start GCM operation */ + rt_err_t (*finish)(struct hwcrypto_gcm *gcm_ctx, + const unsigned char *tag, size_t tag_len); /**< finish GCM operation. get tag */ +}; + +/** + * @brief GCM context. Hardware driver usage + */ +struct hwcrypto_gcm +{ + struct hwcrypto_symmetric parent; /**< Inheritance from hardware symmetric crypto context */ + hwcrypto_type crypt_type; /**< symmetric crypto type. eg: AES/DES */ + const struct hwcrypto_gcm_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating GCM Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return GCM context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_gcm_create(struct rt_hwcrypto_device *device, + hwcrypto_type crypt_type); + +/** + * @brief Destroy GCM Context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief This function starts a GCM encryption or decryption operation + * + * @param ctx GCM context + * @param add The buffer holding the additional data + * @param add_len The length of the additional data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_start(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *add, + rt_size_t add_len); + +/** + * @brief This function finishes the GCM operation and generates the authentication tag + * + * @param ctx GCM context + * @param tag The buffer for holding the tag + * @param tag_len The length of the tag to generate + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_finish(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *tag, + rt_size_t tag_len); + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx GCM context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out); + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setkey(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +rt_err_t rt_hwcrypto_gcm_getkey(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setiv(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +rt_err_t rt_hwcrypto_gcm_getiv(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Set offset in initialization vector + * + * @param ctx GCM context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_gcm_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off); + +/** + * @brief Get offset in initialization vector + * + * @param ctx GCM context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_gcm_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off); + +/** + * @brief This function copy GCM context + * + * @param des The destination GCM context + * @param src The GCM context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_cpy(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset GCM context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_reset(struct rt_hwcrypto_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_hash.c b/components/drivers/hwcrypto/hw_hash.c new file mode 100644 index 0000000000..b20069ac0e --- /dev/null +++ b/components/drivers/hwcrypto/hw_hash.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_hash.h> + +/** + * @brief Creating hash Context + * + * @param device Hardware crypto device + * @param type Type of hash context + * + * @return Hash context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_hash_create(struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_hash)); + return ctx; +} + +/** + * @brief Destroy hash Context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Get the final hash value + * + * @param ctx Hash context + * @param output Hash value buffer + * @param length Hash value buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_finish(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *output, rt_size_t length) +{ + if (ctx && ((struct hwcrypto_hash *)ctx)->ops->finish) + { + return ((struct hwcrypto_hash *)ctx)->ops->finish((struct hwcrypto_hash *)ctx, output, length); + } + return -RT_ERROR; +} + +/** + * @brief Processing a packet of data + * + * @param ctx Hash context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_update(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *input, rt_size_t length) +{ + if (ctx && ((struct hwcrypto_hash *)ctx)->ops->update) + { + return ((struct hwcrypto_hash *)ctx)->ops->update((struct hwcrypto_hash *)ctx, input, length); + } + return -RT_ERROR; +} + +/** + * @brief This function copy hash context + * + * @param des The destination hash context + * @param src The hash context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + return rt_hwcrypto_ctx_cpy(des, src); +} + +/** + * @brief Reset hash context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_reset(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_reset(ctx); +} + +/** + * @brief Setting hash context type + * + * @param ctx Hash context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + return rt_hwcrypto_set_type(ctx, type); +} diff --git a/components/drivers/hwcrypto/hw_hash.h b/components/drivers/hwcrypto/hw_hash.h new file mode 100644 index 0000000000..de0310e84c --- /dev/null +++ b/components/drivers/hwcrypto/hw_hash.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#ifndef __HW_HASH_H__ +#define __HW_HASH_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_hash; + +struct hwcrypto_hash_ops +{ + rt_err_t (*update)(struct hwcrypto_hash *hash_ctx, + const rt_uint8_t *in, rt_size_t length); /**< Processing a packet of data */ + rt_err_t (*finish)(struct hwcrypto_hash *hash_ctx, + rt_uint8_t *out, rt_size_t length); /**< Get the final hash value */ +}; + +/** + * @brief hash context. Hardware driver usage + */ +struct hwcrypto_hash +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_hash_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating hash Context + * + * @param device Hardware crypto device + * @param type Type of hash context + * + * @return Hash context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_hash_create(struct rt_hwcrypto_device *device, + hwcrypto_type type); + +/** + * @brief Destroy hash Context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Get the final hash value + * + * @param ctx Hash context + * @param output Hash value buffer + * @param length Hash value buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_finish(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *output, rt_size_t length); + +/** + * @brief Processing a packet of data + * + * @param ctx Hash context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_update(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *input, rt_size_t length); + +/** + * @brief This function copy hash context + * + * @param des The destination hash context + * @param src The hash context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset hash context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting hash context type + * + * @param ctx Hash context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_rng.c b/components/drivers/hwcrypto/hw_rng.c new file mode 100644 index 0000000000..13a17cc6be --- /dev/null +++ b/components/drivers/hwcrypto/hw_rng.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_rng.h> + +/* Used to save default RNG Context */ +static struct rt_hwcrypto_ctx *ctx_default; + +/** + * @brief Creating RNG Context + * + * @param device Hardware crypto device + * + * @return RNG context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_rng_create(struct rt_hwcrypto_device *device) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_RNG, sizeof(struct hwcrypto_rng)); + return ctx; +} + +/** + * @brief Destroy RNG Context + * + * @param ctx RNG context + */ +void rt_hwcrypto_rng_destroy(struct rt_hwcrypto_ctx *ctx) +{ + /* Destroy the defaule RNG Context ? */ + if (ctx == ctx_default) + { + ctx_default = RT_NULL; + } + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Setting RNG default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_rng_default(struct rt_hwcrypto_device *device) +{ + struct rt_hwcrypto_ctx *tmp_ctx; + + /* if device is null, destroy default RNG Context */ + if (device == RT_NULL) + { + if (ctx_default) + { + rt_hwcrypto_rng_destroy(ctx_default); + ctx_default = RT_NULL; + } + return RT_EOK; + } + /* Try create RNG Context */ + tmp_ctx = rt_hwcrypto_rng_create(device); + if (tmp_ctx == RT_NULL) + { + return -RT_ERROR; + } + /* create RNG Context success, update default RNG Context */ + rt_hwcrypto_rng_destroy(ctx_default); + ctx_default = tmp_ctx; + + return RT_EOK; +} + +/** + * @brief Getting Random Numbers from RNG Context + * + * @param ctx RNG context + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update_ctx(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx) + { + return ((struct hwcrypto_rng *)ctx)->ops->update((struct hwcrypto_rng *)ctx); + } + return 0; +} + +/** + * @brief Return a random number + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update(void) +{ + /* Default device does not exist ? */ + if (ctx_default == RT_NULL) + { + /* try create Context from default device */ + rt_hwcrypto_rng_default(rt_hwcrypto_dev_default()); + } + return rt_hwcrypto_rng_update_ctx(ctx_default); +} diff --git a/components/drivers/hwcrypto/hw_rng.h b/components/drivers/hwcrypto/hw_rng.h new file mode 100644 index 0000000000..fc28afdb1e --- /dev/null +++ b/components/drivers/hwcrypto/hw_rng.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_RNG_H__ +#define __HW_RNG_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_rng; + +struct hwcrypto_rng_ops +{ + rt_uint32_t (*update)(struct hwcrypto_rng *ctx); /**< Return a random number */ +}; + +/** + * @brief random context. Hardware driver usage + */ +struct hwcrypto_rng +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_rng_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating RNG Context + * + * @param device Hardware crypto device + * + * @return RNG context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_rng_create(struct rt_hwcrypto_device *device); + +/** + * @brief Destroy RNG Context + * + * @param ctx RNG context + */ +void rt_hwcrypto_rng_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting RNG default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_rng_default(struct rt_hwcrypto_device *device); + +/** + * @brief Getting Random Numbers from RNG Context + * + * @param ctx RNG context + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update_ctx(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Return a random number + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_symmetric.c b/components/drivers/hwcrypto/hw_symmetric.c new file mode 100644 index 0000000000..789c5c1a2c --- /dev/null +++ b/components/drivers/hwcrypto/hw_symmetric.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_symmetric.h> + +/** + * @brief Creating Symmetric Encryption and Decryption Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return Symmetric crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_symmetric)); + return ctx; +} + +/** + * @brief Destroy Symmetric Encryption and Decryption Context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx Symmetric crypto context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out) +{ + struct hwcrypto_symmetric *symmetric_ctx; + struct hwcrypto_symmetric_info symmetric_info; + rt_err_t err; + + if (ctx == RT_NULL) + { + return -RT_EINVAL; + } + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + if (symmetric_ctx->ops->crypt == RT_NULL) + { + return -RT_ERROR; + } + if (mode != HWCRYPTO_MODE_ENCRYPT && mode != HWCRYPTO_MODE_DECRYPT) + { + return -EINVAL; + } + + /* Input information packaging */ + symmetric_info.mode = mode; + symmetric_info.in = in; + symmetric_info.out = out; + symmetric_info.length = length; + + /* Calling Hardware Encryption and Decryption Function */ + err = symmetric_ctx->ops->crypt(symmetric_ctx, &symmetric_info); + + /* clean up flags */ + symmetric_ctx->flags &= ~(SYMMTRIC_MODIFY_KEY | SYMMTRIC_MODIFY_IV | SYMMTRIC_MODIFY_IVOFF); + return err; +} + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *key, rt_uint32_t bitlen) +{ + struct hwcrypto_symmetric *symmetric_ctx; + + if (ctx && bitlen <= RT_HWCRYPTO_KEYBIT_MAX_SIZE) + { + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + rt_memcpy(symmetric_ctx->key, key, bitlen >> 3); + /* Record key length */ + symmetric_ctx->key_bitlen = bitlen; + /* Key change flag set up */ + symmetric_ctx->flags |= SYMMTRIC_MODIFY_KEY; + return RT_EOK; + } + + return -RT_EINVAL; +} + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +int rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *key, rt_uint32_t bitlen) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + + if (ctx && bitlen >= symmetric_ctx->key_bitlen) + { + rt_memcpy(key, symmetric_ctx->key, symmetric_ctx->key_bitlen >> 3); + return symmetric_ctx->key_bitlen; + } + + return 0; +} + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *iv, rt_size_t len) +{ + struct hwcrypto_symmetric *symmetric_ctx; + + if (ctx && len <= RT_HWCRYPTO_IV_MAX_SIZE) + { + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + rt_memcpy(symmetric_ctx->iv, iv, len); + symmetric_ctx->iv_len = len; + /* IV change flag set up */ + symmetric_ctx->flags |= SYMMTRIC_MODIFY_IV; + return RT_EOK; + } + + return -RT_EINVAL; +} + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +int rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *iv, rt_size_t len) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx;; + + if (ctx && len >= symmetric_ctx->iv_len) + { + rt_memcpy(iv, symmetric_ctx->iv, symmetric_ctx->iv_len); + return symmetric_ctx->iv_len; + } + + return 0; +} + +/** + * @brief Set offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off) +{ + if (ctx) + { + ((struct hwcrypto_symmetric *)ctx)->iv_off = iv_off; + /* iv_off change flag set up */ + ((struct hwcrypto_symmetric *)ctx)->flags |= SYMMTRIC_MODIFY_IVOFF; + } +} + +/** + * @brief Get offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off) +{ + if (ctx && iv_off) + { + *iv_off = ((struct hwcrypto_symmetric *)ctx)->iv_off; + } +} + +/** + * @brief This function copy symmetric crypto context + * + * @param des The destination symmetric crypto context + * @param src The symmetric crypto context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + struct hwcrypto_symmetric *symmetric_des = (struct hwcrypto_symmetric *)des; + struct hwcrypto_symmetric *symmetric_src = (struct hwcrypto_symmetric *)src; + + if (des != RT_NULL && src != RT_NULL) + { + /* Copy Symmetric Encryption and Decryption Context Information */ + symmetric_des->flags = symmetric_src->flags ; + symmetric_des->iv_len = symmetric_src->iv_len ; + symmetric_des->iv_off = symmetric_src->iv_off ; + symmetric_des->key_bitlen = symmetric_src->key_bitlen; + rt_memcpy(symmetric_des->iv, symmetric_src->iv, symmetric_src->iv_len); + rt_memcpy(symmetric_des->key, symmetric_src->key, symmetric_src->key_bitlen >> 3); + + /* Hardware context copy */ + return rt_hwcrypto_ctx_cpy(des, src); + } + return -RT_EINVAL; +} + +/** + * @brief Reset symmetric crypto context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx *ctx) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + if (ctx != RT_NULL) + { + /* Copy Symmetric Encryption and Decryption Context Information */ + symmetric_ctx->flags = 0x00; + symmetric_ctx->iv_len = 0x00; + symmetric_ctx->iv_off = 0x00; + symmetric_ctx->key_bitlen = 0x00; + rt_memset(symmetric_ctx->iv, 0, RT_HWCRYPTO_IV_MAX_SIZE); + rt_memset(symmetric_ctx->key, 0, RT_HWCRYPTO_KEYBIT_MAX_SIZE >> 3); + + /* Hardware context reset */ + rt_hwcrypto_ctx_reset(ctx); + } +} + +/** + * @brief Setting symmetric crypto context type + * + * @param ctx Symmetric crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + return rt_hwcrypto_set_type(ctx, type); +} diff --git a/components/drivers/hwcrypto/hw_symmetric.h b/components/drivers/hwcrypto/hw_symmetric.h new file mode 100644 index 0000000000..12f4dbec30 --- /dev/null +++ b/components/drivers/hwcrypto/hw_symmetric.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_SYMMETRIC_H__ +#define __HW_SYMMETRIC_H__ + +#include <hwcrypto.h> + +#ifndef RT_HWCRYPTO_IV_MAX_SIZE +#define RT_HWCRYPTO_IV_MAX_SIZE (16) +#endif +#ifndef RT_HWCRYPTO_KEYBIT_MAX_SIZE +#define RT_HWCRYPTO_KEYBIT_MAX_SIZE (256) +#endif + +#define SYMMTRIC_MODIFY_KEY (0x1 << 0) +#define SYMMTRIC_MODIFY_IV (0x1 << 1) +#define SYMMTRIC_MODIFY_IVOFF (0x1 << 2) + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_symmetric; +struct hwcrypto_symmetric_info; + +struct hwcrypto_symmetric_ops +{ + rt_err_t (*crypt)(struct hwcrypto_symmetric *symmetric_ctx, + struct hwcrypto_symmetric_info *symmetric_info); /**< Hardware Symmetric Encryption and Decryption Callback */ +}; + +/** + * @brief Hardware driver usage, including input and output information + */ +struct hwcrypto_symmetric_info +{ + hwcrypto_mode mode; /**< crypto mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT */ + const rt_uint8_t *in; /**< Input data */ + rt_uint8_t *out; /**< Output data will be written */ + rt_size_t length; /**< The length of the input data in Bytes. It's a multiple of block size. */ +}; + +/** + * @brief Symmetric crypto context. Hardware driver usage + */ +struct hwcrypto_symmetric +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + rt_uint32_t flags; /**< key or iv or ivoff has been changed. The flag will be set up */ + rt_int32_t iv_len; /**< initialization vector effective length */ + rt_int32_t iv_off; /**< The offset in IV */ + rt_uint8_t iv[RT_HWCRYPTO_IV_MAX_SIZE]; /**< The initialization vector */ + rt_uint8_t key[RT_HWCRYPTO_KEYBIT_MAX_SIZE >> 3]; /**< The crypto key */ + rt_int32_t key_bitlen; /**< The crypto key bit length */ + const struct hwcrypto_symmetric_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating Symmetric Encryption and Decryption Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return Symmetric crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device *device, + hwcrypto_type type); + +/** + * @brief Destroy Symmetric Encryption and Decryption Context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx Symmetric crypto context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out); + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +int rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +int rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Set offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off); + +/** + * @brief Get offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off); + +/** + * @brief This function copy symmetric crypto context + * + * @param des The destination symmetric crypto context + * @param src The symmetric crypto context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset symmetric crypto context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting symmetric crypto context type + * + * @param ctx Symmetric crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hwcrypto.c b/components/drivers/hwcrypto/hwcrypto.c new file mode 100644 index 0000000000..bbe1ff63fb --- /dev/null +++ b/components/drivers/hwcrypto/hwcrypto.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hwcrypto.h> + +/** + * @brief Setting context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + if (ctx) + { + /* Is it the same category? */ + if ((ctx->type & HWCRYPTO_MAIN_TYPE_MASK) == (type & HWCRYPTO_MAIN_TYPE_MASK)) + { + ctx->type = type; + return RT_EOK; + } + /* Context is empty type */ + else if (ctx->type == HWCRYPTO_TYPE_NULL) + { + ctx->type = type; + return RT_EOK; + } + else + { + return -RT_ERROR; + } + } + return -RT_EINVAL; +} + +/** + * @brief Reset context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * + */ +void rt_hwcrypto_ctx_reset(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx && ctx->device->ops->reset) + { + ctx->device->ops->reset(ctx); + } +} + +/** + * @brief Init crypto context + * + * @param ctx The context to initialize + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_init(struct rt_hwcrypto_ctx *ctx, struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + rt_err_t err; + + /* Setting context type */ + rt_hwcrypto_set_type(ctx, type); + ctx->device = device; + /* Create hardware context */ + err = ctx->device->ops->create(ctx); + if (err != RT_EOK) + { + return err; + } + return RT_EOK; +} + +/** + * @brief Create crypto context + * + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return Crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_ctx_create(struct rt_hwcrypto_device *device, hwcrypto_type type, rt_uint32_t obj_size) +{ + struct rt_hwcrypto_ctx *ctx; + rt_err_t err; + + /* Parameter checking */ + if (device == RT_NULL || obj_size < sizeof(struct rt_hwcrypto_ctx)) + { + return RT_NULL; + } + ctx = rt_malloc(obj_size); + if (ctx == RT_NULL) + { + return ctx; + } + rt_memset(ctx, 0, obj_size); + /* Init context */ + err = rt_hwcrypto_ctx_init(ctx, device, type); + if (err != RT_EOK) + { + rt_free(ctx); + ctx = RT_NULL; + } + return ctx; +} + +/** + * @brief Destroy crypto context + * + * @param device Crypto context + */ +void rt_hwcrypto_ctx_destroy(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx == RT_NULL) + { + return; + } + /* Destroy hardware context */ + if (ctx->device->ops->destroy) + { + ctx->device->ops->destroy(ctx); + } + /* Free the resources */ + rt_free(ctx); +} + +/** + * @brief Copy crypto context + * + * @param des The destination context + * @param src The context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + if (des == RT_NULL || src == RT_NULL) + { + return -RT_EINVAL; + } + + /* The equipment is different or of different types and cannot be copied */ + if (des->device != src->device || + (des->type & HWCRYPTO_MAIN_TYPE_MASK) != (src->type & HWCRYPTO_MAIN_TYPE_MASK)) + { + return -RT_EINVAL; + } + des->type = src->type; + /* Calling Hardware Context Copy Function */ + return src->device->ops->copy(des, src); +} + +/** + * @brief Get the default hardware crypto device + * + * @return Hardware crypto device + * + */ +struct rt_hwcrypto_device *rt_hwcrypto_dev_default(void) +{ + static struct rt_hwcrypto_device *hwcrypto_dev; + + /* If there is a default device, return the device */ + if (hwcrypto_dev) + { + return hwcrypto_dev; + } + /* Find by default device name */ + hwcrypto_dev = (struct rt_hwcrypto_device *)rt_device_find(RT_HWCRYPTO_DEFAULT_NAME); + return hwcrypto_dev; +} + +/** + * @brief Get the unique ID of the device + * + * @param device Device object + * + * @return Device unique ID + */ +rt_uint64_t rt_hwcrypto_id(struct rt_hwcrypto_device *device) +{ + if (device) + { + return device->id; + } + return 0; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops hwcrypto_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL +}; +#endif + +/** + * @brief Register hardware crypto device + * + * @param device Hardware crypto device + * @param name Name of device + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_register(struct rt_hwcrypto_device *device, const char *name) +{ + rt_err_t err; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(name != RT_NULL); + RT_ASSERT(device->ops != RT_NULL); + RT_ASSERT(device->ops->create != RT_NULL); + RT_ASSERT(device->ops->destroy != RT_NULL); + RT_ASSERT(device->ops->copy != RT_NULL); + RT_ASSERT(device->ops->reset != RT_NULL); + + rt_memset(&device->parent, 0, sizeof(struct rt_device)); +#ifdef RT_USING_DEVICE_OPS + device->parent.ops = &hwcrypto_ops; +#else + device->parent.init = RT_NULL; + device->parent.open = RT_NULL; + device->parent.close = RT_NULL; + device->parent.read = RT_NULL; + device->parent.write = RT_NULL; + device->parent.control = RT_NULL; +#endif + + device->parent.user_data = RT_NULL; + device->parent.type = RT_Device_Class_Miscellaneous; + + /* Register device */ + err = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + + return err; +} diff --git a/components/drivers/hwcrypto/hwcrypto.h b/components/drivers/hwcrypto/hwcrypto.h new file mode 100644 index 0000000000..a428f4437d --- /dev/null +++ b/components/drivers/hwcrypto/hwcrypto.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#ifndef __HWCRYPTO_H__ +#define __HWCRYPTO_H__ + +#include <rtthread.h> + +#ifndef RT_HWCRYPTO_DEFAULT_NAME +#define RT_HWCRYPTO_DEFAULT_NAME ("hwcryto") +#endif + +#define HWCRYPTO_MAIN_TYPE_MASK (0xffffUL << 16) +#define HWCRYPTO_SUB_TYPE_MASK (0xffUL << 8) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + HWCRYPTO_TYPE_NULL = 0x00000000, + + /* Main Type */ + /* symmetric Type */ + HWCRYPTO_TYPE_HEAD = __LINE__, + HWCRYPTO_TYPE_AES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< AES */ + HWCRYPTO_TYPE_DES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< DES */ + HWCRYPTO_TYPE_3DES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< 3DES */ + HWCRYPTO_TYPE_RC4 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< RC4 */ + HWCRYPTO_TYPE_GCM = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< GCM */ + /* HASH Type */ + HWCRYPTO_TYPE_MD5 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< MD5 */ + HWCRYPTO_TYPE_SHA1 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< SHA1 */ + HWCRYPTO_TYPE_SHA2 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< SHA2 */ + /* Other Type */ + HWCRYPTO_TYPE_RNG = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< RNG */ + HWCRYPTO_TYPE_CRC = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< CRC */ + HWCRYPTO_TYPE_BIGNUM = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< BIGNUM */ + + /* AES Subtype */ + HWCRYPTO_TYPE_AES_ECB = HWCRYPTO_TYPE_AES | (0x01 << 8), + HWCRYPTO_TYPE_AES_CBC = HWCRYPTO_TYPE_AES | (0x02 << 8), + HWCRYPTO_TYPE_AES_CFB = HWCRYPTO_TYPE_AES | (0x03 << 8), + HWCRYPTO_TYPE_AES_CTR = HWCRYPTO_TYPE_AES | (0x04 << 8), + HWCRYPTO_TYPE_AES_OFB = HWCRYPTO_TYPE_AES | (0x05 << 8), + + /* DES Subtype */ + HWCRYPTO_TYPE_DES_ECB = HWCRYPTO_TYPE_DES | (0x01 << 8), + HWCRYPTO_TYPE_DES_CBC = HWCRYPTO_TYPE_DES | (0x02 << 8), + + /* 3DES Subtype */ + HWCRYPTO_TYPE_3DES_ECB = HWCRYPTO_TYPE_3DES | (0x01 << 8), + HWCRYPTO_TYPE_3DES_CBC = HWCRYPTO_TYPE_3DES | (0x02 << 8), + + /* SHA2 Subtype */ + HWCRYPTO_TYPE_SHA224 = HWCRYPTO_TYPE_SHA2 | (0x01 << 8), + HWCRYPTO_TYPE_SHA256 = HWCRYPTO_TYPE_SHA2 | (0x02 << 8), + HWCRYPTO_TYPE_SHA384 = HWCRYPTO_TYPE_SHA2 | (0x03 << 8), + HWCRYPTO_TYPE_SHA512 = HWCRYPTO_TYPE_SHA2 | (0x04 << 8), +} hwcrypto_type; + +typedef enum +{ + HWCRYPTO_MODE_ENCRYPT = 0x1, /**< Encryption operations */ + HWCRYPTO_MODE_DECRYPT = 0x2, /**< Decryption operations */ + HWCRYPTO_MODE_UNKNOWN = 0x7fffffff, /**< Unknown */ +} hwcrypto_mode; + +struct rt_hwcrypto_ctx; + +struct rt_hwcrypto_ops +{ + rt_err_t (*create)(struct rt_hwcrypto_ctx *ctx); /**< Creating hardware context */ + void (*destroy)(struct rt_hwcrypto_ctx *ctx); /**< Delete hardware context */ + rt_err_t (*copy)(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src); /**< Cpoy hardware context */ + void (*reset)(struct rt_hwcrypto_ctx *ctx); /**< Reset hardware context */ +}; + +struct rt_hwcrypto_device +{ + struct rt_device parent; /**< Inherited from the standard device */ + const struct rt_hwcrypto_ops *ops; /**< Hardware crypto ops */ + rt_uint64_t id; /**< Unique id */ + void *user_data; /**< Device user data */ +}; + +struct rt_hwcrypto_ctx +{ + struct rt_hwcrypto_device *device; /**< Binding device */ + hwcrypto_type type; /**< Encryption and decryption types */ + void *contex; /**< Hardware context */ +}; + +/** + * @brief Setting context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +/** + * @brief Reset context type (Direct calls are not recommended) + * + * @param ctx Crypto context + */ +void rt_hwcrypto_ctx_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Init crypto context (Direct calls are not recommended) + * + * @param ctx The context to initialize + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_init(struct rt_hwcrypto_ctx *ctx, + struct rt_hwcrypto_device *device, hwcrypto_type type); + +/** + * @brief Create crypto context (Direct calls are not recommended) + * + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return Crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_ctx_create(struct rt_hwcrypto_device *device, + hwcrypto_type type, rt_uint32_t obj_size); + +/** + * @brief Destroy crypto context (Direct calls are not recommended) + * + * @param device Crypto context + */ +void rt_hwcrypto_ctx_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Copy crypto context (Direct calls are not recommended) + * + * @param des The destination context + * @param src The context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Register hardware crypto device + * + * @param device Hardware crypto device + * @param name Name of device + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_register(struct rt_hwcrypto_device *device, const char *name); + +/** + * @brief Get the default hardware crypto device + * + * @return Hardware crypto device + * + */ +struct rt_hwcrypto_device *rt_hwcrypto_dev_default(void); + +/** + * @brief Get the unique ID of the device + * + * @param device Device object + * + * @return Device unique ID + */ +rt_uint64_t rt_hwcrypto_id(struct rt_hwcrypto_device *device); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwtimer/README_CN.md b/components/drivers/hwtimer/README_CN.md index fb3b4fa60a..810b1b1d80 100644 --- a/components/drivers/hwtimer/README_CN.md +++ b/components/drivers/hwtimer/README_CN.md @@ -1,17 +1,16 @@ -定时器设备 -=== - -##功能 ---- +# 定时器设备 + +## 功能 + * 时间测量 * 周期或单次执行回调函数 -##编译 ---- +## 编译 + 1. 在rtconfig.h添加 `#define RT_USING_HWTIMER` - -##使用流程 ---- + +## 使用流程 + 1. 以读写方式打开设备 2. 设置超时回调函数(如果需要) 3. 根据需要设置定时模式(单次/周期) @@ -19,12 +18,12 @@ 5. 写入超时值,定时器随即启动 6. 停止定时器(可选) 7. 关闭设备(如果需要) - + 应用参考 [hwtimer_test] (/examples/test/hwtimer\_test.c) -##驱动编写指南 ---- -###操作接口 +## 驱动编写指南 + +### 操作接口 ``` struct rt_hwtimer_ops @@ -43,8 +42,8 @@ struct rt_hwtimer_ops * count_get - <读取计数器值> * control - <设置计数频率 > -###定时器特征信息 - +### 定时器特征信息 + ``` struct rt_hwtimer_info { @@ -60,7 +59,8 @@ struct rt_hwtimer_info * maxcnt <计数器最大计数值> * cntmode <递增计数/递减计数> -###注册设备 +### 注册设备 + ``` static rt_hwtimer_t _timer0; int stm32_hwtimer_init(void) @@ -73,8 +73,9 @@ int stm32_hwtimer_init(void) return 0; } ``` - -###定时器中断 + +### 定时器中断 + ``` void timer_irq_handler(void) { @@ -84,15 +85,13 @@ void timer_irq_handler(void) } ``` -##注意事项 ---- - -<font color="#FF0000">可能出现定时误差</font> - +## 注意事项 + +**可能出现定时误差** 误差原因: 假设计数器最大值0xFFFF,计数频率1Mhz,定时时间1秒又1微秒。 - + 由于定时器一次最多只能计时到65535us,对于1000001us的定时要求。 可以50000us定时20次完成,此时将会出现计算误差1us。 diff --git a/components/drivers/hwtimer/hwtimer.c b/components/drivers/hwtimer/hwtimer.c index cd85b3baef..3953919fae 100644 --- a/components/drivers/hwtimer/hwtimer.c +++ b/components/drivers/hwtimer/hwtimer.c @@ -153,7 +153,7 @@ static rt_size_t rt_hwtimer_read(struct rt_device *dev, rt_off_t pos, void *buff cnt = timer->ops->count_get(timer); if (timer->info->cntmode == HWTIMER_CNTMODE_DW) { - cnt = timer->info->maxcnt - cnt; + cnt = (timer->freq * timer->period_sec) - cnt; } t = timer->overflow * timer->period_sec + cnt/(float)timer->freq; @@ -255,6 +255,7 @@ static rt_err_t rt_hwtimer_control(struct rt_device *dev, int cmd, void *args) *((struct rt_hwtimer_info*)args) = *timer->info; } + break; case HWTIMER_CTRL_MODE_SET: { rt_hwtimer_mode_t *m; diff --git a/components/drivers/i2c/fm24clxx.c b/components/drivers/i2c/fm24clxx.c deleted file mode 100644 index eecf3d455a..0000000000 --- a/components/drivers/i2c/fm24clxx.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-07-14 aubr.cool 1st version - */ -#include <rtthread.h> -#include <rtdevice.h> -#include "fm24clxx.h" - -struct fm24clxx_device -{ - struct rt_device parent; - struct rt_i2c_bus_device *bus; -}; - -/* RT-Thread device interface */ - -static rt_err_t fm24clxx_init(rt_device_t dev) -{ - return RT_EOK; -} -static rt_err_t fm24clxx_open(rt_device_t dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t fm24clxx_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t fm24clxx_control(rt_device_t dev, int cmd, void *args) -{ - return RT_EOK; -} - -static rt_size_t fm24clxx_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) -{ - struct fm24clxx_device *fm24clxx; - const struct fm24clxx_config *cfg; - struct rt_i2c_msg msg[2]; - rt_uint8_t mem_addr[2] = {0,}; - rt_size_t ret = 0; - RT_ASSERT(dev != 0); - - fm24clxx = (struct fm24clxx_device *) dev; - - RT_ASSERT(fm24clxx->parent.user_data != 0); - cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; - - if(pos > cfg->size) - { - return 0; - } - - if(pos + size > cfg->size) - { - size = cfg->size - pos; - } - - msg[0].addr = cfg->addr; - msg[0].flags = cfg->flags | RT_I2C_WR; - mem_addr[0] = (pos >> 8); - mem_addr[1] = (rt_uint8_t) pos; - msg[0].buf = (rt_uint8_t *) mem_addr; - msg[0].len = 2; - - msg[1].addr = cfg->addr; - msg[1].flags = cfg->flags | RT_I2C_RD; - msg[1].buf = (rt_uint8_t *) buffer; - msg[1].len = size; - - ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); - return (ret == 2) ? size : 0; -} - -static rt_size_t fm24clxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) -{ - struct fm24clxx_device *fm24clxx; - const struct fm24clxx_config *cfg; - struct rt_i2c_msg msg[2]; - rt_uint8_t mem_addr[2] = {0,}; - rt_size_t ret = 0; - RT_ASSERT(dev != 0); - - fm24clxx = (struct fm24clxx_device *) dev; - - RT_ASSERT(fm24clxx->parent.user_data != 0); - cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; - - if(pos > cfg->size) - { - return 0; - } - - if(pos + size > cfg->size) - { - size = cfg->size - pos; - } - - msg[0].addr = cfg->addr; - msg[0].flags = cfg->flags | RT_I2C_WR; - mem_addr[0] = (pos >> 8); - mem_addr[1] = (rt_uint8_t) pos; - msg[0].buf = (rt_uint8_t *) mem_addr; - msg[0].len = 2; - - msg[1].addr = cfg->addr; - msg[1].flags = cfg->flags | RT_I2C_WR | RT_I2C_NO_START; - msg[1].buf = (rt_uint8_t *) buffer; - msg[1].len = size; - - ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); - return (ret == 2) ? size : 0; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device fm24clxx_ops = -{ - fm24clxx_init, - fm24clxx_open, - fm24clxx_close, - fm24clxx_read, - fm24clxx_write, - fm24clxx_control -}; -#endif - -rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void *user_data) -{ - static struct fm24clxx_device fm24clxx_drv; - struct rt_i2c_bus_device *bus; - - bus = rt_i2c_bus_device_find(i2c_bus); - if (bus == RT_NULL) - { - return RT_ENOSYS; - } - - fm24clxx_drv.bus = bus; - fm24clxx_drv.parent.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - fm24clxx_drv.parent.ops = &fm24clxx_ops; -#else - fm24clxx_drv.parent.init = fm24clxx_init; - fm24clxx_drv.parent.open = fm24clxx_open; - fm24clxx_drv.parent.close = fm24clxx_close; - fm24clxx_drv.parent.read = fm24clxx_read; - fm24clxx_drv.parent.write = fm24clxx_write; - fm24clxx_drv.parent.control = fm24clxx_control; -#endif - - fm24clxx_drv.parent.user_data = user_data; - - return rt_device_register(&fm24clxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR); -}
\ No newline at end of file diff --git a/components/drivers/i2c/fm24clxx.h b/components/drivers/i2c/fm24clxx.h deleted file mode 100644 index 74ee065470..0000000000 --- a/components/drivers/i2c/fm24clxx.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-07-14 aubr.cool 1st version - */ - -#ifndef __FM24CLXX_H__ -#define __FM24CLXX_H__ - -#include <rtthread.h> - -struct fm24clxx_config -{ - rt_uint32_t size; - rt_uint16_t addr; - rt_uint16_t flags; -}; - -extern rt_err_t fm24clxx_register(const char *e2m_device_name, - const char *i2c_bus, void *user_data); - -#endif /*__FM24CLXX_H__*/
\ No newline at end of file diff --git a/components/drivers/i2c/i2c-bit-ops.c b/components/drivers/i2c/i2c-bit-ops.c index 26479a1d68..99338eef54 100644 --- a/components/drivers/i2c/i2c-bit-ops.c +++ b/components/drivers/i2c/i2c-bit-ops.c @@ -10,11 +10,13 @@ #include <rtdevice.h> -#ifdef RT_I2C_BIT_DEBUG -#define bit_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) +#define DBG_TAG "I2C" +#ifdef RT_I2C_BITOPS_DEBUG +#define DBG_LVL DBG_LOG #else -#define bit_dbg(fmt, ...) +#define DBG_LVL DBG_INFO #endif +#include <rtdbg.h> #define SET_SDA(ops, val) ops->set_sda(ops->data, val) #define SET_SCL(ops, val) ops->set_scl(ops->data, val) @@ -54,11 +56,11 @@ static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops) return -RT_ETIMEOUT; rt_thread_delay((ops->timeout + 1) >> 1); } -#ifdef RT_I2C_BIT_DEBUG +#ifdef RT_I2C_BITOPS_DEBUG if (rt_tick_get() != start) { - bit_dbg("wait %ld tick for SCL line to go high\n", - rt_tick_get() - start); + LOG_D("wait %ld tick for SCL line to go high", + rt_tick_get() - start); } #endif @@ -70,14 +72,14 @@ done: static void i2c_start(struct rt_i2c_bit_ops *ops) { -#ifdef RT_I2C_BIT_DEBUG +#ifdef RT_I2C_BITOPS_DEBUG if (ops->get_scl && !GET_SCL(ops)) { - bit_dbg("I2C bus error, SCL line low\n"); + LOG_E("I2C bus error, SCL line low"); } if (ops->get_sda && !GET_SDA(ops)) { - bit_dbg("I2C bus error, SDA line low\n"); + LOG_E("I2C bus error, SDA line low"); } #endif SDA_L(ops); @@ -114,13 +116,13 @@ rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops) if (SCL_H(ops) < 0) { - bit_dbg("wait ack timeout\n"); + LOG_W("wait ack timeout"); return -RT_ETIMEOUT; } ack = !GET_SDA(ops); /* ACK : SDA pin is pulled low */ - bit_dbg("%s\n", ack ? "ACK" : "NACK"); + LOG_D("%s", ack ? "ACK" : "NACK"); SCL_L(ops); @@ -132,7 +134,7 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) rt_int32_t i; rt_uint8_t bit; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; for (i = 7; i >= 0; i--) { @@ -142,8 +144,8 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) i2c_delay(ops); if (SCL_H(ops) < 0) { - bit_dbg("i2c_writeb: 0x%02x, " - "wait scl pin high timeout at bit %d\n", + LOG_D("i2c_writeb: 0x%02x, " + "wait scl pin high timeout at bit %d", data, i); return -RT_ETIMEOUT; @@ -159,7 +161,7 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) { rt_uint8_t i; rt_uint8_t data = 0; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; SDA_H(ops); i2c_delay(ops); @@ -169,8 +171,8 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) if (SCL_H(ops) < 0) { - bit_dbg("i2c_readb: wait scl pin high " - "timeout at bit %d\n", 7 - i); + LOG_D("i2c_readb: wait scl pin high " + "timeout at bit %d", 7 - i); return -RT_ETIMEOUT; } @@ -205,13 +207,13 @@ static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, } else if (ret == 0) { - i2c_dbg("send bytes: NACK.\n"); + LOG_D("send bytes: NACK."); return 0; } else { - i2c_dbg("send bytes: error %d\n", ret); + LOG_E("send bytes: error %d", ret); return ret; } @@ -222,14 +224,14 @@ static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus_device *bus, int ack) { - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; if (ack) SET_SDA(ops, 0); i2c_delay(ops); if (SCL_H(ops) < 0) { - bit_dbg("ACK or NACK timeout\n"); + LOG_E("ACK or NACK timeout."); return -RT_ETIMEOUT; } @@ -263,7 +265,7 @@ static rt_size_t i2c_recv_bytes(struct rt_i2c_bus_device *bus, ptr ++; count --; - bit_dbg("recieve bytes: 0x%02x, %s\n", + LOG_D("recieve bytes: 0x%02x, %s", val, (flags & RT_I2C_NO_READ_ACK) ? "(No ACK/NACK)" : (count ? "ACK" : "NACK")); @@ -282,7 +284,7 @@ static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, rt_uint8_t addr, rt_int32_t retries) { - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_int32_t i; rt_err_t ret = 0; @@ -291,10 +293,10 @@ static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, ret = i2c_writeb(bus, addr); if (ret == 1 || i == retries) break; - bit_dbg("send stop condition\n"); + LOG_D("send stop condition"); i2c_stop(ops); i2c_delay2(ops); - bit_dbg("send start condition\n"); + LOG_D("send start condition"); i2c_start(ops); } @@ -306,7 +308,7 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, { rt_uint16_t flags = msg->flags; rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_uint8_t addr1, addr2; rt_int32_t retries; @@ -319,12 +321,12 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, addr1 = 0xf0 | ((msg->addr >> 7) & 0x06); addr2 = msg->addr & 0xff; - bit_dbg("addr1: %d, addr2: %d\n", addr1, addr2); + LOG_D("addr1: %d, addr2: %d", addr1, addr2); ret = i2c_send_address(bus, addr1, retries); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending first addr\n"); + LOG_W("NACK: sending first addr"); return -RT_EIO; } @@ -332,19 +334,19 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, ret = i2c_writeb(bus, addr2); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending second addr\n"); + LOG_W("NACK: sending second addr"); return -RT_EIO; } if (flags & RT_I2C_RD) { - bit_dbg("send repeated start condition\n"); + LOG_D("send repeated start condition"); i2c_restart(ops); addr1 |= 0x01; ret = i2c_send_address(bus, addr1, retries); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending repeated addr\n"); + LOG_E("NACK: sending repeated addr"); return -RT_EIO; } @@ -369,11 +371,11 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, rt_uint32_t num) { struct rt_i2c_msg *msg; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_int32_t i, ret; rt_uint16_t ignore_nack; - bit_dbg("send start condition\n"); + LOG_D("send start condition"); i2c_start(ops); for (i = 0; i < num; i++) { @@ -388,7 +390,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, ret = i2c_bit_send_address(bus, msg); if ((ret != RT_EOK) && !ignore_nack) { - bit_dbg("receive NACK from device addr 0x%02x msg %d\n", + LOG_D("receive NACK from device addr 0x%02x msg %d", msgs[i].addr, i); goto out; } @@ -397,7 +399,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, { ret = i2c_recv_bytes(bus, msg); if (ret >= 1) - bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s"); + LOG_D("read %d byte%s", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) @@ -409,7 +411,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, { ret = i2c_send_bytes(bus, msg); if (ret >= 1) - bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s"); + LOG_D("write %d byte%s", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) @@ -421,7 +423,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, ret = i; out: - bit_dbg("send stop condition\n"); + LOG_D("send stop condition"); i2c_stop(ops); return ret; diff --git a/components/drivers/i2c/i2c_core.c b/components/drivers/i2c/i2c_core.c index f245abb9ca..f358c2b758 100644 --- a/components/drivers/i2c/i2c_core.c +++ b/components/drivers/i2c/i2c_core.c @@ -10,6 +10,14 @@ #include <rtdevice.h> +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include <rtdbg.h> + rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name) { @@ -21,7 +29,7 @@ rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, res = rt_i2c_bus_device_device_init(bus, bus_name); - i2c_dbg("I2C bus [%s] registered\n", bus_name); + LOG_I("I2C bus [%s] registered", bus_name); return res; } @@ -32,7 +40,7 @@ struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name) rt_device_t dev = rt_device_find(bus_name); if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS) { - i2c_dbg("I2C bus %s not exist\n", bus_name); + LOG_E("I2C bus %s not exist", bus_name); return RT_NULL; } @@ -53,9 +61,9 @@ rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, #ifdef RT_I2C_DEBUG for (ret = 0; ret < num; ret++) { - i2c_dbg("msgs[%d] %c, addr=0x%02x, len=%d\n", ret, - (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', - msgs[ret].addr, msgs[ret].len); + LOG_D("msgs[%d] %c, addr=0x%02x, len=%d", ret, + (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', + msgs[ret].addr, msgs[ret].len); } #endif @@ -67,7 +75,7 @@ rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, } else { - i2c_dbg("I2C bus operation not supported\n"); + LOG_E("I2C bus operation not supported"); return 0; } @@ -83,7 +91,7 @@ rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msg; msg.addr = addr; - msg.flags = flags & RT_I2C_ADDR_10BIT; + msg.flags = flags; msg.len = count; msg.buf = (rt_uint8_t *)buf; @@ -103,8 +111,7 @@ rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, RT_ASSERT(bus != RT_NULL); msg.addr = addr; - msg.flags = flags & RT_I2C_ADDR_10BIT; - msg.flags |= RT_I2C_RD; + msg.flags = flags | RT_I2C_RD; msg.len = count; msg.buf = buf; diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c index 6c7df8e427..59f728be09 100644 --- a/components/drivers/i2c/i2c_dev.c +++ b/components/drivers/i2c/i2c_dev.c @@ -11,6 +11,14 @@ #include <rtdevice.h> +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include <rtdbg.h> + static rt_size_t i2c_bus_device_read(rt_device_t dev, rt_off_t pos, void *buffer, @@ -23,12 +31,12 @@ static rt_size_t i2c_bus_device_read(rt_device_t dev, RT_ASSERT(bus != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", dev->parent.name, count); + LOG_D("I2C bus dev [%s] reading %u bytes.", dev->parent.name, count); addr = pos & 0xffff; flags = (pos >> 16) & 0xffff; - return rt_i2c_master_recv(bus, addr, flags, buffer, count); + return rt_i2c_master_recv(bus, addr, flags, (rt_uint8_t *)buffer, count); } static rt_size_t i2c_bus_device_write(rt_device_t dev, @@ -43,12 +51,12 @@ static rt_size_t i2c_bus_device_write(rt_device_t dev, RT_ASSERT(bus != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev [%s] writing %u bytes.\n", dev->parent.name, count); + LOG_D("I2C bus dev [%s] writing %u bytes.", dev->parent.name, count); addr = pos & 0xffff; flags = (pos >> 16) & 0xffff; - return rt_i2c_master_send(bus, addr, flags, buffer, count); + return rt_i2c_master_send(bus, addr, flags, (const rt_uint8_t *)buffer, count); } static rt_err_t i2c_bus_device_control(rt_device_t dev, diff --git a/components/drivers/include/drivers/alarm.h b/components/drivers/include/drivers/alarm.h index b5ebbc86d9..dd59f4c1e8 100644 --- a/components/drivers/include/drivers/alarm.h +++ b/components/drivers/include/drivers/alarm.h @@ -6,6 +6,8 @@ * Change Logs: * Date Author Notes * 2012-10-27 heyuanjie87 first version. + * 2013-05-17 aozima initial alarm event & mutex in system init. + * 2020-10-15 zhangsz add alarm flags hour minute second. */ #ifndef __ALARM_H__ @@ -22,6 +24,9 @@ #define RT_ALARM_WEEKLY 0x200 /* alarm weekly at Monday or Friday etc. */ #define RT_ALARM_MONTHLY 0x400 /* alarm monthly at someday */ #define RT_ALARM_YAERLY 0x800 /* alarm yearly at a certain date */ +#define RT_ALARM_HOUR 0x1000 /* alarm each hour at a certain min:second */ +#define RT_ALARM_MINUTE 0x2000 /* alarm each minute at a certain second */ +#define RT_ALARM_SECOND 0x4000 /* alarm each second */ /* alarm control cmd */ #define RT_ALARM_CTRL_MODIFY 1 /* modify alarm time or alarm flag */ @@ -67,6 +72,6 @@ void rt_alarm_update(rt_device_t dev, rt_uint32_t event); rt_err_t rt_alarm_delete(rt_alarm_t alarm); rt_err_t rt_alarm_start(rt_alarm_t alarm); rt_err_t rt_alarm_stop(rt_alarm_t alarm); -void rt_alarm_system_init(void); +int rt_alarm_system_init(void); #endif /* __ALARM_H__ */ diff --git a/components/drivers/include/drivers/audio.h b/components/drivers/include/drivers/audio.h index 7d2cb36728..86057e7626 100644 --- a/components/drivers/include/drivers/audio.h +++ b/components/drivers/include/drivers/audio.h @@ -5,52 +5,30 @@ * * Change Logs: * Date Author Notes - * 2017-05-09 Urey first version + * 2017-05-09 Urey first version + * 2019-07-09 Zero-Free improve device ops interface and data flows + * */ #ifndef __AUDIO_H__ #define __AUDIO_H__ +#include "audio_pipe.h" + /* AUDIO command */ #define _AUDIO_CTL(a) (0x10 + a) #define AUDIO_CTL_GETCAPS _AUDIO_CTL(1) #define AUDIO_CTL_CONFIGURE _AUDIO_CTL(2) -#define AUDIO_CTL_SHUTDOWN _AUDIO_CTL(3) -#define AUDIO_CTL_START _AUDIO_CTL(4) -#define AUDIO_CTL_STOP _AUDIO_CTL(5) -#define AUDIO_CTL_PAUSE _AUDIO_CTL(6) -#define AUDIO_CTL_RESUME _AUDIO_CTL(7) -#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(8) -#define AUDIO_CTL_ALLOCBUFFER _AUDIO_CTL(9) -#define AUDIO_CTL_FREEBUFFER _AUDIO_CTL(10) -#define AUDIO_CTL_HWRESET _AUDIO_CTL(11) - +#define AUDIO_CTL_START _AUDIO_CTL(3) +#define AUDIO_CTL_STOP _AUDIO_CTL(4) +#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(5) /* Audio Device Types */ #define AUDIO_TYPE_QUERY 0x00 #define AUDIO_TYPE_INPUT 0x01 #define AUDIO_TYPE_OUTPUT 0x02 #define AUDIO_TYPE_MIXER 0x04 -#define AUDIO_TYPE_SELECTOR 0x08 -#define AUDIO_TYPE_EFFECT 0x10 - -/* Audio Format Types */ -#define AUDIO_FMT_PCM_U8 0x0001 -#define AUDIO_FMT_PCM_S8 0x0002 - -#define AUDIO_FMT_PCM_U16_LE 0x0010 -#define AUDIO_FMT_PCM_S16_BE 0x0020 -#define AUDIO_FMT_PCM_S16_LE 0x0040 -#define AUDIO_FMT_PCM_U16_BE 0x0080 -#define AUDIO_FMT_PCM_U24_LE 0x0100 -#define AUDIO_FMT_PCM_S24_BE 0x0200 -#define AUDIO_FMT_PCM_S24_LE 0x0400 -#define AUDIO_FMT_PCM_U24_BE 0x0800 -#define AUDIO_FMT_PCM_U32_LE 0x1000 -#define AUDIO_FMT_PCM_S32_BE 0x2000 -#define AUDIO_FMT_PCM_S32_LE 0x4000 -#define AUDIO_FMT_PCM_U32_BE 0x8000 /* Supported Sampling Rates */ #define AUDIO_SAMP_RATE_8K 0x0001 @@ -76,13 +54,11 @@ #define AUDIO_BIT_RATE_172K 0x40 #define AUDIO_BIT_RATE_192K 0x80 - - /* Support Dsp(input/output) Units controls */ #define AUDIO_DSP_PARAM 0 /* get/set all params */ -#define AUDIO_DSP_SAMPLERATE 1 /* 采样频率 */ -#define AUDIO_DSP_FMT 2 -#define AUDIO_DSP_CHANNELS 3 +#define AUDIO_DSP_SAMPLERATE 1 /* samplerate */ +#define AUDIO_DSP_CHANNELS 2 /* channels */ +#define AUDIO_DSP_SAMPLEBITS 3 /* sample bits width */ /* Supported Mixer Units controls */ #define AUDIO_MIXER_QUERY 0x0000 @@ -95,15 +71,13 @@ #define AUDIO_MIXER_LINE 0x0040 #define AUDIO_MIXER_DIGITAL 0x0080 #define AUDIO_MIXER_MIC 0x0100 +#define AUDIO_MIXER_VITURAL 0x0200 +#define AUDIO_MIXER_EXTEND 0x8000 /* extend mixer command */ -#define AUDIO_MIXER_EXTEND 0x8000 //extend mixer command +#define AUDIO_VOLUME_MAX (100) +#define AUDIO_VOLUME_MIN (0) #define CFG_AUDIO_REPLAY_QUEUE_COUNT 4 -#define CFG_AUDIO_RECORD_PIPE_SIZE (8 * 1024) -#define AUDIO_DEVICE_MP_CNT (4) -#define AUDIO_DEVICE_DECODE_MP_BLOCK_SZ (4352 * 4) -#define AUDIO_DEVICE_DECODE_MP_SZ ((AUDIO_DEVICE_DECODE_MP_BLOCK_SZ*2 + 4)*AUDIO_DEVICE_MP_CNT) - enum { @@ -115,19 +89,10 @@ enum /* the preferred number and size of audio pipeline buffer for the audio device */ struct rt_audio_buf_info { - rt_uint32_t buffer_size; /* Preferred qty of buffers */ - rt_uint32_t buffer_count; /* Preferred size of the buffers */ -}; -struct rt_audio_buf_desc -{ - rt_uint8_t *data_ptr; - rt_size_t data_size; -}; - -struct rt_audio_frame -{ - const void *data_ptr; - rt_size_t data_size; + rt_uint8_t *buffer; + rt_uint16_t block_size; + rt_uint16_t block_count; + rt_uint32_t total_size; }; struct rt_audio_device; @@ -135,73 +100,68 @@ struct rt_audio_caps; struct rt_audio_configure; struct rt_audio_ops { - rt_err_t (*getcaps) (struct rt_audio_device *audio,struct rt_audio_caps *caps); - rt_err_t (*configure) (struct rt_audio_device *audio,struct rt_audio_caps *caps); - - rt_err_t (*init) (struct rt_audio_device *audio); - rt_err_t (*shutdown) (struct rt_audio_device *audio); - rt_err_t (*start) (struct rt_audio_device *audio,int stream); - rt_err_t (*stop) (struct rt_audio_device *audio,int stream); - rt_err_t (*suspend) (struct rt_audio_device *audio,int stream); - rt_err_t (*resume) (struct rt_audio_device *audio,int stream); - - rt_err_t (*control) (struct rt_audio_device *audio, int cmd, void *arg); - rt_size_t (*transmit) (struct rt_audio_device *audio, const void *writeBuf,void *readBuf, rt_size_t size); - - //get page size of codec or private buffer's info - void (*buffer_info) (struct rt_audio_device *audio,struct rt_audio_buf_info *info ); + rt_err_t (*getcaps)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*configure)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*init)(struct rt_audio_device *audio); + rt_err_t (*start)(struct rt_audio_device *audio, int stream); + rt_err_t (*stop)(struct rt_audio_device *audio, int stream); + rt_size_t (*transmit)(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size); + /* get page size of codec or private buffer's info */ + void (*buffer_info)(struct rt_audio_device *audio, struct rt_audio_buf_info *info); }; - struct rt_audio_configure { - rt_uint32_t channels; - - rt_uint32_t samplefmt; rt_uint32_t samplerate; - rt_uint32_t samplefmts; + rt_uint16_t channels; + rt_uint16_t samplebits; }; struct rt_audio_caps { - int main_type; - int sub_type; + int main_type; + int sub_type; - union - { - rt_uint32_t mask; - int value; - struct rt_audio_configure config; - }udata; + union + { + rt_uint32_t mask; + int value; + struct rt_audio_configure config; + } udata; }; struct rt_audio_replay { - rt_bool_t activated; + struct rt_mempool *mp; struct rt_data_queue queue; + struct rt_mutex lock; + struct rt_completion cmp; + struct rt_audio_buf_info buf_info; + rt_uint8_t *write_data; + rt_uint16_t write_index; + rt_uint16_t read_index; + rt_uint32_t pos; + rt_uint8_t event; + rt_bool_t activated; }; struct rt_audio_record { + struct rt_audio_pipe pipe; rt_bool_t activated; }; struct rt_audio_device { - struct rt_device parent; + struct rt_device parent; struct rt_audio_ops *ops; - - struct rt_mempool mp; - struct rt_audio_replay *replay; struct rt_audio_record *record; }; -rt_err_t rt_audio_register (struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); -void rt_audio_tx_complete (struct rt_audio_device *audio,rt_uint8_t *pbuf); -void rt_audio_rx_done (struct rt_audio_device *audio,rt_uint8_t *pbuf,rt_size_t len); -rt_uint32_t rt_audio_format_to_bits (rt_uint32_t format); - +rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); +void rt_audio_tx_complete(struct rt_audio_device *audio); +void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len); /* Device Control Commands */ #define CODEC_CMD_RESET 0 diff --git a/components/drivers/include/drivers/can.h b/components/drivers/include/drivers/can.h index c61fb19eaa..d4fcc845b4 100644 --- a/components/drivers/include/drivers/can.h +++ b/components/drivers/include/drivers/can.h @@ -221,7 +221,7 @@ struct rt_can_msg rt_uint32_t rsv : 1; rt_uint32_t len : 8; rt_uint32_t priv : 8; - rt_uint32_t hdr : 8; + rt_int32_t hdr : 8; rt_uint32_t reserved : 8; rt_uint8_t data[8]; }; @@ -252,7 +252,7 @@ struct rt_can_rx_fifo #define RT_CAN_EVENT_RX_IND 0x01 /* Rx indication */ #define RT_CAN_EVENT_TX_DONE 0x02 /* Tx complete */ -#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx complete */ +#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx fail */ #define RT_CAN_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ #define RT_CAN_EVENT_RXOF_IND 0x06 /* Rx overflow */ @@ -278,7 +278,7 @@ struct rt_can_ops int (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno); }; -rt_err_t rt_hw_can_register(struct rt_can_device *can, +rt_err_t rt_hw_can_register(struct rt_can_device *can, const char *name, const struct rt_can_ops *ops, void *data); diff --git a/components/drivers/include/drivers/crypto.h b/components/drivers/include/drivers/crypto.h new file mode 100644 index 0000000000..5341d9ee48 --- /dev/null +++ b/components/drivers/include/drivers/crypto.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-17 tyx the first version + */ + +#ifndef __CRYPTO_H__ +#define __CRYPTO_H__ + +#include <rtthread.h> +#include <hwcrypto.h> +#include <hw_symmetric.h> +#include <hw_rng.h> +#include <hw_hash.h> +#include <hw_crc.h> +#include <hw_gcm.h> +#include <hw_bignum.h> + +#endif diff --git a/components/drivers/include/drivers/dac.h b/components/drivers/include/drivers/dac.h new file mode 100644 index 0000000000..b6043348dc --- /dev/null +++ b/components/drivers/include/drivers/dac.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-19 thread-liu the first version + */ + +#ifndef __DAC_H__ +#define __DAC_H__ +#include <rtthread.h> + +struct rt_dac_device; +struct rt_dac_ops +{ + rt_err_t (*disabled)(struct rt_dac_device *device, rt_uint32_t channel); + rt_err_t (*enabled)(struct rt_dac_device *device, rt_uint32_t channel); + rt_err_t (*convert)(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value); +}; + +struct rt_dac_device +{ + struct rt_device parent; + const struct rt_dac_ops *ops; +}; +typedef struct rt_dac_device *rt_dac_device_t; + +typedef enum +{ + RT_DAC_CMD_ENABLE, + RT_DAC_CMD_DISABLE, +} rt_dac_cmd_t; + +rt_err_t rt_hw_dac_register(rt_dac_device_t dac,const char *name, const struct rt_dac_ops *ops, const void *user_data); + +rt_uint32_t rt_dac_write(rt_dac_device_t dev, rt_uint32_t channel, rt_uint32_t value); +rt_err_t rt_dac_enable(rt_dac_device_t dev, rt_uint32_t channel); +rt_err_t rt_dac_disable(rt_dac_device_t dev, rt_uint32_t channel); + +#endif /* __dac_H__ */ diff --git a/components/drivers/include/drivers/i2c.h b/components/drivers/include/drivers/i2c.h index e2a9e7d0b8..17d57288cd 100644 --- a/components/drivers/include/drivers/i2c.h +++ b/components/drivers/include/drivers/i2c.h @@ -60,11 +60,12 @@ struct rt_i2c_bus_device void *priv; }; -#ifdef RT_I2C_DEBUG -#define i2c_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) -#else -#define i2c_dbg(fmt, ...) -#endif +struct rt_i2c_client +{ + struct rt_device parent; + struct rt_i2c_bus_device *bus; + rt_uint16_t client_addr; +}; rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name); diff --git a/components/drivers/include/drivers/mtd.h b/components/drivers/include/drivers/mtd.h deleted file mode 100644 index fb7ea4389d..0000000000 --- a/components/drivers/include/drivers/mtd.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTD_H__ -#define __MTD_H__ - -#include <rtthread.h> -#include <stddef.h> -#include <stdint.h> - -#define MTD_TYPE_NOR 1 -#define MTD_TYPE_NAND 2 - - /** - * MTD operation modes - * - * @MTD_OPM_PLACE_OOB: OOB data are placed at the given offset (default) - * @MTD_OPM_AUTO_OOB: OOB data are automatically placed at the free areas - * @MTD_OPM_RAW: data are transferred as-is, with no error correction; - */ -enum mtd_opm -{ - MTD_OPM_PLACE_OOB = 0, - MTD_OPM_AUTO_OOB = 1, - MTD_OPM_RAW = 2, -}; - -#ifndef loff_t -typedef long loff_t; -#endif - -struct mtd_oob_region -{ - uint8_t offset; - uint8_t length; -}; - -typedef struct mtd_info -{ - struct rt_device parent; - - const struct mtd_ops *ops; - - uint16_t oob_size; - uint16_t sector_size; /* Minimal writable flash unit size */ - uint32_t block_size:28; /* Erase size for the device */ - uint32_t type:4; - - size_t size; /* Total size of the MTD */ - loff_t offset; /* At which this MTD starts, from the beginning of the MEMORY */ - struct mtd_info *master; - - void *priv; -}rt_mtd_t; - -struct mtd_io_desc -{ - uint8_t mode; /* operation mode(enum mtd_opm) */ - uint8_t ooblen; /* number of oob bytes to write/read */ - uint8_t oobretlen; /* number of oob bytes written/read */ - uint8_t ooboffs; /* offset in the oob area */ - uint8_t *oobbuf; - - size_t datlen; /* number of data bytes to write/read */ - size_t datretlen; /* number of data bytes written/read */ - uint8_t *datbuf; /* if NULL only oob are read/written */ -}; - -struct mtd_ops -{ - int(*erase)(rt_mtd_t *mtd, loff_t addr, size_t len); /* return 0 if success */ - int(*read) (rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *ops); /* return 0 if success */ - int(*write) (rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *ops); /* return 0 if success */ - int(*isbad) (rt_mtd_t *mtd, uint32_t block); /* return 1 if bad, 0 not bad */ - int(*markbad) (rt_mtd_t *mtd, uint32_t block); /* return 0 if success */ -}; - -struct mtd_part -{ - const char *name; /* name of the MTD partion */ - loff_t offset; /* start addr of partion */ - size_t size; /* size of partion */ -}; - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size); -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc); -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc); -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len); -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len); -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block); - -rt_mtd_t* rt_mtd_get(const char *name); -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np); - -#endif diff --git a/components/drivers/include/drivers/mtd_nand.h b/components/drivers/include/drivers/mtd_nand.h index 8afed000dd..f7675aede6 100644 --- a/components/drivers/include/drivers/mtd_nand.h +++ b/components/drivers/include/drivers/mtd_nand.h @@ -21,13 +21,13 @@ struct rt_mtd_nand_driver_ops; #define RT_MTD_NAND_DEVICE(device) ((struct rt_mtd_nand_device*)(device)) -#define RT_MTD_EOK 0 /* NO error */ -#define RT_MTD_EECC 1 /* ECC error */ -#define RT_MTD_EBUSY 2 /* hardware busy */ -#define RT_MTD_EIO 3 /* generic IO issue */ -#define RT_MTD_ENOMEM 4 /* out of memory */ -#define RT_MTD_ESRC 5 /* source issue */ -#define RT_MTD_EECC_CORRECT 6 /* ECC error but correct */ +#define RT_MTD_EOK 0 /* NO error */ +#define RT_MTD_EECC 101 /* ECC error */ +#define RT_MTD_EBUSY 102 /* hardware busy */ +#define RT_MTD_EIO 103 /* generic IO issue */ +#define RT_MTD_ENOMEM 104 /* out of memory */ +#define RT_MTD_ESRC 105 /* source issue */ +#define RT_MTD_EECC_CORRECT 106 /* ECC error but correct */ struct rt_mtd_nand_device { @@ -41,77 +41,97 @@ struct rt_mtd_nand_device rt_uint32_t pages_per_block; /* The number of page a block */ rt_uint16_t block_total; + /* Only be touched by driver */ rt_uint32_t block_start; /* The start of available block*/ rt_uint32_t block_end; /* The end of available block */ /* operations interface */ - const struct rt_mtd_nand_driver_ops* ops; + const struct rt_mtd_nand_driver_ops *ops; }; struct rt_mtd_nand_driver_ops { - rt_err_t (*read_id) (struct rt_mtd_nand_device* device); + rt_err_t (*read_id)(struct rt_mtd_nand_device *device); - rt_err_t (*read_page)(struct rt_mtd_nand_device* device, + rt_err_t (*read_page)(struct rt_mtd_nand_device *device, rt_off_t page, - rt_uint8_t* data, rt_uint32_t data_len, - rt_uint8_t * spare, rt_uint32_t spare_len); + rt_uint8_t *data, rt_uint32_t data_len, + rt_uint8_t *spare, rt_uint32_t spare_len); - rt_err_t (*write_page)(struct rt_mtd_nand_device * device, + rt_err_t (*write_page)(struct rt_mtd_nand_device *device, rt_off_t page, - const rt_uint8_t * data, rt_uint32_t data_len, - const rt_uint8_t * spare, rt_uint32_t spare_len); - rt_err_t (*move_page) (struct rt_mtd_nand_device *device, rt_off_t src_page, rt_off_t dst_page); + const rt_uint8_t *data, rt_uint32_t data_len, + const rt_uint8_t *spare, rt_uint32_t spare_len); + rt_err_t (*move_page)(struct rt_mtd_nand_device *device, rt_off_t src_page, rt_off_t dst_page); - rt_err_t (*erase_block)(struct rt_mtd_nand_device* device, rt_uint32_t block); - rt_err_t (*check_block)(struct rt_mtd_nand_device* device, rt_uint32_t block); - rt_err_t (*mark_badblock)(struct rt_mtd_nand_device* device, rt_uint32_t block); + rt_err_t (*erase_block)(struct rt_mtd_nand_device *device, rt_uint32_t block); + rt_err_t (*check_block)(struct rt_mtd_nand_device *device, rt_uint32_t block); + rt_err_t (*mark_badblock)(struct rt_mtd_nand_device *device, rt_uint32_t block); }; -rt_err_t rt_mtd_nand_register_device(const char* name, struct rt_mtd_nand_device* device); +rt_err_t rt_mtd_nand_register_device(const char *name, struct rt_mtd_nand_device *device); -rt_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device* device) +rt_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device *device) { + RT_ASSERT(device->ops->read_id); return device->ops->read_id(device); } rt_inline rt_err_t rt_mtd_nand_read( - struct rt_mtd_nand_device* device, + struct rt_mtd_nand_device *device, rt_off_t page, - rt_uint8_t* data, rt_uint32_t data_len, - rt_uint8_t * spare, rt_uint32_t spare_len) + rt_uint8_t *data, rt_uint32_t data_len, + rt_uint8_t *spare, rt_uint32_t spare_len) { + RT_ASSERT(device->ops->read_page); return device->ops->read_page(device, page, data, data_len, spare, spare_len); } rt_inline rt_err_t rt_mtd_nand_write( - struct rt_mtd_nand_device* device, + struct rt_mtd_nand_device *device, rt_off_t page, - const rt_uint8_t* data, rt_uint32_t data_len, - const rt_uint8_t * spare, rt_uint32_t spare_len) + const rt_uint8_t *data, rt_uint32_t data_len, + const rt_uint8_t *spare, rt_uint32_t spare_len) { + RT_ASSERT(device->ops->write_page); return device->ops->write_page(device, page, data, data_len, spare, spare_len); } -rt_inline rt_err_t rt_mtd_nand_move_page(struct rt_mtd_nand_device* device, - rt_off_t src_page, rt_off_t dst_page) +rt_inline rt_err_t rt_mtd_nand_move_page(struct rt_mtd_nand_device *device, + rt_off_t src_page, rt_off_t dst_page) { + RT_ASSERT(device->ops->move_page); return device->ops->move_page(device, src_page, dst_page); } -rt_inline rt_err_t rt_mtd_nand_erase_block(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_erase_block(struct rt_mtd_nand_device *device, rt_uint32_t block) { + RT_ASSERT(device->ops->erase_block); return device->ops->erase_block(device, block); } -rt_inline rt_err_t rt_mtd_nand_check_block(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_check_block(struct rt_mtd_nand_device *device, rt_uint32_t block) { - return device->ops->check_block(device, block); + if (device->ops->check_block) + { + return device->ops->check_block(device, block); + } + else + { + return -RT_ENOSYS; + } } -rt_inline rt_err_t rt_mtd_nand_mark_badblock(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_mark_badblock(struct rt_mtd_nand_device *device, rt_uint32_t block) { - return device->ops->mark_badblock(device, block); + if (device->ops->mark_badblock) + { + return device->ops->mark_badblock(device, block); + } + else + { + return -RT_ENOSYS; + } } #endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtdnand.h b/components/drivers/include/drivers/mtdnand.h deleted file mode 100644 index 2e836cb2fb..0000000000 --- a/components/drivers/include/drivers/mtdnand.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef _MTDNAND_H_ -#define _MTDNAND_H_ - -#include "mtd.h" - - /* Status bits */ -#define NAND_STATUS_FAIL 0x01 -#define NAND_STATUS_FAIL_N1 0x02 -#define NAND_STATUS_WP 0x80 - -typedef enum -{ - NAND_CMD_PAGE_RD, /* read data to chip's page buffer,do WaitBusy after this cmd in low driver */ - NAND_CMD_PAGE_WR0, /* write data to chip's page buffer */ - NAND_CMD_PAGE_WR1, /* do flash programe */ - NAND_CMD_BLK_ERASE, /* erase block */ - NAND_CMD_ECC_EN, /* enable gen HWECC */ - NAND_CMD_ECC_DIS /* disable gen HWECC */ -} nand_cmd_t; - -typedef enum -{ - NAND_ECCM_NONE, - NAND_ECCM_HW, -} nand_eccmode_t; - -struct nand_chip; -struct nand_ops; - -/** -* struct nand_buffers - buffer structure for read/write -* @ecccalc: buffer pointer for calculated ECC, size is oobsize. -* @ecccode: buffer pointer for ECC read from flash, size is oobsize. -* -*/ -struct nand_buffers -{ - uint8_t *ecccalc; - uint8_t *ecccode; -}; - -struct nand_ecc -{ - uint8_t mode; /* nand_eccmode_t */ - uint8_t bytes; /* gen ecc bytes per ecc step(usually 3) */ - uint16_t stepsize:12; /* min 256 */ - uint16_t _step:4; /* */ - - /* driver must set the two interface if HWECC */ - void (*calculate)(struct nand_chip *chip, const uint8_t *dat, uint8_t *ecc_code); - /* return max bit flips if can't correct,return -1 ECC is error(0 success) */ - int(*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc); - /* ignore if NONECC */ - const struct mtd_oob_region *layout; -}; - -typedef struct nand_chip -{ - rt_mtd_t parent; - - /* driver must init these */ - const struct nand_ops *ops; - struct nand_ecc ecc; - const struct mtd_oob_region *freelayout; - - /* driver do not touch */ - struct nand_buffers buffers; - uint8_t *oob_poi; - uint8_t *pagebuf; - uint32_t size; - uint16_t oobsize; - uint8_t pages_pb; - uint16_t page_size; - int(*read_page)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page); - int(*write_page)(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page); -}rt_nand_t; - -struct nand_ops -{ - int(*cmdfunc)(rt_nand_t *nand, int cmd, int page, int offset); /* send nand operation cmd, return Status bits(0 success), - if nand is busy please wait in low driver */ - int(*read_buf)(rt_nand_t *nand, uint8_t *buf, int len); /* read data from nand chip's page buffer */ - int(*write_buf)(rt_nand_t *nand, const uint8_t *buf, int len);/* write data to nand chip's page buffer */ - int(*isbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(not 0xff is bad) */ - int(*markbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(set to 0x00) */ -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size); - -#endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtdnor.h b/components/drivers/include/drivers/mtdnor.h deleted file mode 100644 index ccb7466b4b..0000000000 --- a/components/drivers/include/drivers/mtdnor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTDNOR_H__ -#define __MTDNOR_H__ - -#include <drivers/mtd.h> - -struct nor_ops; - -typedef struct -{ - rt_mtd_t parent; - - const struct nor_ops *ops; /* operations interface */ -}rt_nor_t; - -struct nor_ops -{ - int (*erase)(rt_nor_t *nor, loff_t addr, size_t len); /* return success erased len or error code */ - int (*read)(rt_nor_t *nor, loff_t addr, uint8_t *buf, size_t len); /* return success data size or error code */ - int (*write)(rt_nor_t *nor, loff_t addr, const uint8_t *buf, size_t len); /* return success data size or error code */ -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize); - -#endif diff --git a/components/drivers/include/drivers/phy.h b/components/drivers/include/drivers/phy.h new file mode 100644 index 0000000000..2d1ad9f91f --- /dev/null +++ b/components/drivers/include/drivers/phy.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-14 wangqiang the first version + */ + +#ifndef __PHY_H__ +#define __PHY_H__ + +#include <rtthread.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Defines the PHY link speed. This is align with the speed for MAC. */ +enum phy_speed +{ + PHY_SPEED_10M = 0U, /* PHY 10M speed. */ + PHY_SPEED_100M /* PHY 100M speed. */ +}; + +/* Defines the PHY link duplex. */ +enum phy_duplex +{ + PHY_HALF_DUPLEX = 0U, /* PHY half duplex. */ + PHY_FULL_DUPLEX /* PHY full duplex. */ +}; + +/*! @brief Defines the PHY loopback mode. */ +enum phy_loop +{ + PHY_LOCAL_LOOP = 0U, /* PHY local loopback. */ + PHY_REMOTE_LOOP /* PHY remote loopback. */ +}; + + +struct rt_phy_msg +{ + rt_uint32_t reg; + rt_uint32_t value; +}; + +typedef struct rt_phy_msg rt_phy_msg_t; + + +struct rt_phy_device +{ + struct rt_device parent; + struct rt_mdio_bus *bus; + rt_uint32_t addr; + struct rt_phy_ops *ops; +}; + +typedef struct rt_phy_device rt_phy_t; + + +enum { + PHY_STATUS_OK = 0, + PHY_STATUS_FAIL, + PHY_STATUS_TIMEOUT, +}; + +typedef rt_int32_t rt_phy_status; + +struct rt_phy_ops +{ + rt_phy_status (*init)(void *object, rt_uint32_t phy_addr, rt_uint32_t src_clock_hz); + rt_phy_status (*read)(rt_uint32_t reg, rt_uint32_t *data); + rt_phy_status (*write)(rt_uint32_t reg, rt_uint32_t data); + rt_phy_status (*loopback)(rt_uint32_t mode, rt_uint32_t speed, rt_bool_t enable); + rt_phy_status (*get_link_status)(rt_bool_t *status); + rt_phy_status (*get_link_speed_duplex)(rt_uint32_t *speed, rt_uint32_t *duplex); +}; + +rt_err_t rt_hw_phy_register(struct rt_phy_device *phy, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* __PHY_H__*/ diff --git a/components/drivers/include/drivers/phy_mdio.h b/components/drivers/include/drivers/phy_mdio.h new file mode 100644 index 0000000000..d978ec2984 --- /dev/null +++ b/components/drivers/include/drivers/phy_mdio.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-14 wangqiang the first version + */ + +#ifndef __MDIO_H__ +#define __MDIO_H__ + +#include <rtthread.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + +struct rt_mdio_bus_ops +{ + rt_bool_t (*init)(void *bus, rt_uint32_t src_clock_hz); + rt_size_t (*read)(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size); + rt_size_t (*write)(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size); + rt_bool_t (*uninit)(void *bus); +}; + +struct rt_mdio_bus +{ + void *hw_obj; + char *name; + struct rt_mdio_bus_ops *ops; +}; + +typedef struct rt_mdio_bus rt_mdio_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/drivers/pin.h b/components/drivers/include/drivers/pin.h index ca35407932..f5b2ded9f6 100644 --- a/components/drivers/include/drivers/pin.h +++ b/components/drivers/include/drivers/pin.h @@ -74,10 +74,13 @@ struct rt_pin_ops rt_uint32_t mode, void (*hdr)(void *args), void *args); rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin); rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled); + rt_base_t (*pin_get)(const char *name); }; int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data); +/* Get pin number by name,such as PA.0,P0.12 */ +rt_base_t rt_pin_get(const char *name); void rt_pin_mode(rt_base_t pin, rt_base_t mode); void rt_pin_write(rt_base_t pin, rt_base_t value); int rt_pin_read(rt_base_t pin); diff --git a/components/drivers/include/drivers/pm.h b/components/drivers/include/drivers/pm.h index 94d4c8559b..dd5875aa1d 100644 --- a/components/drivers/include/drivers/pm.h +++ b/components/drivers/include/drivers/pm.h @@ -7,6 +7,7 @@ * Date Author Notes * 2012-06-02 Bernard the first version * 2018-08-02 Tanek split run and sleep modes, support custom mode + * 2019-04-28 Zero-Free improve PM mode and device ops interface */ #ifndef __PM_H__ @@ -16,96 +17,67 @@ #ifndef PM_HAS_CUSTOM_CONFIG -/* All modes used for rt_pm_request() adn rt_pm_release() */ +/* All modes used for rt_pm_request() and rt_pm_release() */ enum { - /* run modes */ - PM_RUN_MODE_NORMAL = 0, - /* sleep modes */ - PM_SLEEP_MODE_SLEEP, - PM_SLEEP_MODE_TIMER, + PM_SLEEP_MODE_NONE = 0, + PM_SLEEP_MODE_IDLE, + PM_SLEEP_MODE_LIGHT, + PM_SLEEP_MODE_DEEP, + PM_SLEEP_MODE_STANDBY, PM_SLEEP_MODE_SHUTDOWN, + PM_SLEEP_MODE_MAX, +}; + +enum +{ + /* run modes*/ + PM_RUN_MODE_HIGH_SPEED = 0, + PM_RUN_MODE_NORMAL_SPEED, + PM_RUN_MODE_MEDIUM_SPEED, + PM_RUN_MODE_LOW_SPEED, + PM_RUN_MODE_MAX, +}; + +enum +{ + RT_PM_FREQUENCY_PENDING = 0x01, }; +#define RT_PM_DEFAULT_SLEEP_MODE PM_SLEEP_MODE_IDLE +#define RT_PM_DEFAULT_RUN_MODE PM_RUN_MODE_NORMAL_SPEED + /* The name of all modes used in the msh command "pm_dump" */ -#define PM_MODE_NAMES \ +#define PM_SLEEP_MODE_NAMES \ { \ - "Running Mode", \ - \ - "Sleep Mode", \ - "Timer Mode", \ + "None Mode", \ + "Idle Mode", \ + "LightSleep Mode", \ + "DeepSleep Mode", \ + "Standby 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 +#define PM_RUN_MODE_NAMES \ +{ \ + "High Speed", \ + "Normal Speed", \ + "Medium Speed", \ + "Low Mode", \ +} #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 +#define RT_PM_DEVICE_CTRL_RELEASE 0x00 struct rt_pm; @@ -114,13 +86,8 @@ struct rt_pm; */ 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 (*sleep)(struct rt_pm *pm, rt_uint8_t mode); + void (*run)(struct rt_pm *pm, rt_uint8_t mode); 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); @@ -128,18 +95,15 @@ struct rt_pm_ops 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); + int (*suspend)(const struct rt_device *device, rt_uint8_t mode); + void (*resume)(const struct rt_device *device, rt_uint8_t mode); + int (*frequency_change)(const struct rt_device *device, rt_uint8_t mode); }; struct rt_device_pm { - const struct rt_device* device; - const struct rt_device_pm_ops* ops; + const struct rt_device *device; + const struct rt_device_pm_ops *ops; }; /** @@ -150,32 +114,45 @@ 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; + rt_uint8_t modes[PM_SLEEP_MODE_MAX]; + rt_uint8_t sleep_mode; /* current sleep mode */ + rt_uint8_t run_mode; /* current running mode */ /* 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; + struct rt_device_pm *device_pm; /* if the mode has timer, the corresponding bit is 1*/ - rt_uint32_t timer_mask; + rt_uint8_t timer_mask; + rt_uint8_t flags; const struct rt_pm_ops *ops; }; -void rt_pm_enter(void); -void rt_pm_exit(void); +enum +{ + RT_PM_ENTER_SLEEP = 0, + RT_PM_EXIT_SLEEP, +}; + +struct rt_pm_notify +{ + void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data); + void *data; +}; + +void rt_pm_request(rt_uint8_t sleep_mode); +void rt_pm_release(rt_uint8_t sleep_mode); +int rt_pm_run_enter(rt_uint8_t run_mode); -void rt_pm_request(rt_ubase_t mode); -void rt_pm_release(rt_ubase_t mode); +void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops); +void rt_pm_device_unregister(struct rt_device *device); -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_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data); +void rt_pm_default_set(rt_uint8_t sleep_mode); void rt_system_pm_init(const struct rt_pm_ops *ops, rt_uint8_t timer_mask, - void *user_data); + void *user_data); #endif /* __PM_H__ */ diff --git a/components/drivers/include/drivers/pulse_encoder.h b/components/drivers/include/drivers/pulse_encoder.h new file mode 100644 index 0000000000..0c7df04cd6 --- /dev/null +++ b/components/drivers/include/drivers/pulse_encoder.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-08 balanceTWK the first version + */ + +#ifndef __PULSE_ENCODER_H__ +#define __PULSE_ENCODER_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* pulse_encoder control command */ +#define PULSE_ENCODER_CMD_GET_TYPE (128 + 0) /* get a pulse_encoder type information */ +#define PULSE_ENCODER_CMD_ENABLE (128 + 1) /* enable pulse_encoder */ +#define PULSE_ENCODER_CMD_DISABLE (128 + 2) /* disable pulse_encoder */ +#define PULSE_ENCODER_CMD_CLEAR_COUNT (128 + 3) /* clear pulse_encoder count */ + +/* pulse_encoder type */ +enum rt_pulse_encoder_type +{ + UNKNOWN_PULSE_ENCODER_TYPE = 0x00, /* Unknown pulse_encoder type */ + SINGLE_PHASE_PULSE_ENCODER, /* single phase pulse_encoder */ + AB_PHASE_PULSE_ENCODER /* two phase pulse_encoder */ +}; + +struct rt_pulse_encoder_device; + +struct rt_pulse_encoder_ops +{ + rt_err_t (*init)(struct rt_pulse_encoder_device *pulse_encoder); + rt_int32_t (*get_count)(struct rt_pulse_encoder_device *pulse_encoder); + rt_err_t (*clear_count)(struct rt_pulse_encoder_device *pulse_encoder); + rt_err_t (*control)(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args); +}; + +struct rt_pulse_encoder_device +{ + struct rt_device parent; + const struct rt_pulse_encoder_ops *ops; + enum rt_pulse_encoder_type type; +}; + +rt_err_t rt_device_pulse_encoder_register(struct rt_pulse_encoder_device *pulse_encoder, const char *name, void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __PULSE_ENCODER_H__ */ diff --git a/components/drivers/include/drivers/rt_inputcapture.h b/components/drivers/include/drivers/rt_inputcapture.h new file mode 100644 index 0000000000..40cd55883d --- /dev/null +++ b/components/drivers/include/drivers/rt_inputcapture.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-13 balanceTWK first version. + */ + +#ifndef __RT_INPUT_CAPTURE_H__ +#define __RT_INPUT_CAPTURE_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* capture control command */ +#define INPUTCAPTURE_CMD_CLEAR_BUF (128 + 0) /* clear capture buf */ +#define INPUTCAPTURE_CMD_SET_WATERMARK (128 + 1) /* Set the callback threshold */ + +struct rt_inputcapture_data +{ + rt_uint32_t pulsewidth_us; + rt_bool_t is_high; +}; + +struct rt_inputcapture_device +{ + struct rt_device parent; + + const struct rt_inputcapture_ops *ops; + struct rt_ringbuffer *ringbuff; + rt_size_t watermark; +}; + +/** + * capture operators + */ +struct rt_inputcapture_ops +{ + rt_err_t (*init)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*open)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*close)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*get_pulsewidth)(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); +}; + +void rt_hw_inputcapture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level); + +rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, + const char *name, + void *data); +#ifdef __cplusplus +} +#endif + +#endif /* __RT_INPUT_CAPTURE_H__ */ diff --git a/components/drivers/include/drivers/spi.h b/components/drivers/include/drivers/spi.h index 04a65421a5..d92518cd94 100644 --- a/components/drivers/include/drivers/spi.h +++ b/components/drivers/include/drivers/spi.h @@ -1,11 +1,12 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2012-11-23 Bernard Add extern "C" + * 2020-06-13 armink fix the 3 wires issue */ #ifndef __SPI_H__ @@ -18,8 +19,6 @@ extern "C"{ #endif -#define RT_SPI_CPHA (1<<0) /* bit[0]:CPHA, clock phase */ -#define RT_SPI_CPOL (1<<1) /* bit[1]:CPOL, clock polarity */ /** * At CPOL=0 the base value of the clock is zero * - For CPHA=0, data are captured on the clock's rising edge (low->high transition) @@ -32,26 +31,29 @@ extern "C"{ * - For CPHA=1, data are captured on clock's rising edge and data are propagated * on a falling edge. */ +#define RT_SPI_CPHA (1<<0) /* bit[0]:CPHA, clock phase */ +#define RT_SPI_CPOL (1<<1) /* bit[1]:CPOL, clock polarity */ + #define RT_SPI_LSB (0<<2) /* bit[2]: 0-LSB */ #define RT_SPI_MSB (1<<2) /* bit[2]: 1-MSB */ #define RT_SPI_MASTER (0<<3) /* SPI master device */ #define RT_SPI_SLAVE (1<<3) /* SPI slave device */ +#define RT_SPI_CS_HIGH (1<<4) /* Chipselect active high */ +#define RT_SPI_NO_CS (1<<5) /* No chipselect */ +#define RT_SPI_3WIRE (1<<6) /* SI/SO pin shared */ +#define RT_SPI_READY (1<<7) /* Slave pulls low to pause */ + +#define RT_SPI_MODE_MASK (RT_SPI_CPHA | RT_SPI_CPOL | RT_SPI_MSB | RT_SPI_SLAVE | RT_SPI_CS_HIGH | RT_SPI_NO_CS | RT_SPI_3WIRE | RT_SPI_READY) + #define RT_SPI_MODE_0 (0 | 0) /* CPOL = 0, CPHA = 0 */ #define RT_SPI_MODE_1 (0 | RT_SPI_CPHA) /* CPOL = 0, CPHA = 1 */ #define RT_SPI_MODE_2 (RT_SPI_CPOL | 0) /* CPOL = 1, CPHA = 0 */ #define RT_SPI_MODE_3 (RT_SPI_CPOL | RT_SPI_CPHA) /* CPOL = 1, CPHA = 1 */ -#define RT_SPI_MODE_MASK (RT_SPI_CPHA | RT_SPI_CPOL | RT_SPI_MSB) - -#define RT_SPI_BUS_MODE_SPI (1<<0) -#define RT_SPI_BUS_MODE_QSPI (1<<1) - -#define RT_SPI_CS_HIGH (1<<4) /* Chipselect active high */ -#define RT_SPI_NO_CS (1<<5) /* No chipselect */ -#define RT_SPI_3WIRE (1<<6) /* SI/SO pin shared */ -#define RT_SPI_READY (1<<7) /* Slave pulls low to pause */ +#define RT_SPI_BUS_MODE_SPI (1<<0) +#define RT_SPI_BUS_MODE_QSPI (1<<1) /** * SPI message structure diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h index c26d83391e..4d85a85e35 100644 --- a/components/drivers/include/drivers/usb_common.h +++ b/components/drivers/include/drivers/usb_common.h @@ -435,15 +435,15 @@ typedef struct usb_os_proerty * usb_os_proerty_t; // 5 A big-endian 32-bit integer (REG_DWORD_BIG_ENDIAN) // 6 A NULL-terminated Unicode string that contains a symbolic link (REG_LINK) // 7 Multiple NULL-terminated Unicode strings (REG_MULTI_SZ) -#define USB_OS_PROERTY_TYPE_REG_SZ 0x01UL -#define USB_OS_PROERTY_TYPE_REG_EXPAND_SZ 0x02UL -#define USB_OS_PROERTY_TYPE_REG_BINARY 0x03UL -#define USB_OS_PROERTY_TYPE_REG_DWORD_LITTLE_ENDIAN 0x04UL -#define USB_OS_PROERTY_TYPE_REG_DWORD_BIG_ENDIAN 0x05UL -#define USB_OS_PROERTY_TYPE_REG_LINK 0x06UL -#define USB_OS_PROERTY_TYPE_REG_MULTI_SZ 0x07UL +#define USB_OS_PROPERTY_TYPE_REG_SZ 0x01UL +#define USB_OS_PROPERTY_TYPE_REG_EXPAND_SZ 0x02UL +#define USB_OS_PROPERTY_TYPE_REG_BINARY 0x03UL +#define USB_OS_PROPERTY_TYPE_REG_DWORD_LITTLE_ENDIAN 0x04UL +#define USB_OS_PROPERTY_TYPE_REG_DWORD_BIG_ENDIAN 0x05UL +#define USB_OS_PROPERTY_TYPE_REG_LINK 0x06UL +#define USB_OS_PROPERTY_TYPE_REG_MULTI_SZ 0x07UL -#define USB_OS_PROERTY_DESC(PropertyDataType,PropertyName,PropertyData) \ +#define USB_OS_PROPERTY_DESC(PropertyDataType,PropertyName,PropertyData) \ {\ .dwSize = sizeof(struct usb_os_proerty)-sizeof(const char *)*2\ +sizeof(PropertyName)*2+sizeof(PropertyData)*2,\ diff --git a/components/drivers/include/ipc/dataqueue.h b/components/drivers/include/ipc/dataqueue.h index f584c267bf..0262f4702b 100644 --- a/components/drivers/include/ipc/dataqueue.h +++ b/components/drivers/include/ipc/dataqueue.h @@ -17,17 +17,19 @@ #define RT_DATAQUEUE_EVENT_LWM 0x03 struct rt_data_item; -#define RT_DATAQUEUE_SIZE(dq) ((dq)->put_index - (dq)->get_index) -#define RT_DATAQUEUE_EMPTY(dq) ((dq)->size - RT_DATAQUEUE_SIZE(dq)) + /* data queue implementation */ struct rt_data_queue { + rt_uint32_t magic; + rt_uint16_t size; rt_uint16_t lwm; - rt_bool_t waiting_lwm; - rt_uint16_t get_index; - rt_uint16_t put_index; + rt_uint16_t get_index : 15; + rt_uint16_t is_empty : 1; + rt_uint16_t put_index : 15; + rt_uint16_t is_full : 1; struct rt_data_item *queue; @@ -57,5 +59,7 @@ rt_err_t rt_data_queue_peak(struct rt_data_queue *queue, const void **data_ptr, rt_size_t *size); void rt_data_queue_reset(struct rt_data_queue *queue); +rt_err_t rt_data_queue_deinit(struct rt_data_queue *queue); +rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue); #endif diff --git a/components/drivers/include/ipc/pipe.h b/components/drivers/include/ipc/pipe.h index 25b19f540d..93ba95cd2c 100644 --- a/components/drivers/include/ipc/pipe.h +++ b/components/drivers/include/ipc/pipe.h @@ -24,6 +24,7 @@ struct rt_pipe_device { struct rt_device parent; + rt_bool_t is_named; /* ring buffer in pipe device */ struct rt_ringbuffer *fifo; diff --git a/components/drivers/include/ipc/workqueue.h b/components/drivers/include/ipc/workqueue.h index 9e23e181b1..23e256c420 100644 --- a/components/drivers/include/ipc/workqueue.h +++ b/components/drivers/include/ipc/workqueue.h @@ -11,13 +11,27 @@ #include <rtthread.h> +enum +{ + RT_WORK_STATE_PENDING = 0x0001, /* Work item pending state */ + RT_WORK_STATE_SUBMITTING = 0x0002, /* Work item submitting state */ +}; + +/** + * work type defitions + */ +enum +{ + RT_WORK_TYPE_DELAYED = 0x0001, +}; + /* workqueue implementation */ struct rt_workqueue { rt_list_t work_list; struct rt_work *work_current; /* current work */ - struct rt_semaphore sem; + struct rt_semaphore sem; rt_thread_t work_thread; }; @@ -25,28 +39,50 @@ struct rt_work { rt_list_t list; - void (*work_func)(struct rt_work* work, void* work_data); + void (*work_func)(struct rt_work *work, void *work_data); void *work_data; + rt_uint16_t flags; + rt_uint16_t type; + struct rt_timer timer; + struct rt_workqueue *workqueue; +}; + +struct rt_delayed_work +{ + struct rt_work work; }; #ifdef RT_USING_HEAP /** * WorkQueue for DeviceDriver */ -struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_size, rt_uint8_t priority); -rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue); -rt_err_t rt_workqueue_dowork(struct rt_workqueue* queue, struct rt_work* work); -rt_err_t rt_workqueue_cancel_work(struct rt_workqueue* queue, struct rt_work* work); -rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue* queue, struct rt_work* work); +struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority); +rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue); +rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work); +rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time); +rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work); +rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work); + +#ifdef RT_USING_SYSTEM_WORKQUEUE +rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time); +rt_err_t rt_work_cancel(struct rt_work *work); +#endif -rt_inline void rt_work_init(struct rt_work* work, void (*work_func)(struct rt_work* work, void* work_data), - void* work_data) +rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_work *work, void *work_data), + void *work_data) { rt_list_init(&(work->list)); work->work_func = work_func; work->work_data = work_data; + work->workqueue = RT_NULL; + work->flags = 0; + work->type = 0; } -#endif +void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work, + void *work_data), void *work_data); + +int rt_work_sys_workqueue_init(void); #endif +#endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index d59b40cc47..f0fa2f5b4a 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -69,6 +69,11 @@ extern "C" { #endif /* RT_USING_I2C_BITOPS */ #endif /* RT_USING_I2C */ +#ifdef RT_USING_PHY +#include "drivers/phy.h" +#include "drivers/phy_mdio.h" +#endif /* RT_USING_PHY */ + #ifdef RT_USING_SDIO #include "drivers/mmcsd_core.h" #include "drivers/sd.h" @@ -103,6 +108,10 @@ extern "C" { #include "drivers/adc.h" #endif +#ifdef RT_USING_DAC +#include "drivers/dac.h" +#endif + #ifdef RT_USING_PWM #include "drivers/rt_drv_pwm.h" #endif @@ -122,6 +131,18 @@ extern "C" { #include "drivers/mtdnand.h" #endif +#ifdef RT_USING_HWCRYPTO +#include "drivers/crypto.h" +#endif + +#ifdef RT_USING_PULSE_ENCODER +#include "drivers/pulse_encoder.h" +#endif + +#ifdef RT_USING_INPUT_CAPTURE +#include "drivers/rt_inputcapture.h" +#endif + #ifdef __cplusplus } #endif diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript index c45ba524c5..72058eeeca 100644 --- a/components/drivers/misc/SConscript +++ b/components/drivers/misc/SConscript @@ -11,8 +11,17 @@ if GetDepend(['RT_USING_PIN']): if GetDepend(['RT_USING_ADC']): src = src + ['adc.c'] +if GetDepend(['RT_USING_DAC']): + src = src + ['dac.c'] + if GetDepend(['RT_USING_PWM']): src = src + ['rt_drv_pwm.c'] + +if GetDepend(['RT_USING_PULSE_ENCODER']): + src = src + ['pulse_encoder.c'] + +if GetDepend(['RT_USING_INPUT_CAPTURE']): + src = src + ['rt_inputcapture.c'] if len(src): group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/components/drivers/misc/adc.c b/components/drivers/misc/adc.c index 83e789a6e4..2d26beb243 100644 --- a/components/drivers/misc/adc.c +++ b/components/drivers/misc/adc.c @@ -15,10 +15,8 @@ #include <string.h> #include <stdlib.h> -#define DBG_ENABLE -#define DBG_SECTION_NAME "adc" -#define DBG_LEVEL DBG_INFO -#define DBG_COLOR +#define DBG_TAG "adc" +#define DBG_LVL DBG_INFO #include <rtdbg.h> static rt_size_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) @@ -62,19 +60,37 @@ static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args) return result; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops adc_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _adc_read, + RT_NULL, + _adc_control, +}; +#endif + 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->parent.rx_indicate = RT_NULL; + device->parent.tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->parent.ops = &adc_ops; +#else + 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; +#endif device->ops = ops; device->parent.user_data = (void *)user_data; diff --git a/components/drivers/misc/dac.c b/components/drivers/misc/dac.c new file mode 100644 index 0000000000..336c78d018 --- /dev/null +++ b/components/drivers/misc/dac.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-19 thread-liu the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> + +#include <string.h> +#include <stdlib.h> + +#define DBG_TAG "dac" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +static rt_size_t _dac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_err_t result = RT_EOK; + rt_size_t i; + struct rt_dac_device *dac = (struct rt_dac_device *)dev; + rt_uint32_t *value = (rt_uint32_t *)buffer; + + for (i = 0; i < size; i += sizeof(int)) + { + result = dac->ops->convert(dac, pos + i, value); + if (result != RT_EOK) + { + return 0; + } + value++; + } + + return i; +} + +static rt_err_t _dac_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t result = RT_EOK; + rt_dac_device_t dac = (struct rt_dac_device *)dev; + + if (dac->ops->enabled == RT_NULL) + { + return -RT_ENOSYS; + } + if (cmd == RT_DAC_CMD_ENABLE) + { + result = dac->ops->enabled(dac, (rt_uint32_t)args); + } + else if (cmd == RT_DAC_CMD_DISABLE) + { + result = dac->ops->disabled(dac, (rt_uint32_t)args); + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops dac_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + _dac_write, + _dac_control, +}; +#endif + +rt_err_t rt_hw_dac_register(rt_dac_device_t device, const char *name, const struct rt_dac_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.rx_indicate = RT_NULL; + device->parent.tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->parent.ops = &dac_ops; +#else + device->parent.init = RT_NULL; + device->parent.open = RT_NULL; + device->parent.close = RT_NULL; + device->parent.read = RT_NULL; + device->parent.write = _dac_write; + device->parent.control = _dac_control; +#endif + 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_dac_write(rt_dac_device_t dev, rt_uint32_t channel, rt_uint32_t value) +{ + RT_ASSERT(dev); + + dev->ops->convert(dev, channel, &value); + + return RT_EOK; +} + +rt_err_t rt_dac_enable(rt_dac_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); + } + else + { + result = -RT_ENOSYS; + } + + return result; +} + +rt_err_t rt_dac_disabled(rt_dac_device_t dev, rt_uint32_t channel) +{ + rt_err_t result = RT_EOK; + + RT_ASSERT(dev); + if (dev->ops->disabled != RT_NULL) + { + result = dev->ops->disabled(dev, channel); + } + else + { + result = -RT_ENOSYS; + } + + return result; +} + +#ifdef FINSH_USING_MSH + +static int dac(int argc, char **argv) +{ + int result = RT_EOK; + static rt_dac_device_t dac_device = RT_NULL; + char *result_str; + + if (argc > 1) + { + if (!strcmp(argv[1], "probe")) + { + if (argc == 3) + { + dac_device = (rt_dac_device_t)rt_device_find(argv[2]); + result_str = (dac_device == RT_NULL) ? "failure" : "success"; + rt_kprintf("probe %s %s \n", argv[2], result_str); + } + else + { + rt_kprintf("dac probe <dac_name> - probe dac by name\n"); + } + } + else + { + if (dac_device == RT_NULL) + { + rt_kprintf("Please using 'dac probe <dac_name>' first\n"); + return -RT_ERROR; + } + if (!strcmp(argv[1], "enable")) + { + if (argc == 3) + { + result = rt_dac_enable(dac_device, atoi(argv[2])); + result_str = (result == RT_EOK) ? "success" : "failure"; + rt_kprintf("%s channel %d enables %s \n", dac_device->parent.parent.name, atoi(argv[2]), result_str); + } + else + { + rt_kprintf("dac enable <channel> - enable dac channel\n"); + } + } + else if (!strcmp(argv[1], "write")) + { + if (argc == 4) + { + rt_dac_write(dac_device, atoi(argv[2]), atoi(argv[3])); + rt_kprintf("%s channel %d write value is %d \n", dac_device->parent.parent.name, atoi(argv[2]), atoi(argv[3])); + } + else + { + rt_kprintf("dac write <channel> <value> - write dac value on the channel\n"); + } + } + else if (!strcmp(argv[1], "disable")) + { + if (argc == 3) + { + result = rt_dac_disabled(dac_device, atoi(argv[2])); + result_str = (result == RT_EOK) ? "success" : "failure"; + rt_kprintf("%s channel %d disable %s \n", dac_device->parent.parent.name, atoi(argv[2]), result_str); + } + else + { + rt_kprintf("dac disable <channel> - disable dac channel\n"); + } + } + else + { + rt_kprintf("Unknown command. Please enter 'dac' for help\n"); + } + } + } + else + { + rt_kprintf("Usage: \n"); + rt_kprintf("dac probe <dac_name> - probe dac by name\n"); + rt_kprintf("dac write <channel> <value> - write dac value on the channel\n"); + rt_kprintf("dac disable <channel> - disable dac channel\n"); + rt_kprintf("dac enable <channel> - enable dac channel\n"); + result = -RT_ERROR; + } + return RT_EOK; +} +MSH_CMD_EXPORT(dac, dac function); + +#endif /* FINSH_USING_MSH */ diff --git a/components/drivers/misc/pin.c b/components/drivers/misc/pin.c index aca58ee21b..2750f5105a 100644 --- a/components/drivers/misc/pin.c +++ b/components/drivers/misc/pin.c @@ -151,3 +151,18 @@ int rt_pin_read(rt_base_t pin) return _hw_pin.ops->pin_read(&_hw_pin.parent, pin); } FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_read, pinRead, read status from hardware pin); + +rt_base_t rt_pin_get(const char *name) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + RT_ASSERT(name[0] == 'P'); + + if(_hw_pin.ops->pin_get == RT_NULL) + { + return -RT_ENOSYS; + } + + return _hw_pin.ops->pin_get(name); +} +FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_get, pinGet, get pin number from hardware pin); + diff --git a/components/drivers/misc/pulse_encoder.c b/components/drivers/misc/pulse_encoder.c new file mode 100644 index 0000000000..3145c24675 --- /dev/null +++ b/components/drivers/misc/pulse_encoder.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-08 balanceTWK the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> + +static rt_err_t rt_pulse_encoder_init(struct rt_device *dev) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->init) + { + return pulse_encoder->ops->init(pulse_encoder); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_err_t rt_pulse_encoder_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->control) + { + return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_ENABLE, RT_NULL); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_err_t rt_pulse_encoder_close(struct rt_device *dev) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->control) + { + return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_DISABLE, RT_NULL); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_size_t rt_pulse_encoder_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->get_count) + { + *(rt_int32_t *)buffer = pulse_encoder->ops->get_count(pulse_encoder); + } + return 1; +} + +static rt_err_t rt_pulse_encoder_control(struct rt_device *dev, int cmd, void *args) +{ + rt_err_t result; + struct rt_pulse_encoder_device *pulse_encoder; + + result = RT_EOK; + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + switch (cmd) + { + case PULSE_ENCODER_CMD_CLEAR_COUNT: + result = pulse_encoder->ops->clear_count(pulse_encoder); + break; + case PULSE_ENCODER_CMD_GET_TYPE: + *(enum rt_pulse_encoder_type *)args = pulse_encoder->type; + break; + case PULSE_ENCODER_CMD_ENABLE: + case PULSE_ENCODER_CMD_DISABLE: + result = pulse_encoder->ops->control(pulse_encoder, cmd, args); + break; + default: + result = -RT_ENOSYS; + break; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pulse_encoder_ops = +{ + rt_pulse_encoder_init, + rt_pulse_encoder_open, + rt_pulse_encoder_close, + rt_pulse_encoder_read, + RT_NULL, + rt_pulse_encoder_control +}; +#endif + +rt_err_t rt_device_pulse_encoder_register(struct rt_pulse_encoder_device *pulse_encoder, const char *name, void *user_data) +{ + struct rt_device *device; + + RT_ASSERT(pulse_encoder != RT_NULL); + RT_ASSERT(pulse_encoder->ops != RT_NULL); + + device = &(pulse_encoder->parent); + + device->type = RT_Device_Class_Miscellaneous; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &pulse_encoder_ops; +#else + device->init = rt_pulse_encoder_init; + device->open = rt_pulse_encoder_open; + device->close = rt_pulse_encoder_close; + device->read = rt_pulse_encoder_read; + device->write = RT_NULL; + device->control = rt_pulse_encoder_control; +#endif + device->user_data = user_data; + + return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE); +} diff --git a/components/drivers/misc/rt_drv_pwm.c b/components/drivers/misc/rt_drv_pwm.c index 2b7986b4d8..97d38d51b3 100644 --- a/components/drivers/misc/rt_drv_pwm.c +++ b/components/drivers/misc/rt_drv_pwm.c @@ -259,7 +259,7 @@ static int pwm_set(int argc, char **argv) _exit: return result; } -MSH_CMD_EXPORT(pwm_set, pwm_set 1 100 50); +MSH_CMD_EXPORT(pwm_set, pwm_set pwm1 1 100 50); #endif /* FINSH_USING_MSH */ #endif /* RT_USING_FINSH */ diff --git a/components/drivers/misc/rt_inputcapture.c b/components/drivers/misc/rt_inputcapture.c new file mode 100644 index 0000000000..d1886186d7 --- /dev/null +++ b/components/drivers/misc/rt_inputcapture.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-13 balanceTWK the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <rtdbg.h> + +static rt_err_t rt_inputcapture_init(struct rt_device *dev) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + inputcapture->watermark = RT_INPUT_CAPTURE_RB_SIZE / 2; + if (inputcapture->ops->init) + { + ret = inputcapture->ops->init(inputcapture); + } + + return ret; +} + +static rt_err_t rt_inputcapture_open(struct rt_device *dev, rt_uint16_t oflag) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + if (inputcapture->ringbuff == RT_NULL) + { + inputcapture->ringbuff = rt_ringbuffer_create(sizeof(struct rt_inputcapture_data) * RT_INPUT_CAPTURE_RB_SIZE); + } + if (inputcapture->ops->open) + { + ret = inputcapture->ops->open(inputcapture); + } + + return ret; +} + +static rt_err_t rt_inputcapture_close(struct rt_device *dev) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = -RT_ERROR; + inputcapture = (struct rt_inputcapture_device *)dev; + + if (inputcapture->ops->close) + { + ret = inputcapture->ops->close(inputcapture); + } + + if (ret != RT_EOK) + { + return ret; + } + + if (inputcapture->ringbuff) + { + rt_ringbuffer_destroy(inputcapture->ringbuff); + inputcapture->ringbuff = RT_NULL; + } + return ret; +} + +static rt_size_t rt_inputcapture_read(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + rt_size_t receive_size; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + inputcapture = (struct rt_inputcapture_device *)dev; + receive_size = rt_ringbuffer_get(inputcapture->ringbuff, (rt_uint8_t *)buffer, sizeof(struct rt_inputcapture_data) * size); + + return receive_size / sizeof(struct rt_inputcapture_data); +} + +static rt_err_t rt_inputcapture_control(struct rt_device *dev, int cmd, void *args) +{ + rt_err_t result; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + result = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + switch (cmd) + { + case INPUTCAPTURE_CMD_CLEAR_BUF: + if (inputcapture->ringbuff) + { + rt_ringbuffer_reset(inputcapture->ringbuff); + } + break; + case INPUTCAPTURE_CMD_SET_WATERMARK: + inputcapture->watermark = *(rt_size_t *)args; + break; + default: + result = -RT_ENOSYS; + break; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops inputcapture_ops = +{ + rt_inputcapture_init, + rt_inputcapture_open, + rt_inputcapture_close, + rt_inputcapture_read, + RT_NULL, + rt_inputcapture_control +}; +#endif + +rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, const char *name, void *user_data) +{ + struct rt_device *device; + + RT_ASSERT(inputcapture != RT_NULL); + RT_ASSERT(inputcapture->ops != RT_NULL); + RT_ASSERT(inputcapture->ops->get_pulsewidth != RT_NULL); + + device = &(inputcapture->parent); + + device->type = RT_Device_Class_Miscellaneous; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + inputcapture->ringbuff = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &inputcapture_ops; +#else + device->init = rt_inputcapture_init; + device->open = rt_inputcapture_open; + device->close = rt_inputcapture_close; + device->read = rt_inputcapture_read; + device->write = RT_NULL; + device->control = rt_inputcapture_control; +#endif + device->user_data = user_data; + + return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE); +} + +/** + * This function is ISR for inputcapture interrupt. + * level: RT_TRUE denotes high level pulse, and RT_FALSE denotes low level pulse. + */ +void rt_hw_inputcapture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level) +{ + struct rt_inputcapture_data data; + rt_size_t receive_size; + if (inputcapture->ops->get_pulsewidth(inputcapture, &data.pulsewidth_us) != RT_EOK) + { + return; + } + + data.is_high = level; + if (rt_ringbuffer_put(inputcapture->ringbuff, (rt_uint8_t *)&data, sizeof(struct rt_inputcapture_data)) == 0) + { + LOG_W("inputcapture ringbuffer doesn't have enough space."); + } + + receive_size = rt_ringbuffer_data_len(inputcapture->ringbuff) / sizeof(struct rt_inputcapture_data); + + if (receive_size >= inputcapture->watermark) + { + /* indicate to upper layer application */ + if (inputcapture->parent.rx_indicate != RT_NULL) + inputcapture->parent.rx_indicate(&inputcapture->parent, receive_size); + } +} diff --git a/components/drivers/mtd/SConscript b/components/drivers/mtd/SConscript index 462c38194c..6f86656187 100644 --- a/components/drivers/mtd/SConscript +++ b/components/drivers/mtd/SConscript @@ -1,5 +1,3 @@ -Import('RTT_ROOT') -Import('rtconfig') from building import * cwd = GetCurrentDir() @@ -9,17 +7,6 @@ depend = [] CPPPATH = [cwd + '/../include'] group = [] -if GetDepend(['RT_USING_MTD']): - src += ['mtd.c'] - depend += ['RT_USING_MTD'] - - if GetDepend(['MTD_USING_NOR']): - src += ['mtdnor.c'] - depend += ['MTD_USING_NOR'] - if GetDepend(['MTD_USING_NAND']): - src += ['mtdnand.c'] - depend += ['MTD_USING_NAND'] - if GetDepend(['RT_USING_MTD_NOR']): src += ['mtd_nor.c'] depend += ['RT_USING_MTD_NOR'] @@ -31,4 +18,4 @@ if GetDepend(['RT_USING_MTD_NAND']): if src: group = DefineGroup('DeviceDrivers', src, depend = depend, CPPPATH = CPPPATH) -Return('group')
\ No newline at end of file +Return('group') diff --git a/components/drivers/mtd/mtd.c b/components/drivers/mtd/mtd.c deleted file mode 100644 index 3e7b4f2b54..0000000000 --- a/components/drivers/mtd/mtd.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include <drivers/mtd.h> - -static rt_mtd_t* mtd_part_alloc(rt_mtd_t *master, const struct mtd_part *part) -{ - rt_mtd_t *slave; - - slave = rt_malloc(sizeof(rt_mtd_t)); - if (slave == RT_NULL) - goto out; - - slave->master = master; - - *slave = *master; - slave->size = part->size; - slave->offset = part->offset; - -out: - - return slave; -} - -rt_mtd_t* rt_mtd_get(const char *name) -{ - rt_mtd_t *mtd; - - mtd = (rt_mtd_t *)rt_device_find(name); - if (mtd == RT_NULL) - return RT_NULL; - - if (mtd->parent.type != RT_Device_Class_MTD) - return RT_NULL; - - return mtd; -} - -/* - * Register MTD driver - * - * @parts partion description - * @np number of partitions - * @return number of unregistered partitions - * -*/ -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np) -{ - int ret; - rt_mtd_t *slave; - - master->master = master; - master->parent.type = RT_Device_Class_MTD; - - if (np > 0) - { - master->offset = parts->offset; - master->size = parts->size; - - ret = rt_device_register((rt_device_t)master, parts->name, 0); - if (ret != 0) - goto _out; - - np --; - parts ++; - } - - while (np > 0) - { - slave = mtd_part_alloc(master, parts); - if (!slave) - break; - ret = rt_device_register((rt_device_t)slave, parts->name, 0); - if (ret) - break; - parts ++; - np --; - } - -_out: - return np; -} - -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks; - loff_t addr; - - total_blks = mtd->size/mtd->block_size; - if (block >= total_blks) - return -EINVAL; - addr = mtd->offset + mtd->block_size * block; - - return mtd->ops->erase(mtd->master, addr, mtd->block_size); -} - -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->isbad) - return 0; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->isbad(mtd->master, block + offset_blk); -} - -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->markbad) - return -EOPNOTSUPP; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->markbad(mtd->master, block + offset_blk); -} - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - if (addr > mtd->size || (addr + size) > mtd->size) - return -EINVAL; - addr += mtd->offset; - - return mtd->ops->erase(mtd->master, addr, size); -} - -/* -* Read data only -* -* @from offset to read from -* @return success size or error code -*/ -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (from < 0 || from >= (loff_t)mtd->size || len > mtd->size - from) - return -EINVAL; - if (!len) - return 0; - - desc.datbuf = buf; - desc.datlen = len; - ret = mtd->ops->read(mtd->master, from + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Write data only -* -* @to offset to write from -* @return success size or error code -*/ -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (to < 0 || to >= (loff_t)mtd->size || len > mtd->size - to) - return -EINVAL; - if (!mtd->ops->write) - return -EROFS; - if (!len) - return 0; - - desc.datbuf = (uint8_t*)buf; - desc.datlen = len; - ret = mtd->ops->write(mtd->master, to + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Read data and/or out-of-band -* -* @from offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (from < 0 || from >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen > (mtd->size - from))) - return -EINVAL; - - return mtd->ops->read(mtd->master, from + mtd->offset, desc); -} - -/** -* Write data and/or out-of-band -* -* @to offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (to < 0 || to >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen >(mtd->size - to))) - return -EINVAL; - - return mtd->ops->write(mtd->master, to + mtd->offset, desc); -} diff --git a/components/drivers/mtd/mtd_nand.c b/components/drivers/mtd/mtd_nand.c index 3e4582ceaf..ae5aa9c172 100644 --- a/components/drivers/mtd/mtd_nand.c +++ b/components/drivers/mtd/mtd_nand.c @@ -56,7 +56,7 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args) } #ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops mtd_nand_ops = +const static struct rt_device_ops mtd_nand_ops = { _mtd_init, _mtd_open, @@ -78,7 +78,7 @@ rt_err_t rt_mtd_nand_register_device(const char *name, /* set device class and generic device interface */ dev->type = RT_Device_Class_MTD; #ifdef RT_USING_DEVICE_OPS - dev->ops = &mtd_nand_ops; + dev->ops = &mtd_nand_ops; #else dev->init = _mtd_init; dev->open = _mtd_open; @@ -101,188 +101,262 @@ rt_err_t rt_mtd_nand_register_device(const char *name, static void mtd_dump_hex(const rt_uint8_t *ptr, rt_size_t buflen) { - unsigned char *buf = (unsigned char*)ptr; - int i, j; - for (i=0; i<buflen; i+=16) - { - rt_kprintf("%06x: ", i); - for (j=0; j<16; j++) - if (i+j < buflen) - rt_kprintf("%02x ", buf[i+j]); - else - rt_kprintf(" "); - rt_kprintf(" "); - for (j=0; j<16; j++) - if (i+j < buflen) - rt_kprintf("%c", __is_print(buf[i+j]) ? buf[i+j] : '.'); - rt_kprintf("\n"); - } + unsigned char *buf = (unsigned char *)ptr; + int i, j; + for (i = 0; i < buflen; i += 16) + { + rt_kprintf("%06x: ", i); + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%02x ", buf[i + j]); + else + rt_kprintf(" "); + rt_kprintf(" "); + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + rt_kprintf("\n"); + } } -int mtd_nandid(const char* name) +int mtd_nandid(const char *name) { - struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + struct rt_mtd_nand_device *nand; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - return rt_mtd_nand_read_id(nand); + return rt_mtd_nand_read_id(nand); } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nandid, nand_id, read ID - nandid(name)); -int mtd_nand_read(const char* name, int block, int page) +int mtd_nand_read(const char *name, int block, int page) { - rt_err_t result; - rt_uint8_t *page_ptr; - rt_uint8_t *oob_ptr; - struct rt_mtd_nand_device *nand; + rt_err_t result; + rt_uint8_t *page_ptr; + rt_uint8_t *oob_ptr; + struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - page_ptr = rt_malloc(nand->page_size + nand->oob_size); - if (page_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + page_ptr = rt_malloc(nand->page_size + nand->oob_size); + if (page_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - oob_ptr = page_ptr + nand->page_size; - rt_memset(page_ptr, 0xff, nand->page_size + nand->oob_size); + oob_ptr = page_ptr + nand->page_size; + rt_memset(page_ptr, 0xff, nand->page_size + nand->oob_size); - /* calculate the page number */ - page = block * nand->pages_per_block + page; - result = rt_mtd_nand_read(nand, page, page_ptr, nand->page_size, - oob_ptr, nand->oob_size); + /* calculate the page number */ + page = block * nand->pages_per_block + page; + result = rt_mtd_nand_read(nand, page, page_ptr, nand->page_size, + oob_ptr, nand->oob_size); - rt_kprintf("read page, rc=%d\n", result); - mtd_dump_hex(page_ptr, nand->page_size); - mtd_dump_hex(oob_ptr, nand->oob_size); + rt_kprintf("read page, rc=%d\n", result); + mtd_dump_hex(page_ptr, nand->page_size); + mtd_dump_hex(oob_ptr, nand->oob_size); - rt_free(page_ptr); - return 0; + rt_free(page_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_read, nand_read, read page in nand - nand_read(name, block, page)); -int mtd_nand_readoob(const char* name, int block, int page) +int mtd_nand_readoob(const char *name, int block, int page) { - struct rt_mtd_nand_device *nand; - rt_uint8_t *oob_ptr; + struct rt_mtd_nand_device *nand; + rt_uint8_t *oob_ptr; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - oob_ptr = rt_malloc(nand->oob_size); - if (oob_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + oob_ptr = rt_malloc(nand->oob_size); + if (oob_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - /* calculate the page number */ - page = block * nand->pages_per_block + page; - rt_mtd_nand_read(nand, page, RT_NULL, nand->page_size, - oob_ptr, nand->oob_size); - mtd_dump_hex(oob_ptr, nand->oob_size); + /* calculate the page number */ + page = block * nand->pages_per_block + page; + rt_mtd_nand_read(nand, page, RT_NULL, nand->page_size, + oob_ptr, nand->oob_size); + mtd_dump_hex(oob_ptr, nand->oob_size); - rt_free(oob_ptr); - return 0; + rt_free(oob_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_readoob, nand_readoob, read spare data in nand - nand_readoob(name, block, page)); -int mtd_nand_write(const char* name, int block, int page) +int mtd_nand_write(const char *name, int block, int page) { - rt_err_t result; - rt_uint8_t *page_ptr; - rt_uint8_t *oob_ptr; - rt_uint32_t index; - struct rt_mtd_nand_device *nand; + rt_err_t result; + rt_uint8_t *page_ptr; + rt_uint8_t *oob_ptr; + rt_uint32_t index; + struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - page_ptr = rt_malloc(nand->page_size + nand->oob_size); - if (page_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + page_ptr = rt_malloc(nand->page_size + nand->oob_size); + if (page_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - oob_ptr = page_ptr + nand->page_size; - /* prepare page data */ - for (index = 0; index < nand->page_size; index ++) - { - page_ptr[index] = index & 0xff; - } - /* prepare oob data */ - for (index = 0; index < nand->oob_size; index ++) - { - oob_ptr[index] = index & 0xff; - } + oob_ptr = page_ptr + nand->page_size; + /* prepare page data */ + for (index = 0; index < nand->page_size; index ++) + { + page_ptr[index] = index & 0xff; + } + /* prepare oob data */ + for (index = 0; index < nand->oob_size; index ++) + { + oob_ptr[index] = index & 0xff; + } - /* calculate the page number */ - page = block * nand->pages_per_block + page; - result = rt_mtd_nand_write(nand, page, page_ptr, nand->page_size, - oob_ptr, nand->oob_size); - if (result != RT_MTD_EOK) - { - rt_kprintf("write page failed!, rc=%d\n", result); - } + /* calculate the page number */ + page = block * nand->pages_per_block + page; + result = rt_mtd_nand_write(nand, page, page_ptr, nand->page_size, + oob_ptr, nand->oob_size); + if (result != RT_MTD_EOK) + { + rt_kprintf("write page failed!, rc=%d\n", result); + } - rt_free(page_ptr); - return 0; + rt_free(page_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_write, nand_write, write dump data to nand - nand_write(name, block, page)); -int mtd_nand_erase(const char* name, int block) +int mtd_nand_erase(const char *name, int block) { - struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + struct rt_mtd_nand_device *nand; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - return rt_mtd_nand_erase_block(nand, block); + return rt_mtd_nand_erase_block(nand, block); } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase, nand_erase, nand_erase(name, block)); -int mtd_nand_erase_all(const char* name) +int mtd_nand_erase_all(const char *name) { - rt_uint32_t index = 0; - struct rt_mtd_nand_device *nand; - - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + rt_uint32_t index = 0; + struct rt_mtd_nand_device *nand; - for (index = 0; index < (nand->block_end - nand->block_start); index ++) - { - rt_mtd_nand_erase_block(nand, index); - } - - return 0; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } + + for (index = 0; index < (nand->block_end - nand->block_start); index ++) + { + rt_mtd_nand_erase_block(nand, index); + } + + return 0; +} + +#ifdef FINSH_USING_MSH +static void mtd_nand(int argc, char **argv) +{ + /* If the number of arguments less than 2 */ + if (argc < 3) + { +help: + rt_kprintf("\n"); + rt_kprintf("mtd_nand [OPTION] [PARAM ...]\n"); + rt_kprintf(" id <name> Get nandid by given name\n"); + rt_kprintf(" read <name> <bn> <pn> Read data on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" readoob <name> <bn> <pn> Read oob on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" write <name> <bn> <pn> Run write test on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" erase <name> <bn> Erase on block <bn> of device <name>\n"); + rt_kprintf(" eraseall <name> Erase all block on device <name>\n"); + return ; + } + else if (!strcmp(argv[1], "id")) + { + mtd_nandid(argv[2]); + } + else if (!strcmp(argv[1], "read")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_read(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "readoob")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_readoob(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "write")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_write(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "erase")) + { + if (argc < 4) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_erase(argv[2], atoi(argv[3])); + } + else if (!strcmp(argv[1], "eraseall")) + { + mtd_nand_erase_all(argv[2]); + } + else + { + rt_kprintf("Input parameters are not supported!\n"); + goto help; + } } +MSH_CMD_EXPORT(mtd_nand, MTD nand device test function); +#endif /* FINSH_USING_MSH */ + +#ifndef FINSH_USING_MSH_ONLY +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nandid, nand_id, read ID - nandid(name)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_read, nand_read, read page in nand - nand_read(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_readoob, nand_readoob, read spare data in nand - nand_readoob(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_write, nand_write, write dump data to nand - nand_write(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase, nand_erase, nand_erase(name, block)); FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase_all, nand_erase_all, erase all of nand device - nand_erase_all(name, block)); -#endif +#endif /* FINSH_USING_MSH_ONLY */ -#endif +#endif /* defined(RT_MTD_NAND_DEBUG) && defined(RT_USING_FINSH) */ + +#endif /* RT_USING_MTD_NAND */ diff --git a/components/drivers/mtd/mtdnand.c b/components/drivers/mtd/mtdnand.c deleted file mode 100644 index 50012219fb..0000000000 --- a/components/drivers/mtd/mtdnand.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-09-10 heyuanjie87 first version - */ - -#include <rtdevice.h> - -#define MTDTONAND(x) ((rt_nand_t*)(x)) -#define NOTALIGNED(x) ((x & (chip->page_size - 1)) != 0) -#ifndef min -#define min(a,b) (a>b? b:a) -#endif - -static uint8_t *nand_fill_oob(rt_nand_t *chip, uint8_t *oob, size_t len, struct mtd_io_desc *desc) -{ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(chip->oob_poi + desc->ooboffs, oob, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - const struct mtd_oob_region *free = chip->freelayout; - uint32_t boffs; - size_t bytes; - - bytes = min(len, free->length); - boffs = free->offset; - - rt_memcpy(chip->oob_poi + boffs, oob, bytes); - oob += bytes; - - return oob; - } - } - - return NULL; -} - -static uint8_t *nand_transfer_oob(rt_nand_t *chip, uint8_t *oob, struct mtd_io_desc *desc, size_t len) -{ - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(oob, chip->oob_poi + desc->ooboffs, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - struct mtd_oob_region *free = (struct mtd_oob_region *)chip->freelayout; - uint32_t boffs = 0, roffs = desc->ooboffs; - size_t bytes = 0; - - for (; free->length && len; free++, len -= bytes) - { - /* Read request not from offset 0? */ - if (roffs) - { - if (roffs >= free->length) - { - roffs -= free->length; - continue; - } - boffs = free->offset + roffs; - bytes = min(len, (free->length - roffs)); - roffs = 0; - } - else - { - bytes = min(len, free->length); - boffs = free->offset; - } - - rt_memcpy(oob, chip->oob_poi + boffs, bytes); - oob += bytes; - } - - return oob; - } - } - - return NULL; -} - -static int nand_read_page_raw(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - chip->ops->read_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_raw(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - chip->ops->write_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_hwecc(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t stepsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *ecc_calc = chip->buffers.ecccalc; - const uint8_t *p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += stepsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->write_buf(chip, p, stepsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - rt_memcpy(&chip->oob_poi[eccpos], ecc_calc, chip->ecc.layout->length); - - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_read_page_hwecc(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t eccsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *p = buf; - uint8_t *ecc_calc = chip->buffers.ecccalc; - uint8_t *ecc_code = chip->buffers.ecccode; - int ret = 0; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->read_buf(chip, p, eccsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - rt_memcpy(ecc_code, &chip->oob_poi[eccpos], chip->ecc.layout->length); - - eccsteps = chip->ecc._step; - p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - int stat; - - stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); - if (stat != 0) - ret = -1; - } - - return ret; -} - -static int nand_write_page(rt_nand_t *chip, const uint8_t *buf, - int oob_required, int page, int raw) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, 0x00); - - if (raw) - { - nand_write_page_raw(chip, buf, oob_required, page); - } - else - { - chip->write_page(chip, buf, oob_required, page); - } - - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status; -} - -static int nand_do_read_desc(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page, bytes; - char oob_required; - char ecc_fail = 0; - int ret = 0; - uint32_t readlen = desc->datlen; - uint16_t oobreadlen = desc->ooblen; - uint16_t max_oobsize = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob, *buf, *notalign = 0; - - /* Reject reads, which are not page aligned */ - if (NOTALIGNED(from)) - { - return -EINVAL; - } - - buf = desc->datbuf; - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - page = (int)(from / chip->page_size); - - oob = desc->oobbuf; - oob_required = oob ? 1 : 0; - - while (1) - { - bytes = min(chip->page_size, readlen); - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, 0x00); - if (NOTALIGNED(bytes)) - { - notalign = buf; - buf = chip->pagebuf; - } - /* - * Now read the page into the buffer. Absent an error, - * the read methods return max bitflips per ecc step. - */ - if (desc->mode == MTD_OPM_RAW) - { - ret = nand_read_page_raw(chip, buf, oob_required, page); - } - else - { - ret = chip->read_page(chip, buf, oob_required, page); - } - - if (ret != 0) - { - ret = -EBADMSG; - break; - } - - if (oob) - { - int toread = min(oobreadlen, max_oobsize); - - if (toread) - { - oob = nand_transfer_oob(chip, oob, desc, toread); - oobreadlen -= toread; - } - } - - if (notalign) - { - rt_memcpy(notalign, buf, bytes); - } - - buf += bytes; - readlen -= bytes; - - if (!readlen) - break; - - page++; - } - - desc->datretlen = desc->datlen - (size_t)readlen; - if (oob) - desc->oobretlen = desc->ooblen - oobreadlen; - - return ret; -} - -/* - * write with ECC - * -*/ -static int nand_do_write_desc(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page; - uint16_t writelen = desc->datlen; - uint16_t oob_required = desc->oobbuf ? 1 : 0; - uint16_t oobwritelen = desc->ooblen; - uint16_t oobmaxlen = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob = desc->oobbuf; - uint8_t *buf = desc->datbuf; - int ret; - - if (!writelen) - return 0; - - /* Reject writes, which are not page aligned */ - if (NOTALIGNED(to)) - { - return -EINVAL; - } - - page = (int)(to / chip->page_size); - - /* Don't allow multipage oob writes with offset */ - if (oob && desc->ooboffs && (desc->ooboffs + desc->ooblen > oobmaxlen)) - { - ret = -EINVAL; - goto err_out; - } - - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - while (1) - { - uint16_t bytes = min(chip->page_size, writelen); - - if (oob) - { - size_t len = min(oobwritelen, oobmaxlen); - oob = nand_fill_oob(chip, oob, len, desc); - oobwritelen -= len; - } - else - { - /* We still need to erase leftover OOB data */ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - } - - if (NOTALIGNED(bytes)) - { - uint8_t *dbtmp = buf; - buf = chip->pagebuf; - rt_memset(&buf[bytes], 0xff, chip->page_size - bytes); - rt_memcpy(buf, dbtmp, bytes); - } - ret = nand_write_page(chip, buf, oob_required, page, (desc->mode == MTD_OPM_RAW)); - if (ret) - break; - - writelen -= bytes; - if (!writelen) - break; - - buf += bytes; - page++; - } - - desc->datretlen = desc->datlen - writelen; - if (oob) - desc->oobretlen = desc->ooblen; - -err_out: - - return ret; -} - -static int nand_read_oob_std(rt_nand_t *chip, int page) -{ - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, chip->page_size); - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -/* - * read one page of OOB -*/ -static int nand_only_read_oob(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page; - int readlen = desc->ooblen; - int len; - uint8_t *buf = desc->oobbuf; - int ret = 0; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - if (desc->ooboffs >= len) //attempt to start read outside oob - { - return -EINVAL; - } - - page = (int)(from / chip->page_size); - - ret = nand_read_oob_std(chip, page); - if (ret == 0) - { - len = min(len, readlen); - buf = nand_transfer_oob(chip, buf, desc, len); - desc->oobretlen = len; - } - - return ret; -} - -static int nand_write_oob_std(rt_nand_t *chip, int page) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, chip->page_size); - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - /* Send command to program the OOB data */ - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status & NAND_STATUS_FAIL ? -EIO : 0; -} - -static int nand_only_write_oob(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page, ret, len; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - /* Do not allow write past end of page */ - if ((desc->ooboffs + desc->ooblen) > len) - { - return -EINVAL; - } - - if (desc->ooblen == 0) - { - return -EINVAL; - } - - /* get page */ - page = (int)(to / chip->page_size); - - nand_fill_oob(chip, desc->oobbuf, desc->ooblen, desc); - - ret = nand_write_oob_std(chip, page); - if (ret == 0) - desc->oobretlen = len; - - return ret; -} - -static int nand_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - rt_nand_t *chip; - int status; - int page; - uint32_t blksize; - - chip = MTDTONAND(mtd); - blksize = mtd->block_size; - page = addr / chip->page_size; - - while (size >= blksize) - { - status = chip->ops->cmdfunc(chip, NAND_CMD_BLK_ERASE, page, 0); - if (status & NAND_STATUS_FAIL) - { - break; - } - size -= blksize; - page += chip->pages_pb; - } - - return size; -} - -static int nand_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_read_oob(chip, from, desc); - else - ret = nand_do_read_desc(chip, from, desc); - -out: - - return ret; -} - -static int nand_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_write_oob(chip, to, desc); - else - ret = nand_do_write_desc(chip, to, desc); - -out: - - return ret; -} - -static int nand_block_isbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip = MTDTONAND(mtd); - - if (chip->ops->isbad) - { - ret = chip->ops->isbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - nand_read_oob_std(chip, page); - ret = chip->oob_poi[0] != 0xFF; - } - - return ret; -} - -static int nand_block_markbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - if (chip->ops->markbad) - { - ret = chip->ops->markbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - chip->oob_poi[0] = 0; - ret = nand_write_oob_std(chip, page); - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - nand_erase, - nand_read, - nand_write, - nand_block_isbad, - nand_block_markbad, -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size) -{ - uint8_t *buf; - - buf = rt_malloc(oob_size * 3); - if (buf == RT_NULL) - return -ENOMEM; - - nand->oob_poi = buf; - buf += oob_size; - nand->buffers.ecccalc = buf; - buf += oob_size; - nand->buffers.ecccode = buf; - nand->pagebuf = 0; /* alloc when unaligen access */ - - nand->pages_pb = blk_size / page_size; - nand->ecc._step = page_size / nand->ecc.stepsize; - nand->page_size = page_size; - nand->oobsize = oob_size; - - nand->parent.type = MTD_TYPE_NAND; - nand->parent.ops = &_ops; - nand->parent.sector_size = page_size; - nand->parent.block_size = blk_size; - nand->parent.oob_size = oob_size; - - switch (nand->ecc.mode) - { - case NAND_ECCM_NONE: - { - nand->read_page = nand_read_page_raw; - nand->write_page = nand_write_page_raw; - }break; - case NAND_ECCM_HW: - { - nand->read_page = nand_read_page_hwecc; - nand->write_page = nand_write_page_hwecc; - }break; - default: - { - rt_free(buf); - return -1; - } - } - - return 0; -} diff --git a/components/drivers/mtd/mtdnor.c b/components/drivers/mtd/mtdnor.c deleted file mode 100644 index 481d26167e..0000000000 --- a/components/drivers/mtd/mtdnor.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include <drivers/mtdnor.h> - -#ifdef MTD_USING_NOR -static int _nor_erase(rt_mtd_t *mtd, loff_t addr, size_t len) -{ - rt_nor_t *nor; - - nor = (rt_nor_t *)mtd; - return nor->ops->erase(nor, addr, len); -} - -static int _nor_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->read(nor, from, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static int _nor_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->write(nor, to, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - _nor_erase, - _nor_read, - _nor_write, - 0, - 0 -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize) -{ - nor->parent.sector_size = 1; - nor->parent.block_size = blksize; - nor->parent.ops = &_ops; - nor->parent.type = MTD_TYPE_NOR; - nor->parent.oob_size = 0; - - return 0; -} -#endif diff --git a/components/drivers/phy/SConscript b/components/drivers/phy/SConscript new file mode 100644 index 0000000000..ec12ed24c2 --- /dev/null +++ b/components/drivers/phy/SConscript @@ -0,0 +1,8 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd + '/../include'] +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_PHY'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/phy/phy.c b/components/drivers/phy/phy.c new file mode 100644 index 0000000000..3ed4a1a265 --- /dev/null +++ b/components/drivers/phy/phy.c @@ -0,0 +1,78 @@ + +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-27 wangqiang first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtdevice.h> + +#define DBG_TAG "PHY" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + + +static rt_size_t phy_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t count) +{ + struct rt_phy_device *phy = (struct rt_phy_device *)dev->user_data; + struct rt_phy_msg *msg = (struct rt_phy_msg *)buffer; + return phy->bus->ops->read(phy->bus, phy->addr, msg->reg, &(msg->value), 4); +} +static rt_size_t phy_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t count) +{ + struct rt_phy_device *phy = (struct rt_phy_device *)dev->user_data; + struct rt_phy_msg *msg = (struct rt_phy_msg *)buffer; + return phy->bus->ops->write(phy->bus, phy->addr, msg->reg, &(msg->value), 4); +} + + + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops phy_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + phy_device_read, + phy_device_write, + RT_NULL, +}; +#endif + +/* +* phy device register +*/ +rt_err_t rt_hw_phy_register(struct rt_phy_device *phy, const char *name) +{ + rt_err_t ret; + struct rt_device *device; + + device = &(phy->parent); + + device->type = RT_Device_Class_PHY; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = phy_ops; +#else + device->init = NULL; + device->open = NULL; + device->close = NULL; + device->read = phy_device_read; + device->write = phy_device_write; + device->control = NULL; +#endif + device->user_data = phy; + + /* register a character device */ + ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); + + return ret; +} diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index c300414444..dd7cc2ae63 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -7,6 +7,7 @@ * Date Author Notes * 2012-06-02 Bernard the first version * 2018-08-02 Tanek split run and sleep modes, support custom mode + * 2019-04-28 Zero-Free improve PM mode and device ops interface */ #include <rthw.h> @@ -16,27 +17,46 @@ #ifdef RT_USING_PM static struct rt_pm _pm; +static rt_uint8_t _pm_default_sleep = RT_PM_DEFAULT_SLEEP_MODE; +static struct rt_pm_notify _pm_notify; +static rt_uint8_t _pm_init_flag = 0; + +#define RT_PM_TICKLESS_THRESH (2) + +RT_WEAK rt_uint32_t rt_pm_enter_critical(rt_uint8_t sleep_mode) +{ + return rt_hw_interrupt_disable(); +} + +RT_WEAK void rt_pm_exit_critical(rt_uint32_t ctx, rt_uint8_t sleep_mode) +{ + rt_hw_interrupt_enable(ctx); +} /** * This function will suspend all registered devices */ -static void _pm_device_suspend(void) +static int _pm_device_suspend(rt_uint8_t mode) { - int index; + int index, ret = RT_EOK; 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); + ret = _pm.device_pm[index].ops->suspend(_pm.device_pm[index].device, mode); + if(ret != RT_EOK) + break; } } + + return ret; } /** * This function will resume all registered devices */ -static void _pm_device_resume(void) +static void _pm_device_resume(rt_uint8_t mode) { int index; @@ -44,16 +64,15 @@ static void _pm_device_resume(void) { if (_pm.device_pm[index].ops->resume != RT_NULL) { - _pm.device_pm[index].ops->resume(_pm.device_pm[index].device); + _pm.device_pm[index].ops->resume(_pm.device_pm[index].device, mode); } } } -#if PM_RUN_MODE_COUNT > 1 /** * This function will update the frequency of all registered devices */ -static void _pm_device_frequency_change(void) +static void _pm_device_frequency_change(rt_uint8_t mode) { rt_uint32_t index; @@ -61,152 +80,151 @@ static void _pm_device_frequency_change(void) 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); + _pm.device_pm[index].ops->frequency_change(_pm.device_pm[index].device, mode); } } -#endif /** - * This function will enter corresponding power mode. + * This function will update the system clock frequency when idle */ -void rt_pm_enter(void) +static void _pm_frequency_scaling(struct rt_pm *pm) { - rt_ubase_t level; - struct rt_pm *pm; - rt_uint32_t index; - rt_tick_t timeout_tick; + rt_base_t level; - pm = &_pm; + if (pm->flags & RT_PM_FREQUENCY_PENDING) + { + level = rt_hw_interrupt_disable(); + /* change system runing mode */ + pm->ops->run(pm, pm->run_mode); + /* changer device frequency */ + _pm_device_frequency_change(pm->run_mode); + pm->flags &= ~RT_PM_FREQUENCY_PENDING; + rt_hw_interrupt_enable(level); + } +} - /* 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++) +/** + * This function selects the sleep mode according to the rt_pm_request/rt_pm_release count. + */ +static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm) +{ + int index; + rt_uint8_t mode; + + mode = _pm_default_sleep; + for (index = PM_SLEEP_MODE_NONE; index < PM_SLEEP_MODE_MAX; 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 ; + mode = index; + break; } } - /* enable interrupt after check run modes */ - rt_hw_interrupt_enable(level); + pm->sleep_mode = mode; - 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++) + return mode; +} + +/** + * This function changes the power sleep mode base on the result of selection + */ +static void _pm_change_sleep_mode(struct rt_pm *pm, rt_uint8_t mode) +{ + rt_tick_t timeout_tick, delta_tick; + rt_base_t level; + int ret = RT_EOK; + + if (mode == PM_SLEEP_MODE_NONE) { - if (pm->modes[index]) - { - /* let mcu sleep when system is idle */ + pm->sleep_mode = mode; + pm->ops->sleep(pm, PM_SLEEP_MODE_NONE); + } + else + { + level = rt_pm_enter_critical(mode); - /* run mode to sleep mode */ - if (pm->current_mode < PM_SLEEP_MODE_START) - { - /* exit run mode */ - pm->ops->exit(pm); - } + /* Notify app will enter sleep mode */ + if (_pm_notify.notify) + _pm_notify.notify(RT_PM_ENTER_SLEEP, mode, _pm_notify.data); - /* set current power mode */ - pm->current_mode = index; - pm->exit_count = 1; + /* Suspend all peripheral device */ + ret = _pm_device_suspend(mode); + if (ret != RT_EOK) + { + _pm_device_resume(mode); + if (_pm_notify.notify) + _pm_notify.notify(RT_PM_EXIT_SLEEP, mode, _pm_notify.data); + rt_pm_exit_critical(level, mode); - /* suspend all of devices with PM feature */ - _pm_device_suspend(); + return; + } - /* should start pm timer */ - if (pm->timer_mask & (1 << index)) + /* Tickless*/ + if (pm->timer_mask & (0x01 << mode)) + { + timeout_tick = rt_timer_next_timeout_tick(); + if (timeout_tick == RT_TICK_MAX) { - /* get next os tick */ - timeout_tick = rt_timer_next_timeout_tick(); - if (timeout_tick != RT_TICK_MAX) + if (pm->ops->timer_start) { - 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 + pm->ops->timer_start(pm, RT_TICK_MAX); } - /* startup pm timer */ - pm->ops->timer_start(pm, timeout_tick); } + else + { + timeout_tick = timeout_tick - rt_tick_get(); + if (timeout_tick < RT_PM_TICKLESS_THRESH) + { + mode = PM_SLEEP_MODE_IDLE; + } + else + { + pm->ops->timer_start(pm, timeout_tick); + } + } + } - /* enter sleep and wait to be waken up */ - pm->ops->enter(pm); - - /* exit from low power mode */ - rt_pm_exit(); + /* enter lower power state */ + pm->ops->sleep(pm, mode); - rt_hw_interrupt_enable(level); - return ; + /* wake up from lower power state*/ + if (pm->timer_mask & (0x01 << mode)) + { + delta_tick = pm->ops->timer_get_tick(pm); + pm->ops->timer_stop(pm); + if (delta_tick) + { + rt_tick_set(rt_tick_get() + delta_tick); + rt_timer_check(); + } } - } - rt_hw_interrupt_enable(level); + /* resume all device */ + _pm_device_resume(pm->sleep_mode); + + if (_pm_notify.notify) + _pm_notify.notify(RT_PM_EXIT_SLEEP, mode, _pm_notify.data); + + rt_pm_exit_critical(level, mode); + } } /** - * This function exits from sleep mode. + * This function will enter corresponding power mode. */ -void rt_pm_exit(void) +void rt_system_power_manager(void) { - rt_ubase_t level; - struct rt_pm *pm; - rt_tick_t delta_tick; + rt_uint8_t mode; - 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(); - } - } + if (_pm_init_flag == 0) + return; - /* exit from sleep mode */ - pm->ops->exit(pm); - /* resume the device with PM feature */ - _pm_device_resume(); - } - } + /* CPU frequency scaling according to the runing mode settings */ + _pm_frequency_scaling(&_pm); - rt_hw_interrupt_enable(level); + /* Low Power Mode Processing */ + mode = _pm_select_sleep_mode(&_pm); + _pm_change_sleep_mode(&_pm, mode); } /** @@ -215,60 +233,21 @@ void rt_pm_exit(void) * * @param parameter the parameter of run mode or sleep mode */ -void rt_pm_request(rt_ubase_t mode) +void rt_pm_request(rt_uint8_t mode) { - rt_ubase_t level; + rt_base_t level; struct rt_pm *pm; - pm = &_pm; + if (_pm_init_flag == 0) + return; - if (mode > PM_MODE_MAX) + if (mode > (PM_SLEEP_MODE_MAX - 1)) 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() - */ - } - } - + pm = &_pm; + if (pm->modes[mode] < 255) + pm->modes[mode] ++; rt_hw_interrupt_enable(level); } @@ -279,21 +258,21 @@ void rt_pm_request(rt_ubase_t mode) * @param parameter the parameter of run mode or sleep mode * */ -void rt_pm_release(rt_ubase_t mode) +void rt_pm_release(rt_uint8_t mode) { rt_ubase_t level; struct rt_pm *pm; - pm = &_pm; + if (_pm_init_flag == 0) + return; - if (mode > PM_MODE_MAX) + if (mode > (PM_SLEEP_MODE_MAX - 1)) return; level = rt_hw_interrupt_disable(); - + pm = &_pm; if (pm->modes[mode] > 0) pm->modes[mode] --; - rt_hw_interrupt_enable(level); } @@ -303,9 +282,9 @@ void rt_pm_release(rt_ubase_t mode) * @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) +void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops) { - rt_ubase_t level; + rt_base_t level; struct rt_device_pm *device_pm; RT_DEBUG_NOT_IN_INTERRUPT; @@ -322,8 +301,6 @@ void rt_pm_register_device(struct rt_device *device, const struct rt_device_pm_o _pm.device_pm_number += 1; } - rt_sem_release(&(_pm.device_lock)); - rt_hw_interrupt_enable(level); } @@ -332,7 +309,7 @@ void rt_pm_register_device(struct rt_device *device, const struct rt_device_pm_o * * @param device the device with PM feature */ -void rt_pm_unregister_device(struct rt_device *device) +void rt_pm_device_unregister(struct rt_device *device) { rt_ubase_t level; rt_uint32_t index; @@ -363,6 +340,23 @@ void rt_pm_unregister_device(struct rt_device *device) } /** + * This function set notification callback for application + */ +void rt_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data) +{ + _pm_notify.notify = notify; + _pm_notify.data = data; +} + +/** + * This function set default sleep mode when no pm_request + */ +void rt_pm_default_set(rt_uint8_t sleep_mode) +{ + _pm_default_sleep = sleep_mode; +} + +/** * RT-Thread device interface for PM device */ static rt_size_t _rt_pm_device_read(rt_device_t dev, @@ -377,7 +371,7 @@ static rt_size_t _rt_pm_device_read(rt_device_t dev, pm = (struct rt_pm *)dev; RT_ASSERT(pm != RT_NULL); - if (pos <= PM_MODE_MAX) + if (pos < PM_SLEEP_MODE_MAX) { int mode; @@ -399,11 +393,11 @@ static rt_size_t _rt_pm_device_write(rt_device_t dev, { /* get request */ request = *(unsigned char *)buffer; - if (request == '1') + if (request == 0x01) { rt_pm_request(pos); } - else if (request == '0') + else if (request == 0x00) { rt_pm_release(pos); } @@ -434,6 +428,48 @@ static rt_err_t _rt_pm_device_control(rt_device_t dev, return RT_EOK; } +int rt_pm_run_enter(rt_uint8_t mode) +{ + rt_base_t level; + struct rt_pm *pm; + + if (_pm_init_flag == 0) + return -RT_EIO; + + if (mode > PM_RUN_MODE_MAX) + return -RT_EINVAL; + + level = rt_hw_interrupt_disable(); + pm = &_pm; + if (mode < pm->run_mode) + { + /* change system runing mode */ + pm->ops->run(pm, mode); + /* changer device frequency */ + _pm_device_frequency_change(mode); + } + else + { + pm->flags |= RT_PM_FREQUENCY_PENDING; + } + pm->run_mode = mode; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pm_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _rt_pm_device_read, + _rt_pm_device_write, + _rt_pm_device_control, +}; +#endif + /** * This function will initialize power management. * @@ -455,23 +491,24 @@ void rt_system_pm_init(const struct rt_pm_ops *ops, device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->ops = &pm_ops; +#else 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; +#endif 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->sleep_mode = _pm_default_sleep; + pm->run_mode = RT_PM_DEFAULT_RUN_MODE; pm->timer_mask = timer_mask; pm->ops = ops; @@ -479,24 +516,15 @@ void rt_system_pm_init(const struct rt_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); + _pm_init_flag = 1; } #ifdef RT_USING_FINSH #include <finsh.h> +static const char *_pm_sleep_str[] = PM_SLEEP_MODE_NAMES; +static const char *_pm_run_str[] = PM_RUN_MODE_NAMES; + static void rt_pm_release_mode(int argc, char **argv) { int mode = 0; @@ -521,9 +549,20 @@ static void rt_pm_request_mode(int argc, char **argv) } MSH_CMD_EXPORT_ALIAS(rt_pm_request_mode, pm_request, request power management mode); +static void rt_pm_run_mode_switch(int argc, char **argv) +{ + int mode = 0; + if (argc >= 2) + { + mode = atoi(argv[1]); + } + + rt_pm_run_enter(mode); +} +MSH_CMD_EXPORT_ALIAS(rt_pm_run_mode_switch, pm_run, switch power management run mode); + static void rt_pm_dump_status(void) { - static const char *pm_str[] = PM_MODE_NAMES; rt_uint32_t index; struct rt_pm *pm; @@ -531,17 +570,18 @@ static void rt_pm_dump_status(void) rt_kprintf("| Power Management Mode | Counter | Timer |\n"); rt_kprintf("+-----------------------+---------+-------+\n"); - for (index = 0; index <= PM_MODE_MAX; index ++) + for (index = 0; index < PM_SLEEP_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("| %021s | %7d | %5d |\n", _pm_sleep_str[index], pm->modes[index], has_timer); } rt_kprintf("+-----------------------+---------+-------+\n"); - rt_kprintf("pm current mode: %s\n", pm_str[pm->current_mode]); + rt_kprintf("pm current sleep mode: %s\n", _pm_sleep_str[pm->sleep_mode]); + rt_kprintf("pm current run mode: %s\n", _pm_run_str[pm->run_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); diff --git a/components/drivers/rtc/alarm.c b/components/drivers/rtc/alarm.c index c497ebf727..71b6e7236a 100644 --- a/components/drivers/rtc/alarm.c +++ b/components/drivers/rtc/alarm.c @@ -7,6 +7,7 @@ * Date Author Notes * 2012-10-27 heyuanjie87 first version. * 2013-05-17 aozima initial alarm event & mutex in system init. + * 2020-10-15 zhangsz add alarm flags hour minute second. */ #include <rtthread.h> @@ -97,6 +98,61 @@ static void alarm_wakeup(struct rt_alarm *alarm, struct tm *now) } } break; + case RT_ALARM_SECOND: + { + alarm->wktime.tm_hour = now->tm_hour; + alarm->wktime.tm_min = now->tm_min; + alarm->wktime.tm_sec = alarm->wktime.tm_sec + 1; + if (alarm->wktime.tm_sec > 59) + { + alarm->wktime.tm_sec = 0; + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + wakeup = RT_TRUE; + } + break; + case RT_ALARM_MINUTE: + { + alarm->wktime.tm_hour = now->tm_hour; + if (alarm->wktime.tm_sec == now->tm_sec) + { + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_HOUR: + { + if ((alarm->wktime.tm_min == now->tm_min) && + (alarm->wktime.tm_sec == now->tm_sec)) + { + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + wakeup = RT_TRUE; + } + } + break; case RT_ALARM_DAILY: { if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) @@ -177,7 +233,7 @@ static void alarm_update(rt_uint32_t event) /* calculate seconds from 00:00:00 */ sec_alarm = alarm_mkdaysec(&alarm->wktime); - if ((alarm->flag & RT_ALARM_STATE_START) && (alarm != _container.current)) + if (alarm->flag & RT_ALARM_STATE_START) { sec_tmp = sec_alarm - sec_now; if (sec_tmp > 0) @@ -212,6 +268,11 @@ static void alarm_update(rt_uint32_t event) if (alarm_set(alm_prev) == RT_EOK) _container.current = alm_prev; } + else + { + if (_container.current != RT_NULL) + alarm_set(_container.current); + } } rt_mutex_release(&_container.mutex); } @@ -279,6 +340,51 @@ static rt_err_t alarm_setup(rt_alarm_t alarm, struct tm *wktime) switch (alarm->flag & 0xFF00) { + case RT_ALARM_SECOND: + { + alarm->wktime.tm_hour = now.tm_hour; + alarm->wktime.tm_min = now.tm_min; + alarm->wktime.tm_sec = now.tm_sec + 1; + if (alarm->wktime.tm_sec > 59) + { + alarm->wktime.tm_sec = 0; + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + } + break; + case RT_ALARM_MINUTE: + { + alarm->wktime.tm_hour = now.tm_hour; + alarm->wktime.tm_min = now.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + break; + case RT_ALARM_HOUR: + { + alarm->wktime.tm_hour = now.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + break; case RT_ALARM_DAILY: { /* do nothing but needed */ @@ -426,17 +532,17 @@ rt_err_t rt_alarm_start(rt_alarm_t alarm) if (alarm == RT_NULL) return (ret); rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - if (!(alarm->flag & RT_ALARM_STATE_INITED)) + + if (!(alarm->flag & RT_ALARM_STATE_START)) { if (alarm_setup(alarm, &alarm->wktime) != RT_EOK) goto _exit; - } - if ((alarm->flag & 0x01) == RT_ALARM_STATE_STOP) - { + timestamp = time(RT_NULL); localtime_r(×tamp, &now); alarm->flag |= RT_ALARM_STATE_START; + /* set alarm */ if (_container.current == RT_NULL) { @@ -518,10 +624,10 @@ _exit: */ rt_err_t rt_alarm_delete(rt_alarm_t alarm) { - rt_err_t ret = RT_ERROR; + rt_err_t ret = RT_EOK; if (alarm == RT_NULL) - return (ret); + return RT_ERROR; rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); /* stop the alarm */ alarm->flag &= ~RT_ALARM_STATE_START; @@ -551,9 +657,11 @@ rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, struct rt_alarm_setup * if (setup == RT_NULL) return (RT_NULL); + alarm = rt_malloc(sizeof(struct rt_alarm)); if (alarm == RT_NULL) return (RT_NULL); + rt_list_init(&alarm->list); alarm->wktime = setup->wktime; @@ -586,13 +694,33 @@ static void rt_alarmsvc_thread_init(void *param) } } +void rt_alarm_dump(void) +{ + rt_list_t *next; + rt_alarm_t alarm; + rt_uint8_t index = 0; + + rt_kprintf("| alarm_id | YYYY-MM-DD hh:mm:ss | weekday | flags |\n"); + rt_kprintf("+----------+---------------------+---------+---------+\n"); + for (next = _container.head.next; next != &_container.head; next = next->next) + { + alarm = rt_list_entry(next, struct rt_alarm, list); + rt_kprintf("| No %5d | %04d-%02d-%02d %02d:%02d:%02d | %7d | 0x%04x |\n", + index++, alarm->wktime.tm_year + 1900, alarm->wktime.tm_mon + 1, alarm->wktime.tm_mday, + alarm->wktime.tm_hour, alarm->wktime.tm_min, alarm->wktime.tm_sec, + alarm->wktime.tm_wday, alarm->flag); + } + rt_kprintf("+----------+---------------------+---------+---------+\n"); +} + +FINSH_FUNCTION_EXPORT_ALIAS(rt_alarm_dump, __cmd_alarm_dump, dump alarm info); /** \brief initialize alarm service system * * \param none * \return none */ -void rt_alarm_system_init(void) +int rt_alarm_system_init(void) { rt_thread_t tid; @@ -602,8 +730,12 @@ void rt_alarm_system_init(void) tid = rt_thread_create("alarmsvc", rt_alarmsvc_thread_init, RT_NULL, - 512, 8, 1); + 2048, 10, 5); if (tid != RT_NULL) rt_thread_startup(tid); + + return 0; } + +INIT_PREV_EXPORT(rt_alarm_system_init); #endif diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c index e17c0fe7dd..682515ce98 100644 --- a/components/drivers/rtc/rtc.c +++ b/components/drivers/rtc/rtc.c @@ -179,7 +179,7 @@ void list_date(void) time_t now; now = time(RT_NULL); - rt_kprintf("%s\n", ctime(&now)); + rt_kprintf("%.*s\n", 25, ctime(&now)); } FINSH_FUNCTION_EXPORT(list_date, show date and time.) @@ -194,7 +194,7 @@ static void date(uint8_t argc, char **argv) time_t now; /* output current time */ now = time(RT_NULL); - rt_kprintf("%s", ctime(&now)); + rt_kprintf("%.*s", 25, ctime(&now)); } else if (argc >= 7) { diff --git a/components/drivers/sdio/block_dev.c b/components/drivers/sdio/block_dev.c index 23be319fc6..602acb9aa7 100644 --- a/components/drivers/sdio/block_dev.c +++ b/components/drivers/sdio/block_dev.c @@ -13,14 +13,12 @@ #include <drivers/mmcsd_core.h> -#define DBG_ENABLE -#define DBG_SECTION_NAME "SDIO" +#define DBG_TAG "SDIO" #ifdef RT_SDIO_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO +#define DBG_LVL DBG_INFO #endif /* RT_SDIO_DEBUG */ -#define DBG_COLOR #include <rtdbg.h> static rt_list_t blk_devices = RT_LIST_OBJECT_INIT(blk_devices); @@ -369,7 +367,7 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) return err; } - LOG_I("probe mmcsd block device!"); + LOG_D("probe mmcsd block device!"); /* get the first sector to read partition table */ sector = (rt_uint8_t *)rt_malloc(SECTOR_SIZE); @@ -462,8 +460,6 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) rt_device_register(&blk_dev->dev, "sd0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); rt_list_insert_after(&blk_devices, &blk_dev->list); - - break; } else { @@ -474,7 +470,7 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) } #ifdef RT_USING_DFS_MNTTABLE - if (0) // if (blk_dev) + if (blk_dev) { LOG_I("try to mount file system!"); /* try to mount file system on this block device */ @@ -509,9 +505,10 @@ void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card) const char * mounted_path = dfs_filesystem_get_mounted_path(&(blk_dev->dev)); if (mounted_path) { - dfs_unmount(mounted_path); + dfs_unmount(mounted_path); + LOG_D("unmount file system %s for device %s.\r\n", mounted_path, blk_dev->dev.parent.name); } - + rt_sem_delete(blk_dev->part.lock); rt_device_unregister(&blk_dev->dev); rt_list_remove(&blk_dev->list); rt_free(blk_dev); diff --git a/components/drivers/sdio/mmc.c b/components/drivers/sdio/mmc.c index bbf0ff838c..c1c56d37fd 100644 --- a/components/drivers/sdio/mmc.c +++ b/components/drivers/sdio/mmc.c @@ -4,21 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2015-06-15 hichard first version + * Date Author Notes + * 2015-06-15 hichard first version */ #include <drivers/mmcsd_core.h> #include <drivers/mmc.h> -#define DBG_ENABLE -#define DBG_SECTION_NAME "SDIO" +#define DBG_TAG "SDIO" #ifdef RT_SDIO_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO +#define DBG_LVL DBG_INFO #endif /* RT_SDIO_DEBUG */ -#define DBG_COLOR #include <rtdbg.h> static const rt_uint32_t tran_unit[] = @@ -184,6 +182,8 @@ static int mmc_get_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t **new_ext_csd) */ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) { + rt_uint64_t card_capacity = 0; + if(card == RT_NULL || ext_csd == RT_NULL) { LOG_E("emmc parse ext csd fail, invaild args"); @@ -191,11 +191,12 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) } card->flags |= CARD_FLAG_HIGHSPEED; - card->hs_max_data_rate = 200000000; + card->hs_max_data_rate = 52000000; - card->card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]); - card->card_capacity *= card->card_blksize; - card->card_capacity >>= 10; /* unit:KB */ + card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]); + card_capacity *= card->card_blksize; + card_capacity >>= 10; /* unit:KB */ + card->card_capacity = card_capacity; LOG_I("emmc card capacity %d KB.", card->card_capacity); return 0; @@ -317,8 +318,17 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) * the device to work in 8bit transfer mode. If the * mmc switch command returns error then switch to * 4bit transfer mode. On success set the corresponding - * bus width on the host. + * bus width on the host. Meanwhile, mmc core would + * bail out early if corresponding bus capable wasn't + * set by drivers. */ + if ((!(host->flags & MMCSD_BUSWIDTH_8) && + ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8) || + (!(host->flags & MMCSD_BUSWIDTH_4) && + (ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_4 || + ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8))) + continue; + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx]); @@ -503,16 +513,10 @@ static rt_int32_t mmcsd_mmc_init_card(struct rt_mmcsd_host *host, card->flags |= CARD_FLAG_SDHC; /* set bus speed */ - max_data_rate = (unsigned int)-1; if (card->flags & CARD_FLAG_HIGHSPEED) - { - if (max_data_rate > card->hs_max_data_rate) - max_data_rate = card->hs_max_data_rate; - } - else if (max_data_rate > card->max_data_rate) - { + max_data_rate = card->hs_max_data_rate; + else max_data_rate = card->max_data_rate; - } mmcsd_set_clock(host, max_data_rate); diff --git a/components/drivers/sdio/mmcsd_core.c b/components/drivers/sdio/mmcsd_core.c index d1f5978374..99bc6ce744 100644 --- a/components/drivers/sdio/mmcsd_core.c +++ b/components/drivers/sdio/mmcsd_core.c @@ -14,14 +14,12 @@ #include <drivers/mmc.h> #include <drivers/sdio.h> -#define DBG_ENABLE -#define DBG_SECTION_NAME "SDIO" +#define DBG_TAG "SDIO" #ifdef RT_SDIO_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO +#define DBG_LVL DBG_INFO #endif /* RT_SDIO_DEBUG */ -#define DBG_COLOR #include <rtdbg.h> #ifndef RT_MMCSD_STACK_SIZE @@ -595,7 +593,7 @@ static void mmcsd_power_off(struct rt_mmcsd_host *host) int mmcsd_wait_cd_changed(rt_int32_t timeout) { struct rt_mmcsd_host *host; - if (rt_mb_recv(&mmcsd_hotpluge_mb, (rt_uint32_t*)&host, timeout) == RT_EOK) + if (rt_mb_recv(&mmcsd_hotpluge_mb, (rt_ubase_t *)&host, timeout) == RT_EOK) { if(host->card == RT_NULL) { @@ -612,7 +610,7 @@ RTM_EXPORT(mmcsd_wait_cd_changed); void mmcsd_change(struct rt_mmcsd_host *host) { - rt_mb_send(&mmcsd_detect_mb, (rt_uint32_t)host); + rt_mb_send(&mmcsd_detect_mb, (rt_ubase_t)host); } void mmcsd_detect(void *param) @@ -623,7 +621,7 @@ void mmcsd_detect(void *param) while (1) { - if (rt_mb_recv(&mmcsd_detect_mb, (rt_uint32_t*)&host, RT_WAITING_FOREVER) == RT_EOK) + if (rt_mb_recv(&mmcsd_detect_mb, (rt_ubase_t *)&host, RT_WAITING_FOREVER) == RT_EOK) { if (host->card == RT_NULL) { @@ -651,7 +649,7 @@ void mmcsd_detect(void *param) if (init_sd(host, ocr)) mmcsd_power_off(host); mmcsd_host_unlock(host); - rt_mb_send(&mmcsd_hotpluge_mb, (rt_uint32_t)host); + rt_mb_send(&mmcsd_hotpluge_mb, (rt_ubase_t)host); continue; } @@ -664,7 +662,7 @@ void mmcsd_detect(void *param) if (init_mmc(host, ocr)) mmcsd_power_off(host); mmcsd_host_unlock(host); - rt_mb_send(&mmcsd_hotpluge_mb, (rt_uint32_t)host); + rt_mb_send(&mmcsd_hotpluge_mb, (rt_ubase_t)host); continue; } mmcsd_host_unlock(host); @@ -685,7 +683,7 @@ void mmcsd_detect(void *param) host->card = RT_NULL; } mmcsd_host_unlock(host); - rt_mb_send(&mmcsd_hotpluge_mb, (rt_uint32_t)host); + rt_mb_send(&mmcsd_hotpluge_mb, (rt_ubase_t)host); } } } diff --git a/components/drivers/sdio/sd.c b/components/drivers/sdio/sd.c index 69a4561fb0..f7e4e46720 100644 --- a/components/drivers/sdio/sd.c +++ b/components/drivers/sdio/sd.c @@ -11,14 +11,12 @@ #include <drivers/mmcsd_core.h> #include <drivers/sd.h> -#define DBG_ENABLE -#define DBG_SECTION_NAME "SDIO" +#define DBG_TAG "SDIO" #ifdef RT_SDIO_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO +#define DBG_LVL DBG_INFO #endif /* RT_SDIO_DEBUG */ -#define DBG_COLOR #include <rtdbg.h> static const rt_uint32_t tran_unit[] = @@ -95,25 +93,6 @@ static rt_int32_t mmcsd_parse_csd(struct rt_mmcsd_card *card) card->tacc_ns = (tacc_uint[csd->taac&0x07] * tacc_value[(csd->taac&0x78)>>3] + 9) / 10; card->max_data_rate = tran_unit[csd->tran_speed&0x07] * tran_value[(csd->tran_speed&0x78)>>3]; - #if 0 - val = GET_BITS(resp, 115, 4); - unit = GET_BITS(resp, 112, 3); - csd->tacc_ns = (tacc_uint[unit] * tacc_value[val] + 9) / 10; - csd->tacc_clks = GET_BITS(resp, 104, 8) * 100; - - val = GET_BITS(resp, 99, 4); - unit = GET_BITS(resp, 96, 3); - csd->max_data_rate = tran_unit[unit] * tran_value[val]; - csd->ccc = GET_BITS(resp, 84, 12); - - unit = GET_BITS(resp, 47, 3); - val = GET_BITS(resp, 62, 12); - csd->device_size = (1 + val) << (unit + 2); - - csd->read_bl_len = GET_BITS(resp, 80, 4); - csd->write_bl_len = GET_BITS(resp, 22, 4); - csd->r2w_factor = GET_BITS(resp, 26, 3); - #endif break; case 1: card->flags |= CARD_FLAG_SDHC; @@ -144,23 +123,6 @@ static rt_int32_t mmcsd_parse_csd(struct rt_mmcsd_card *card) card->tacc_ns = 0; card->max_data_rate = tran_unit[csd->tran_speed&0x07] * tran_value[(csd->tran_speed&0x78)>>3]; - #if 0 - csd->tacc_ns = 0; - csd->tacc_clks = 0; - - val = GET_BITS(resp, 99, 4); - unit = GET_BITS(resp, 96, 3); - csd->max_data_rate = tran_unit[unit] * tran_value[val]; - csd->ccc = GET_BITS(resp, 84, 12); - - val = GET_BITS(resp, 48, 22); - csd->device_size = (1 + val) << 10; - - csd->read_bl_len = 9; - csd->write_bl_len = 9; - /* host should not use this factor and should use 250ms for write timeout */ - csd->r2w_factor = 2; - #endif break; default: LOG_E("unrecognised CSD structure version %d!", csd->csd_structure); @@ -266,7 +228,7 @@ static rt_int32_t mmcsd_switch(struct rt_mmcsd_card *card) if ((buf[16] & 0xF) != 1) { - LOG_E("switching card to high speed failed!"); + LOG_I("switching card to high speed failed!"); goto err; } diff --git a/components/drivers/sdio/sdio.c b/components/drivers/sdio/sdio.c index 6045c4ade8..65bf87b895 100644 --- a/components/drivers/sdio/sdio.c +++ b/components/drivers/sdio/sdio.c @@ -12,14 +12,12 @@ #include <drivers/sdio.h> #include <drivers/sd.h> -#define DBG_ENABLE -#define DBG_SECTION_NAME "SDIO" +#define DBG_TAG "SDIO" #ifdef RT_SDIO_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO +#define DBG_LVL DBG_INFO #endif /* RT_SDIO_DEBUG */ -#define DBG_COLOR #include <rtdbg.h> #ifndef RT_SDIO_STACK_SIZE @@ -711,6 +709,16 @@ static rt_int32_t sdio_initialize_function(struct rt_mmcsd_card *card, if (ret) goto err1; + /* + * product/manufacturer id is optional for function CIS, so + * copy it from the card structure as needed. + */ + if (func->product == 0) + { + func->manufacturer = card->cis.manufacturer; + func->product = card->cis.product; + } + card->sdio_function[func_num] = func; return 0; diff --git a/components/drivers/sensors/SConscript b/components/drivers/sensors/SConscript index db409cfd2b..51c4b50eef 100644 --- a/components/drivers/sensors/SConscript +++ b/components/drivers/sensors/SConscript @@ -3,14 +3,11 @@ from building import * cwd = GetCurrentDir() -src = ['sensor.cpp'] +src = ['sensor.c'] CPPPATH = [cwd, cwd + '/../include'] -if GetDepend('SENSOR_USING_MPU6050') and GetDepend('RT_USING_I2C'): - src += ['mpu6050_sensor.cpp']; - -if GetDepend('SENSOR_USING_BMI055') and GetDepend('RT_USING_I2C'): - src += ['bmi055_sensor.cpp'] +if GetDepend('RT_USING_SENSOR_CMD'): + src += ['sensor_cmd.c']; group = DefineGroup('Sensors', src, depend = ['RT_USING_SENSOR', 'RT_USING_DEVICE'], CPPPATH = CPPPATH) diff --git a/components/drivers/sensors/bmi055_sensor.cpp b/components/drivers/sensors/bmi055_sensor.cpp deleted file mode 100644 index b6e7f99da5..0000000000 --- a/components/drivers/sensors/bmi055_sensor.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-1-11 RT_learning the first version - */ - -#include <string.h> -#include <stdio.h> -#include <rtdevice.h> -#include "bmi055_sensor.h" - - -const static sensor_t _BMI055_sensor[] = -{ - { - .name = "Accelerometer", - .vendor = "Bosch", - .version = sizeof(sensor_t), - .handle = 0, - .type = SENSOR_TYPE_ACCELEROMETER, - .maxRange = SENSOR_ACCEL_RANGE_16G, - .resolution = 1.0f, - .power = 0.5f, - .minDelay = 10000, - .fifoReservedEventCount = 0, - .fifoMaxEventCount = 64, - }, - { - .name = "Gyroscope", - .vendor = "Bosch", - .version = sizeof(sensor_t), - .handle = 0, - .type = SENSOR_TYPE_GYROSCOPE, - .maxRange = SENSOR_GYRO_RANGE_2000DPS, - .resolution = 1.0f, - .power = 0.5f, - .minDelay = 10000, - .fifoReservedEventCount = 0, - .fifoMaxEventCount = 64, - } -}; - -BMI055::BMI055(int sensor_type, const char* iic_bus, int addr) - : SensorBase(sensor_type) -{ - this->i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(iic_bus); - if (this->i2c_bus == NULL) - { - printf("BMI055: No IIC device:%s\n", iic_bus); - return; - } - - this->i2c_addr = addr; - - /* register to sensor manager */ - SensorManager::registerSensor(this); -} - -int BMI055::read_reg(rt_uint8_t reg, rt_uint8_t *value) -{ - struct rt_i2c_msg msgs[2]; - - msgs[0].addr = this->i2c_addr; - msgs[0].flags = RT_I2C_WR; - msgs[0].buf = ® - msgs[0].len = 1; - - msgs[1].addr = this->i2c_addr; - msgs[1].flags = RT_I2C_RD; /* Read from slave */ - msgs[1].buf = (rt_uint8_t *)value; - msgs[1].len = 1; - - if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) - return RT_EOK; - - return -RT_ERROR; -} - -int BMI055::read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size) -{ - struct rt_i2c_msg msgs[2]; - - msgs[0].addr = this->i2c_addr; - msgs[0].flags = RT_I2C_WR; - msgs[0].buf = ® - msgs[0].len = 1; - - msgs[1].addr = this->i2c_addr; - msgs[1].flags = RT_I2C_RD; /* Read from slave */ - msgs[1].buf = (rt_uint8_t *)value; - msgs[1].len = size; - - if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) - return RT_EOK; - - return -RT_ERROR; -} - -int BMI055::write_reg(rt_uint8_t reg, rt_uint8_t value) -{ - struct rt_i2c_msg msgs[2]; - - msgs[0].addr = this->i2c_addr; - msgs[0].flags = RT_I2C_WR; - msgs[0].buf = ® - msgs[0].len = 1; - - msgs[1].addr = this->i2c_addr; - msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START; - msgs[1].buf = (rt_uint8_t *)&value; - msgs[1].len = 1; - - if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) - return RT_EOK; - - return -RT_ERROR; -} - - -BMI055_Accelerometer::BMI055_Accelerometer(const char* iic_name, int addr) - : BMI055(SENSOR_TYPE_ACCELEROMETER, iic_name, addr) -{ - int index; - uint8_t id; - rt_uint8_t value[6] = {0}; - rt_int32_t x, y, z; - SensorConfig config = {SENSOR_MODE_NORMAL, SENSOR_DATARATE_400HZ, SENSOR_ACCEL_RANGE_2G}; - - write_reg(BMI055_BGW_SOFTRESET, 0xB6); /* reset of the sensor P57 */ - write_reg(BMI055_PMU_LPW, 0x00); /* PMU_LPW NORMAL mode P55 */ - write_reg(BMI055_PMU_BW, 0x0A); /* 01010b 31.25 Hz P55 */ - write_reg(BMI055_PMU_RANGE, 0x05); /* 0101b 卤4g range PMU_RANGE set acc +-4g/s P54 */ - - - x_offset = y_offset = z_offset = 0; - x = y = z = 0; - - /* read BMI055 id */ - read_buffer(BMI055_ACC_BGW_CHIPID, &id, 1); /* BGW_CHIPID P47*/ - if (id != BMI055_ACC_BGW_CHIPID_VALUE) - { - printf("Warning: not found BMI055 id: %02x\n", id); - } - - /* get offset */ - for (index = 0; index < 200; index ++) - { - read_buffer(BMI055_ACCD_X_LSB, value, 6); /*ACCD_X_LSB P47 */ - - x += (((rt_int16_t)value[1] << 8) | value[0]); - y += (((rt_int16_t)value[3] << 8) | value[2]); - z += (((rt_int16_t)value[5] << 8) | value[4]); - } - x_offset = x / 200; - y_offset = y / 200; - z_offset = z / 200; - - this->enable = RT_FALSE; - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; - this->config = config; -} - -int -BMI055_Accelerometer::configure(SensorConfig *config) -{ - int range; - uint8_t value; - - if (config == RT_NULL) return -1; - - /* TODO: set datarate */ - - /* get range and calc the sensitivity */ - range = config->range.accel_range; - switch (range) - { - case SENSOR_ACCEL_RANGE_2G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; - range = 0x03; //0011b - break; - case SENSOR_ACCEL_RANGE_4G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_4G; - range = 0x05; //0101b - break; - case SENSOR_ACCEL_RANGE_8G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_8G; - range = 0x01 << 3; //1000b - break; - case SENSOR_ACCEL_RANGE_16G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_16G; - range = 0x03 << 2; //1100b - break; - default: - return -1; - } - - /* set range to sensor */ - read_reg(BMI055_PMU_RANGE, &value); /* PMU_RANGE P54 */ - value &= 0xF0; - value |= range; - write_reg(BMI055_PMU_RANGE, value); - - return 0; -} - -int -BMI055_Accelerometer::activate(int enable) -{ - uint8_t value; - - if (enable && this->enable == RT_FALSE) - { - /* enable accelerometer */ - read_reg(BMI055_PMU_LPW, &value); /* P55 */ - value &= ~(0x07 << 7); - write_reg(BMI055_PMU_LPW, value); - } - - if (!enable && this->enable == RT_TRUE) - { - /* disable accelerometer */ - read_reg(BMI055_PMU_LPW, &value); - value &= ~(0x07 << 7); - value |= (0x01 << 7); - write_reg(BMI055_PMU_LPW, value); - } - - if (enable) this->enable = RT_TRUE; - else this->enable = RT_FALSE; - - return 0; -} - -int -BMI055_Accelerometer::poll(sensors_event_t *event) -{ - rt_uint8_t value[6]; - rt_int16_t x, y, z; - - /* parameters check */ - if (event == NULL) return -1; - - /* get event data */ - event->version = sizeof(sensors_event_t); - event->sensor = (int32_t) this; - event->timestamp = rt_tick_get(); - event->type = SENSOR_TYPE_ACCELEROMETER; - - read_buffer(0x02, value, 6); - - /* get raw data */ - x = (((rt_int16_t)value[1] << 8) | value[0]); - y = (((rt_int16_t)value[3] << 8) | value[2]); - z = (((rt_int16_t)value[5] << 8) | value[4]); - - if (config.mode == SENSOR_MODE_RAW) - { - event->raw_acceleration.x = x; - event->raw_acceleration.y = y; - event->raw_acceleration.z = z; - } - else - { - - x -= x_offset; y -= y_offset; z -= z_offset; - event->acceleration.x = x * this->sensitivity * SENSORS_GRAVITY_STANDARD; - event->acceleration.y = y * this->sensitivity * SENSORS_GRAVITY_STANDARD; - event->acceleration.z = z * this->sensitivity * SENSORS_GRAVITY_STANDARD; - } - - return 0; -} - -void -BMI055_Accelerometer::getSensor(sensor_t *sensor) -{ - /* get sensor description */ - if (sensor) - { - memcpy(sensor, &_BMI055_sensor[0], sizeof(sensor_t)); - } -} - -BMI055_Gyroscope::BMI055_Gyroscope(const char* iic_name, int addr) - : BMI055(SENSOR_TYPE_GYROSCOPE, iic_name, addr) -{ - int index; - uint8_t id; - rt_uint8_t value[6]; - rt_int32_t x, y, z; - - /* initialize BMI055 */ - write_reg(BMI055_MODE_LPM1_ADDR, 0x00); /* normal mode */ - write_reg(BMI055_MODE_LPM2_ADDR, 0x80); /* fast powerup */ - write_reg(BMI055_BW_ADDR, 0x03); /* ODR:400Hz Filter Bandwidth:47Hz */ - write_reg(BMI055_RANGE_ADDR, 0x00); /* 2000dps */ - - - x_offset = y_offset = z_offset = 0; - x = y = z = 0; - - /* read BMI055 id */ - read_buffer(BMI055_CHIP_ID_ADDR, &id, 1); - if (id != BMI055_GRRO_CHIP_ID) - { - printf("Warning: not found BMI055 id: %02x\n", id); - } - - /* get offset */ - for (index = 0; index < 200; index ++) - { - read_buffer(BMI055_RATE_X_LSB_ADDR, value, 6); - - x += (((rt_int16_t)value[1] << 8) | value[0]); - y += (((rt_int16_t)value[3] << 8) | value[2]); - z += (((rt_int16_t)value[5] << 8) | value[4]); - } - x_offset = x / 200; - y_offset = y / 200; - z_offset = z / 200; - - this->enable = RT_FALSE; - this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; -} - -int -BMI055_Gyroscope::configure(SensorConfig *config) -{ - int range; - uint8_t value; - - if (config == RT_NULL) return -1; - - /* TODO: set datarate */ - - /* get range and calc the sensitivity */ - range = config->range.gyro_range; - switch (range) - { - //to do add more range e.g 125DPS - //case - case SENSOR_GYRO_RANGE_250DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; - range = 0x11; - break; - case SENSOR_GYRO_RANGE_500DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_500DPS; - range = 0x10; - break; - case SENSOR_GYRO_RANGE_1000DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_1000DPS; - range = 0x01; - break; - case SENSOR_GYRO_RANGE_2000DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_2000DPS; - range = 0x00; - break; - default: - return -1; - } - - /* set range to sensor */ - read_reg(BMI055_RANGE_ADDR, &value); - value &= ~0x07; - value |= range; - write_reg(BMI055_RANGE_ADDR, value); - - return 0; -} - -int -BMI055_Gyroscope::activate(int enable) -{ - uint8_t value; - - if (enable && this->enable == RT_FALSE) - { - /* enable gyroscope */ - read_reg(BMI055_MODE_LPM1_ADDR, &value); - value &= ~(0x1010 << 4); //{0; 0} NORMAL mode - write_reg(BMI055_MODE_LPM1_ADDR, value); //P101 NORMAL mode - } - - if (!enable && this->enable == RT_TRUE) - { - /* disable gyroscope */ - read_reg(BMI055_MODE_LPM1_ADDR, &value); - value &= ~(0x01 << 5); //set bit5 deep_suspend 0 - value |= (0x01 << 7); //set bit1 suspend 1 - write_reg(BMI055_MODE_LPM1_ADDR, value); //{1; 0} SUSPEND mode - } - - if (enable) this->enable = RT_TRUE; - else this->enable = RT_FALSE; - - return 0; -} - -int -BMI055_Gyroscope::poll(sensors_event_t *event) -{ - rt_uint8_t value[6]; - rt_int16_t x, y, z; - - /* parameters check */ - if (event == NULL) return -1; - - /* get event data */ - event->version = sizeof(sensors_event_t); - event->sensor = (int32_t) this; - event->timestamp = rt_tick_get(); - event->type = SENSOR_TYPE_GYROSCOPE; - - read_buffer(BMI055_RATE_X_LSB_ADDR, value, 6); - - /* get raw data */ - x = (((rt_int16_t)value[1] << 8) | value[0]); - y = (((rt_int16_t)value[3] << 8) | value[2]); - z = (((rt_int16_t)value[5] << 8) | value[4]); - - - if (config.mode == SENSOR_MODE_RAW) - { - event->raw_gyro.x = x; - event->raw_gyro.y = y; - event->raw_gyro.z = z; - } - else - { - x -= x_offset; y -= y_offset; z -= z_offset; - event->gyro.x = x * this->sensitivity * SENSORS_DPS_TO_RADS; - event->gyro.y = y * this->sensitivity * SENSORS_DPS_TO_RADS; - event->gyro.z = z * this->sensitivity * SENSORS_DPS_TO_RADS; - } - - return 0; -} - -void -BMI055_Gyroscope::getSensor(sensor_t *sensor) -{ - /* get sensor description */ - if (sensor) - { - memcpy(sensor, &_BMI055_sensor[1], sizeof(sensor_t)); - } -} diff --git a/components/drivers/sensors/bmi055_sensor.h b/components/drivers/sensors/bmi055_sensor.h deleted file mode 100644 index 713aa74ad0..0000000000 --- a/components/drivers/sensors/bmi055_sensor.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-1-11 RT_learning the first version - */ -#ifndef __BMI055_H__ -#define __BMI055_H__ - -#include <sensor.h> - -/**************************************************************************************************/ -/************************************Register map accelerometer************************************/ - -#define BMI055_ACC_I2C_ADDR1 0x18 //SDO is low(GND) -#define BMI055_ACC_I2C_ADDR2 0x19 //SDO is high(VCC) - -#define BMI055_ACC_DEFAULT_ADDRESS BMI055_ACC_I2C_ADDR2 //in the LPC54102 SPM-S - -#define BMI055_ACC_BGW_CHIPID_VALUE 0xFA - -#define BMI055_ACC_BGW_CHIPID 0x00 -/**<Address of ACC Chip ID Register */ -#define BMI055_ACCD_X_LSB 0x02 -/**< Address of X axis ACC LSB Register */ -#define BMI055_ACCD_X_MSB 0x03 -/**< Address of X axis ACC MSB Register */ -#define BMI055_ACCD_Y_LSB 0x04 -/**< Address of Y axis ACC LSB Register */ -#define BMI055_ACCD_Y_MSB 0x05 -/**< Address of Y axis ACC MSB Register */ -#define BMI055_ACCD_Z_LSB 0x06 -/**< Address of Z axis ACC LSB Register */ -#define BMI055_ACCD_Z_MSB 0x07 -/**< Address of Z axis ACC MSB Register */ -#define BMI055_ACCD_TEMP 0x08 -/**< Address of Temperature Data Register */ - -/* Status Register */ -#define BMI055_INT_STATUS_0 0x09 -/**< Address of Interrupt status Register 0 */ -#define BMI055_INT_STATUS_1 0x0A -/**< Address of Interrupt status Register 1 */ -#define BMI055_INT_STATUS_2 0x0B -/**< Address of Interrupt status Register 2 */ -#define BMI055_INT_STATUS_3 0x0C -/**< Address of Interrupt status Register 3 */ -#define BMI055_FIFO_STATUS 0x0E -/**< Address of FIFO status Register */ - -/* Control Register */ -#define BMI055_PMU_RANGE 0x0F -/**< Address of Range address Register */ -#define BMI055_PMU_BW 0x10 -/**< Address of Bandwidth Register */ -#define BMI055_PMU_LPW 0x11 -/**< Address of PMU LPW */ -#define BMI055_PMU_LOW_POWER 0x12 -/**< Address of PMU LOW POWER */ -#define BMI055_ACCD_HBW 0x13 -/**< Address of ACCD HBW */ -#define BMI055_BGW_SOFTRESET 0x14 -/**< Address of BGW SOFTRESET */ -#define BMI055_INT_EN_0 0x16 -/**< Address of interrupt engines in group 0 */ -#define BMI055_INT_EN_1 0x17 -/**< Address of interrupt engines in group 1 */ -#define BMI055_INT_EN_2 0x18 -/**< Address of interrupt engines in group 2 */ -#define BMI055_INT_MAP_0 0x19 -/**< Address of Interrupt MAP 0 */ -#define BMI055_INT_MAP_1 0x1A -/**< Address of Interrupt MAP 1 */ -#define BMI055_INT_MAP_2 0x1B -/**< Address of Interrupt MAP 2 */ -#define BMI055_INT_SRC 0x1E -/**< Address of Interrupt source */ -#define BMI055_INT_OUT_CTRL 0x20 -/**< Address of Interrupt Register */ -#define BMI055_INT_RST_LATCH 0x21 -/**< Address of Interrupt reset and mode Register */ -#define BMI055_INT_0 0x22 -/**< Address of low-g Interrupt delay time Register */ -#define BMI055_INT_1 0x23 -/**< Address of low-g Interrupt threshold Register */ -#define BMI055_INT_2 0x24 -/**< Address of Interrupt 2 Register */ -#define BMI055_INT_3 0x25 -/**< Address of high-g Interrupt delay time Register */ -#define BMI055_INT_4 0x26 -/**< Address of high-g Interrupt threshold Register */ -#define BMI055_INT_5 0x27 -/**< Address of high-g Interrupt 5 Register */ -#define BMI055_INT_6 0x28 -/**< Address of any-motion Interrupt threshold Register */ -#define BMI055_INT_7 0x29 -/**< Address of slow/no-motion interrupt threshold Register */ -#define BMI055_INT_8 0x2A -/**< Address of high-g Interrupt 8 Register */ -#define BMI055_INT_9 0x2B -/**< Address of high-g Interrupt 9 Register */ -#define BMI055_INT_A 0x2C -/**< Address of Interrupt A Register */ -#define BMI055_INT_B 0x2D -/**< Address of Interrupt B Register */ -#define BMI055_INT_C 0x2E -/**< Address of Interrupt C Register */ -#define BMI055_INT_D 0x2F -/**< Address of Interrupt D Register */ -#define BMI055_FIFO_CONFIG_0 0x30 -/**< Address of FIFO CONFIG 0 Register */ -#define BMI055_PMU_SELF_TEST 0x32 -/**< Address of PMU SELF TEST Register */ -#define BMI055_TRIM_NVM_CTRL 0x33 -/**< Address of TRIM NVM CTRL Register */ -#define BMI055_BGW_SPI3_WDT 0x34 -/**< Address of BGW SPI3 WDT Register */ -#define BMI055_OFC_CTRL 0x36 -/**< Address of OFC CTRL Register */ -#define BMI055_OFC_SETTING 0x37 -/**< Address of OFC SETTING Register */ -#define BMI055_OFC_OFFSET_X 0x38 -/**< Address of OFC OFFSET X Register */ -#define BMI055_OFC_OFFSET_Y 0x39 -/**< Address of OFC OFFSET Y Register */ -#define BMI055_OFC_OFFSET_Z 0x3A -/**< Address of OFC OFFSET Z Register */ - -/* Trim Register */ -#define BMI055_TRIM_GP0 0x3B -/**< Address of TRIM GP0 Register */ -#define BMI055_TRIM_GP1 0x3C -/**< Address of TRIM GP1 Register */ - -/* Control Register */ -#define BMI055_FIFO_CONFIG_1 0x3E -/**< Address of FIFO CONFIG 1 Register */ - -/* Data Register */ -#define BMI055_FIFO_DATA 0x3F -/**< Address of FIFO DATA Register */ - - -/**************************************************************************************************/ - - - - -/**************************************************************************************************/ -/************************************Register map gyroscope****************************************/ - - -/**< This refers BMI055 return type as signed */ - -// #define BMI055_I2C_ADDR1 0x68 //SDO is low(GND) -// #define BMI055_I2C_ADDR2 0x69 //SDO is high(VCC) -#define BMI055_GYRO_I2C_ADDR1 0x68 //SDO is low(GND) -#define BMI055_GYRO_I2C_ADDR2 0x69 //SDO is high(VCC) - -#define BMI055_GYRO_DEFAULT_ADDRESS BMI055_GYRO_I2C_ADDR2 - -#define BMI055_GRRO_CHIP_ID 0x0F - -/*Define of registers*/ - -/* Hard Wired */ -#define BMI055_CHIP_ID_ADDR 0x00 -/**<Address of Chip ID Register*/ - -/* Data Register */ -#define BMI055_RATE_X_LSB_ADDR 0x02 -/**< Address of X axis Rate LSB Register */ -#define BMI055_RATE_X_MSB_ADDR 0x03 -/**< Address of X axis Rate MSB Register */ -#define BMI055_RATE_Y_LSB_ADDR 0x04 -/**< Address of Y axis Rate LSB Register */ -#define BMI055_RATE_Y_MSB_ADDR 0x05 -/**< Address of Y axis Rate MSB Register */ -#define BMI055_RATE_Z_LSB_ADDR 0x06 -/**< Address of Z axis Rate LSB Register */ -#define BMI055_RATE_Z_MSB_ADDR 0x07 -/**< Address of Z axis Rate MSB Register */ -#define BMI055_TEMP_ADDR 0x08 -/**< Address of Temperature Data LSB Register */ - -/* Status Register */ -#define BMI055_INTR_STAT0_ADDR 0x09 -/**< Address of Interrupt status Register 0 */ -#define BMI055_INTR_STAT1_ADDR 0x0A -/**< Address of Interrupt status Register 1 */ -#define BMI055_INTR_STAT2_ADDR 0x0B -/**< Address of Interrupt status Register 2 */ -#define BMI055_INTR_STAT3_ADDR 0x0C -/**< Address of Interrupt status Register 3 */ -#define BMI055_FIFO_STAT_ADDR 0x0E -/**< Address of FIFO status Register */ - -/* Control Register */ -#define BMI055_RANGE_ADDR 0x0F -/**< Address of Range address Register */ -#define BMI055_BW_ADDR 0x10 -/**< Address of Bandwidth Register */ -#define BMI055_MODE_LPM1_ADDR 0x11 -/**< Address of Mode LPM1 Register */ -#define BMI055_MODE_LPM2_ADDR 0x12 -/**< Address of Mode LPM2 Register */ -#define BMI055_HIGH_BW_ADDR 0x13 -/**< Address of Rate HIGH_BW Register */ -#define BMI055_BGW_SOFT_RST_ADDR 0x14 -/**< Address of BGW Softreset Register */ -#define BMI055_INTR_ENABLE0_ADDR 0x15 -/**< Address of Interrupt Enable 0 */ -#define BMI055_INTR_ENABLE1_ADDR 0x16 -/**< Address of Interrupt Enable 1 */ -#define BMI055_INTR_MAP_ZERO_ADDR 0x17 -/**< Address of Interrupt MAP 0 */ -#define BMI055_INTR_MAP_ONE_ADDR 0x18 -/**< Address of Interrupt MAP 1 */ -#define BMI055_INTR_MAP_TWO_ADDR 0x19 -/**< Address of Interrupt MAP 2 */ -#define BMI055_INTR_ZERO_ADDR 0x1A -/**< Address of Interrupt 0 register */ -#define BMI055_INTR_ONE_ADDR 0x1B -/**< Address of Interrupt 1 register */ -#define BMI055_INTR_TWO_ADDR 0x1C -/**< Address of Interrupt 2 register */ -#define BMI055_INTR_4_ADDR 0x1E -/**< Address of Interrupt 4 register */ -#define BMI055_RST_LATCH_ADDR 0x21 -/**< Address of Reset Latch Register */ -#define BMI055_HIGHRATE_THRES_X_ADDR 0x22 -/**< Address of High Th x Address register */ -#define BMI055_HIGHRATE_DURN_X_ADDR 0x23 -/**< Address of High Dur x Address register */ -#define BMI055_HIGHRATE_THRES_Y_ADDR 0x24 -/**< Address of High Th y Address register */ -#define BMI055_HIGHRATE_DURN_Y_ADDR 0x25 -/**< Address of High Dur y Address register */ -#define BMI055_HIGHRATE_THRES_Z_ADDR 0x26 -/**< Address of High Th z Address register */ -#define BMI055_HIGHRATE_DURN_Z_ADDR 0x27 -/**< Address of High Dur z Address register */ -#define BMI055_SOC_ADDR 0x31 -/**< Address of SOC register */ -#define BMI055_A_FOC_ADDR 0x32 -/**< Address of A_FOC Register */ -#define BMI055_TRIM_NVM_CTRL_ADDR 0x33 -/**< Address of Trim NVM control register */ -#define BMI055_BGW_SPI3_WDT_ADDR 0x34 -/**< Address of BGW SPI3,WDT Register */ - -/* Trim Register */ -#define BMI055_OFC1_ADDR 0x36 -/**< Address of OFC1 Register */ -#define BMI055_OFC2_ADDR 0x37 -/**< Address of OFC2 Register */ -#define BMI055_OFC3_ADDR 0x38 -/**< Address of OFC3 Register */ -#define BMI055_OFC4_ADDR 0x39 -/**< Address of OFC4 Register */ -#define BMI055_TRIM_GP0_ADDR 0x3A -/**< Address of Trim GP0 Register */ -#define BMI055_TRIM_GP1_ADDR 0x3B -/**< Address of Trim GP1 Register */ -#define BMI055_SELECTF_TEST_ADDR 0x3C -/**< Address of BGW Self test Register */ - -/* Control Register */ -#define BMI055_FIFO_CGF1_ADDR 0x3D -/**< Address of FIFO CGF0 Register */ -#define BMI055_FIFO_CGF0_ADDR 0x3E -/**< Address of FIFO CGF1 Register */ - -/* Data Register */ -#define BMI055_FIFO_DATA_ADDR 0x3F -/**< Address of FIFO Data Register */ - - -/**************************************************************************************************/ - -class BMI055 :public SensorBase -{ -public: - BMI055(int sensor_type, const char* iic_bus, int addr); - - int read_reg(rt_uint8_t reg, rt_uint8_t* value); - int write_reg(rt_uint8_t reg, rt_uint8_t value); - int read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size); - -private: - struct rt_i2c_bus_device *i2c_bus; - int i2c_addr; -}; - -class BMI055_Accelerometer:public BMI055 -{ -public: - BMI055_Accelerometer(const char* iic_name, int addr); - - virtual int configure(SensorConfig *config); - virtual int activate(int enable); - - virtual int poll(sensors_event_t *event); - virtual void getSensor(sensor_t *sensor); - -private: - rt_int16_t x_offset, y_offset, z_offset; - - rt_bool_t enable; - float sensitivity; -}; - -class BMI055_Gyroscope:public BMI055 -{ -public: - BMI055_Gyroscope(const char* iic_name, int addr); - - virtual int configure(SensorConfig *config); - virtual int activate(int enable); - - virtual int poll(sensors_event_t *event); - virtual void getSensor(sensor_t *sensor); - -private: - rt_int16_t x_offset, y_offset, z_offset; - - rt_bool_t enable; - float sensitivity; -}; - -#endif diff --git a/components/drivers/sensors/mpu6050_sensor.cpp b/components/drivers/sensors/mpu6050_sensor.cpp deleted file mode 100644 index 358796bc30..0000000000 --- a/components/drivers/sensors/mpu6050_sensor.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2014-12-20 Bernard the first version - * 2015-1-11 RT_learning modify the mpu6050 initialize - */ - -#include <string.h> -#include <stdio.h> -#include <rtdevice.h> - -#include "mpu6050_sensor.h" - - -const static sensor_t _MPU6050_sensor[] = -{ - { - .name = "Accelerometer", - .vendor = "Invensense", - .version = sizeof(sensor_t), - .handle = 0, - .type = SENSOR_TYPE_ACCELEROMETER, - .maxRange = SENSOR_ACCEL_RANGE_16G, - .resolution = 1.0f, - .power = 0.5f, - .minDelay = 10000, - .fifoReservedEventCount = 0, - .fifoMaxEventCount = 64, - }, - { - .name = "Gyroscope", - .vendor = "Invensense", - .version = sizeof(sensor_t), - .handle = 0, - .type = SENSOR_TYPE_GYROSCOPE, - .maxRange = SENSOR_GYRO_RANGE_2000DPS, - .resolution = 1.0f, - .power = 0.5f, - .minDelay = 10000, - .fifoReservedEventCount = 0, - .fifoMaxEventCount = 64, - } -}; - -MPU6050::MPU6050(int sensor_type, const char* iic_bus, int addr) - : SensorBase(sensor_type) -{ - this->i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(iic_bus); - if (this->i2c_bus == NULL) - { - printf("MPU6050: No IIC device:%s\n", iic_bus); - return; - } - - this->i2c_addr = addr; - - /* register to sensor manager */ - SensorManager::registerSensor(this); -} - -int MPU6050::read_reg(rt_uint8_t reg, rt_uint8_t *value) -{ - struct rt_i2c_msg msgs[2]; - - msgs[0].addr = this->i2c_addr; - msgs[0].flags = RT_I2C_WR; - msgs[0].buf = ® - msgs[0].len = 1; - - msgs[1].addr = this->i2c_addr; - msgs[1].flags = RT_I2C_RD; /* Read from slave */ - msgs[1].buf = (rt_uint8_t *)value; - msgs[1].len = 1; - - if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) - return RT_EOK; - - return -RT_ERROR; -} - -int MPU6050::read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size) -{ - struct rt_i2c_msg msgs[2]; - - msgs[0].addr = this->i2c_addr; - msgs[0].flags = RT_I2C_WR; - msgs[0].buf = ® - msgs[0].len = 1; - - msgs[1].addr = this->i2c_addr; - msgs[1].flags = RT_I2C_RD; /* Read from slave */ - msgs[1].buf = (rt_uint8_t *)value; - msgs[1].len = size; - - if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) - return RT_EOK; - - return -RT_ERROR; -} - -int MPU6050::write_reg(rt_uint8_t reg, rt_uint8_t value) -{ - struct rt_i2c_msg msgs[2]; - - msgs[0].addr = this->i2c_addr; - msgs[0].flags = RT_I2C_WR; - msgs[0].buf = ® - msgs[0].len = 1; - - msgs[1].addr = this->i2c_addr; - msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START; - msgs[1].buf = (rt_uint8_t *)&value; - msgs[1].len = 1; - - if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) - return RT_EOK; - - return -RT_ERROR; -} - - -MPU6050_Accelerometer::MPU6050_Accelerometer(const char* iic_name, int addr) - : MPU6050(SENSOR_TYPE_ACCELEROMETER, iic_name, addr) -{ - int index; - uint8_t id; - rt_uint8_t value[6] = {0}; - rt_int32_t x, y, z; - SensorConfig config = {SENSOR_MODE_NORMAL, SENSOR_DATARATE_400HZ, SENSOR_ACCEL_RANGE_2G}; - - /* initialize MPU6050 */ - write_reg(MPU6050_PWR_MGMT_1, 0x80); /* reset mpu6050 device */ - write_reg(MPU6050_SMPLRT_DIV, 0x00); /* Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) */ - write_reg(MPU6050_PWR_MGMT_1, 0x03); /* Wake up device , set device clock Z axis gyroscope */ - write_reg(MPU6050_CONFIG, 0x03); /* set DLPF_CFG 42Hz */ - write_reg(MPU6050_GYRO_CONFIG, 0x18); /* set gyro 2000deg/s */ - write_reg(MPU6050_ACCEL_CONFIG, 0x08); /* set acc +-4g/s */ - - - x_offset = y_offset = z_offset = 0; - x = y = z = 0; - - /* read MPU6050 id */ - read_buffer(MPU6050_WHOAMI, &id, 1); - if (id != MPU6050_ID) - { - printf("Warning: not found MPU6050 id: %02x\n", id); - } - - /* get offset */ - for (index = 0; index < 200; index ++) - { - read_buffer(MPU6050_ACCEL_XOUT_H, value, 6); - - x += (((rt_int16_t)value[0] << 8) | value[1]); - y += (((rt_int16_t)value[2] << 8) | value[3]); - z += (((rt_int16_t)value[4] << 8) | value[5]); - } - x_offset = x / 200; - y_offset = y / 200; - z_offset = z / 200; - - this->enable = RT_FALSE; - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; - this->config = config; -} - -int -MPU6050_Accelerometer::configure(SensorConfig *config) -{ - int range; - uint8_t value; - - if (config == RT_NULL) return -1; - - /* TODO: set datarate */ - - /* get range and calc the sensitivity */ - range = config->range.accel_range; - switch (range) - { - case SENSOR_ACCEL_RANGE_2G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; - range = 0; - break; - case SENSOR_ACCEL_RANGE_4G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_4G; - range = 0x01 << 2; - break; - case SENSOR_ACCEL_RANGE_8G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_8G; - range = 0x02 << 2; - break; - case SENSOR_ACCEL_RANGE_16G: - this->sensitivity = SENSOR_ACCEL_SENSITIVITY_16G; - range = 0x03 << 2; - break; - default: - return -1; - } - - /* set range to sensor */ - read_reg(MPU6050_ACCEL_CONFIG, &value); - value &= ~(0x3 << 2); - value |= range; - write_reg(MPU6050_ACCEL_CONFIG, value); - - return 0; -} - -int -MPU6050_Accelerometer::activate(int enable) -{ - uint8_t value; - - if (enable && this->enable == RT_FALSE) - { - /* enable accelerometer */ - read_reg(MPU6050_PWR_MGMT_2, &value); - value &= ~(0x07 << 2); - write_reg(MPU6050_PWR_MGMT_2, value); - } - - if (!enable && this->enable == RT_TRUE) - { - /* disable accelerometer */ - read_reg(MPU6050_PWR_MGMT_2, &value); - value |= (0x07 << 2); - write_reg(MPU6050_PWR_MGMT_2, value); - } - - if (enable) this->enable = RT_TRUE; - else this->enable = RT_FALSE; - - return 0; -} - -int -MPU6050_Accelerometer::poll(sensors_event_t *event) -{ - rt_uint8_t value[6]; - rt_int16_t x, y, z; - - /* parameters check */ - if (event == NULL) return -1; - - /* get event data */ - event->version = sizeof(sensors_event_t); - event->sensor = (int32_t) this; - event->timestamp = rt_tick_get(); - event->type = SENSOR_TYPE_ACCELEROMETER; - - read_buffer(MPU6050_ACCEL_XOUT_H, value, 6); - - /* get raw data */ - x = (((rt_int16_t)value[0] << 8) | value[1]); - y = (((rt_int16_t)value[2] << 8) | value[3]); - z = (((rt_int16_t)value[4] << 8) | value[5]); - - if (config.mode == SENSOR_MODE_RAW) - { - event->raw_acceleration.x = x; - event->raw_acceleration.y = y; - event->raw_acceleration.z = z; - } - else - { - - x -= x_offset; y -= y_offset; z -= z_offset; - event->acceleration.x = x * this->sensitivity * SENSORS_GRAVITY_STANDARD; - event->acceleration.y = y * this->sensitivity * SENSORS_GRAVITY_STANDARD; - event->acceleration.z = z * this->sensitivity * SENSORS_GRAVITY_STANDARD; - } - - return 0; -} - -void -MPU6050_Accelerometer::getSensor(sensor_t *sensor) -{ - /* get sensor description */ - if (sensor) - { - memcpy(sensor, &_MPU6050_sensor[0], sizeof(sensor_t)); - } -} - -MPU6050_Gyroscope::MPU6050_Gyroscope(const char* iic_name, int addr) - : MPU6050(SENSOR_TYPE_GYROSCOPE, iic_name, addr) -{ - int index; - uint8_t id; - rt_uint8_t value[6]; - rt_int32_t x, y, z; - - /* initialize MPU6050 */ - write_reg(MPU6050_PWR_MGMT_1, 0x80); /* reset mpu6050 device */ - write_reg(MPU6050_SMPLRT_DIV, 0x00); /* Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) */ - write_reg(MPU6050_PWR_MGMT_1, 0x03); /* Wake up device , set device clock Z axis gyroscope */ - write_reg(MPU6050_CONFIG, 0x03); /* set DLPF_CFG 42Hz */ - write_reg(MPU6050_GYRO_CONFIG, 0x18); /* set gyro 2000deg/s */ - write_reg(MPU6050_ACCEL_CONFIG, 0x08); /* set acc +-4g/s */ - - x_offset = y_offset = z_offset = 0; - x = y = z = 0; - - /* read MPU6050 id */ - read_reg(MPU6050_WHOAMI, &id); - if (id != MPU6050_ID) - { - printf("Warning: not found MPU6050 id: %02x\n", id); - } - - /* get offset */ - for (index = 0; index < 200; index ++) - { - read_buffer(MPU6050_GYRO_XOUT_H, value, 6); - - x += (((rt_int16_t)value[0] << 8) | value[1]); - y += (((rt_int16_t)value[2] << 8) | value[3]); - z += (((rt_int16_t)value[4] << 8) | value[5]); - } - x_offset = x / 200; - y_offset = y / 200; - z_offset = z / 200; - - this->enable = RT_FALSE; - this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; -} - -int -MPU6050_Gyroscope::configure(SensorConfig *config) -{ - int range; - uint8_t value; - - if (config == RT_NULL) return -1; - - /* TODO: set datarate */ - - /* get range and calc the sensitivity */ - range = config->range.gyro_range; - switch (range) - { - case SENSOR_GYRO_RANGE_250DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; - range = 0; - break; - case SENSOR_GYRO_RANGE_500DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_500DPS; - range = 0x01 << 2; - break; - case SENSOR_GYRO_RANGE_1000DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_1000DPS; - range = 0x02 << 2; - break; - case SENSOR_GYRO_RANGE_2000DPS: - this->sensitivity = SENSOR_GYRO_SENSITIVITY_2000DPS; - range = 0x03 << 2; - break; - default: - return -1; - } - - /* set range to sensor */ - read_reg(MPU6050_GYRO_CONFIG, &value); - value &= ~(0x3 << 2); - value |= range; - write_reg(MPU6050_GYRO_CONFIG, value); - - return 0; -} - -int -MPU6050_Gyroscope::activate(int enable) -{ - uint8_t value; - - if (enable && this->enable == RT_FALSE) - { - /* enable gyroscope */ - read_reg(MPU6050_PWR_MGMT_1, &value); - value &= ~(0x01 << 4); - write_reg(MPU6050_PWR_MGMT_1, value); - - read_reg(MPU6050_PWR_MGMT_2, &value); - value &= ~(0x07 << 0); - write_reg(MPU6050_PWR_MGMT_2, value); - } - - if (!enable && this->enable == RT_TRUE) - { - /* disable gyroscope */ - read_reg(MPU6050_PWR_MGMT_2, &value); - value |= (0x07 << 0); - write_reg(MPU6050_PWR_MGMT_2, value); - } - - if (enable) this->enable = RT_TRUE; - else this->enable = RT_FALSE; - - return 0; -} - -int -MPU6050_Gyroscope::poll(sensors_event_t *event) -{ - rt_uint8_t value[6]; - rt_int16_t x, y, z; - - /* parameters check */ - if (event == NULL) return -1; - - /* get event data */ - event->version = sizeof(sensors_event_t); - event->sensor = (int32_t) this; - event->timestamp = rt_tick_get(); - event->type = SENSOR_TYPE_GYROSCOPE; - - read_buffer(MPU6050_GYRO_XOUT_H, value, 6); - - /* get raw data */ - x = (((rt_int16_t)value[0] << 8) | value[1]); - y = (((rt_int16_t)value[2] << 8) | value[3]); - z = (((rt_int16_t)value[4] << 8) | value[5]); - - - if (config.mode == SENSOR_MODE_RAW) - { - event->raw_gyro.x = x; - event->raw_gyro.y = y; - event->raw_gyro.z = z; - } - else - { - x -= x_offset; y -= y_offset; z -= z_offset; - event->gyro.x = x * this->sensitivity * SENSORS_DPS_TO_RADS; - event->gyro.y = y * this->sensitivity * SENSORS_DPS_TO_RADS; - event->gyro.z = z * this->sensitivity * SENSORS_DPS_TO_RADS; - } - - return 0; -} - -void -MPU6050_Gyroscope::getSensor(sensor_t *sensor) -{ - /* get sensor description */ - if (sensor) - { - memcpy(sensor, &_MPU6050_sensor[1], sizeof(sensor_t)); - } -} - diff --git a/components/drivers/sensors/mpu6050_sensor.h b/components/drivers/sensors/mpu6050_sensor.h deleted file mode 100644 index 8f70c3e5ed..0000000000 --- a/components/drivers/sensors/mpu6050_sensor.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2014-12-20 Bernard the first version - * 2015-1-11 RT_learning modify the mpu6050 ID - */ - -#ifndef MPU6050_SENSOR_H__ -#define MPU6050_SENSOR_H__ - -#include <sensor.h> - -#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board -#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) -#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW - -#define MPU6050_XG_OFFS_TC 0x00 -#define MPU6050_YG_OFFS_TC 0x01 -#define MPU6050_ZG_OFFS_TC 0x02 -#define MPU6050_X_FINE_GAIN 0x03 -#define MPU6050_Y_FINE_GAIN 0x04 -#define MPU6050_Z_FINE_GAIN 0x05 -#define MPU6050_XA_OFFS_H 0x06 -#define MPU6050_XA_OFFS_L 0x07 -#define MPU6050_YA_OFFS_H 0x08 -#define MPU6050_YA_OFFS_L 0x09 -#define MPU6050_ZA_OFFS_H 0x0A -#define MPU6050_ZA_OFFS_L 0x0B -#define MPU6050_PRODUCT_ID 0x0C -#define MPU6050_SELF_TEST_X 0x0D -#define MPU6050_SELF_TEST_Y 0x0E -#define MPU6050_SELF_TEST_Z 0x0F -#define MPU6050_SELF_TEST_A 0x10 -#define MPU6050_XG_OFFS_USRH 0x13 -#define MPU6050_XG_OFFS_USRL 0x14 -#define MPU6050_YG_OFFS_USRH 0x15 -#define MPU6050_YG_OFFS_USRL 0x16 -#define MPU6050_ZG_OFFS_USRH 0x17 -#define MPU6050_ZG_OFFS_USRL 0x18 -#define MPU6050_SMPLRT_DIV 0x19 -#define MPU6050_CONFIG 0x1A -#define MPU6050_GYRO_CONFIG 0x1B -#define MPU6050_ACCEL_CONFIG 0x1C -#define MPU6050_ACCEL_CONFIG_2 0x1D -#define MPU6050_LP_ACCEL_ODR 0x1E -#define MPU6050_MOT_THR 0x1F -#define MPU6050_FIFO_EN 0x23 -#define MPU6050_I2C_MST_CTRL 0x24 -#define MPU6050_I2C_SLV0_ADDR 0x25 -#define MPU6050_I2C_SLV0_REG 0x26 -#define MPU6050_I2C_SLV0_CTRL 0x27 -#define MPU6050_I2C_SLV1_ADDR 0x28 -#define MPU6050_I2C_SLV1_REG 0x29 -#define MPU6050_I2C_SLV1_CTRL 0x2A -#define MPU6050_I2C_SLV2_ADDR 0x2B -#define MPU6050_I2C_SLV2_REG 0x2C -#define MPU6050_I2C_SLV2_CTRL 0x2D -#define MPU6050_I2C_SLV3_ADDR 0x2E -#define MPU6050_I2C_SLV3_REG 0x2F -#define MPU6050_I2C_SLV3_CTRL 0x30 -#define MPU6050_I2C_SLV4_ADDR 0x31 -#define MPU6050_I2C_SLV4_REG 0x32 -#define MPU6050_I2C_SLV4_DO 0x33 -#define MPU6050_I2C_SLV4_CTRL 0x34 -#define MPU6050_I2C_SLV4_DI 0x35 -#define MPU6050_I2C_MST_STATUS 0x36 -#define MPU6050_INT_PIN_CFG 0x37 -#define MPU6050_INT_ENABLE 0x38 -#define MPU6050_ACCEL_XOUT_H 0x3B -#define MPU6050_ACCEL_XOUT_L 0x3C -#define MPU6050_ACCEL_YOUT_H 0x3D -#define MPU6050_ACCEL_YOUT_L 0x3E -#define MPU6050_ACCEL_ZOUT_H 0x3F -#define MPU6050_ACCEL_ZOUT_L 0x40 -#define MPU6050_TEMP_OUT_H 0x41 -#define MPU6050_TEMP_OUT_L 0x42 -#define MPU6050_GYRO_XOUT_H 0x43 -#define MPU6050_GYRO_XOUT_L 0x44 -#define MPU6050_GYRO_YOUT_H 0x45 -#define MPU6050_GYRO_YOUT_L 0x46 -#define MPU6050_GYRO_ZOUT_H 0x47 -#define MPU6050_GYRO_ZOUT_L 0x48 -#define MPU6050_EXT_SENS_DATA_00 0x49 -#define MPU6050_EXT_SENS_DATA_01 0x4A -#define MPU6050_EXT_SENS_DATA_02 0x4B -#define MPU6050_EXT_SENS_DATA_03 0x4C -#define MPU6050_EXT_SENS_DATA_04 0x4D -#define MPU6050_EXT_SENS_DATA_05 0x4E -#define MPU6050_EXT_SENS_DATA_06 0x4F -#define MPU6050_EXT_SENS_DATA_07 0x50 -#define MPU6050_EXT_SENS_DATA_08 0x51 -#define MPU6050_EXT_SENS_DATA_09 0x52 -#define MPU6050_EXT_SENS_DATA_10 0x53 -#define MPU6050_EXT_SENS_DATA_11 0x54 -#define MPU6050_EXT_SENS_DATA_12 0x55 -#define MPU6050_EXT_SENS_DATA_13 0x56 -#define MPU6050_EXT_SENS_DATA_14 0x57 -#define MPU6050_EXT_SENS_DATA_15 0x58 -#define MPU6050_EXT_SENS_DATA_16 0x59 -#define MPU6050_EXT_SENS_DATA_17 0x5A -#define MPU6050_EXT_SENS_DATA_18 0x5B -#define MPU6050_EXT_SENS_DATA_19 0x5C -#define MPU6050_EXT_SENS_DATA_20 0x5D -#define MPU6050_EXT_SENS_DATA_21 0x5E -#define MPU6050_EXT_SENS_DATA_22 0x5F -#define MPU6050_EXT_SENS_DATA_23 0x60 -#define MPU6050_I2C_SLV0_DO 0x63 -#define MPU6050_I2C_SLV1_DO 0x64 -#define MPU6050_I2C_SLV2_DO 0x65 -#define MPU6050_I2C_SLV3_DO 0x66 -#define MPU6050_I2C_MST_DELAY_CTRL 0x67 -#define MPU6050_SIGNAL_PATH_RESET 0x68 -#define MPU6050_MOT_DETECT_CTRL 0x69 -#define MPU6050_USER_CTRL 0x6A -#define MPU6050_PWR_MGMT_1 0x6B -#define MPU6050_PWR_MGMT_2 0x6C -#define MPU6050_BANK_SEL 0x6D -#define MPU6050_MEM_START_ADDR 0x6E -#define MPU6050_MEM_R_W 0x6F -#define MPU6050_DMP_CFG_1 0x70 -#define MPU6050_DMP_CFG_2 0x71 -#define MPU6050_FIFO_COUNTH 0x72 -#define MPU6050_FIFO_COUNTL 0x73 -#define MPU6050_FIFO_R_W 0x74 -#define MPU6050_WHOAMI 0x75 -#define MPU6050_XA_OFFSET_H 0x77 -#define MPU6050_XA_OFFSET_L 0x78 -#define MPU6050_YA_OFFSET_H 0x7A -#define MPU6050_YA_OFFSET_L 0x7B -#define MPU6050_ZA_OFFSET_H 0x7D -#define MPU6050_ZA_OFFSET_L 0x7E - -#define MPU6050_ID 0x68 - -class MPU6050 :public SensorBase -{ -public: - MPU6050(int sensor_type, const char* iic_bus, int addr); - - int read_reg(rt_uint8_t reg, rt_uint8_t* value); - int write_reg(rt_uint8_t reg, rt_uint8_t value); - int read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size); - -private: - struct rt_i2c_bus_device *i2c_bus; - int i2c_addr; -}; - -class MPU6050_Accelerometer:public MPU6050 -{ -public: - MPU6050_Accelerometer(const char* iic_name, int addr); - - virtual int configure(SensorConfig *config); - virtual int activate(int enable); - - virtual int poll(sensors_event_t *event); - virtual void getSensor(sensor_t *sensor); - -private: - rt_int16_t x_offset, y_offset, z_offset; - - rt_bool_t enable; - float sensitivity; -}; - -class MPU6050_Gyroscope:public MPU6050 -{ -public: - MPU6050_Gyroscope(const char* iic_name, int addr); - - virtual int configure(SensorConfig *config); - virtual int activate(int enable); - - virtual int poll(sensors_event_t *event); - virtual void getSensor(sensor_t *sensor); - -private: - rt_int16_t x_offset, y_offset, z_offset; - - rt_bool_t enable; - float sensitivity; -}; - -#endif diff --git a/components/drivers/sensors/sensor.c b/components/drivers/sensors/sensor.c new file mode 100644 index 0000000000..eb5c97a574 --- /dev/null +++ b/components/drivers/sensors/sensor.c @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-01-31 flybreak first version + * 2020-02-22 luhuadong support custom commands + */ + +#include "sensor.h" + +#define DBG_TAG "sensor" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#include <string.h> + +static char *const sensor_name_str[] = +{ + "none", + "acce_", /* Accelerometer */ + "gyro_", /* Gyroscope */ + "mag_", /* Magnetometer */ + "temp_", /* Temperature */ + "humi_", /* Relative Humidity */ + "baro_", /* Barometer */ + "li_", /* Ambient light */ + "pr_", /* Proximity */ + "hr_", /* Heart Rate */ + "tvoc_", /* TVOC Level */ + "noi_", /* Noise Loudness */ + "step_", /* Step sensor */ + "forc_", /* Force sensor */ + "dust_", /* Dust sensor */ + "eco2_", /* eCO2 sensor */ + "gnss_" /* GPS/GNSS sensor */ +}; + +/* Sensor interrupt correlation function */ +/* + * Sensor interrupt handler function + */ +void rt_sensor_cb(rt_sensor_t sen) +{ + if (sen->parent.rx_indicate == RT_NULL) + { + return; + } + + if (sen->irq_handle != RT_NULL) + { + sen->irq_handle(sen); + } + + /* The buffer is not empty. Read the data in the buffer first */ + if (sen->data_len > 0) + { + sen->parent.rx_indicate(&sen->parent, sen->data_len / sizeof(struct rt_sensor_data)); + } + else if (sen->config.mode == RT_SENSOR_MODE_INT) + { + /* The interrupt mode only produces one data at a time */ + sen->parent.rx_indicate(&sen->parent, 1); + } + else if (sen->config.mode == RT_SENSOR_MODE_FIFO) + { + sen->parent.rx_indicate(&sen->parent, sen->info.fifo_max); + } +} + +/* ISR for sensor interrupt */ +static void irq_callback(void *args) +{ + rt_sensor_t sensor = (rt_sensor_t)args; + rt_uint8_t i; + + if (sensor->module) + { + /* Invoke a callback for all sensors in the module */ + for (i = 0; i < sensor->module->sen_num; i++) + { + rt_sensor_cb(sensor->module->sen[i]); + } + } + else + { + rt_sensor_cb(sensor); + } +} + +/* Sensor interrupt initialization function */ +static rt_err_t rt_sensor_irq_init(rt_sensor_t sensor) +{ + if (sensor->config.irq_pin.pin == RT_PIN_NONE) + { + return -RT_EINVAL; + } + + rt_pin_mode(sensor->config.irq_pin.pin, sensor->config.irq_pin.mode); + + if (sensor->config.irq_pin.mode == PIN_MODE_INPUT_PULLDOWN) + { + rt_pin_attach_irq(sensor->config.irq_pin.pin, PIN_IRQ_MODE_RISING, irq_callback, (void *)sensor); + } + else if (sensor->config.irq_pin.mode == PIN_MODE_INPUT_PULLUP) + { + rt_pin_attach_irq(sensor->config.irq_pin.pin, PIN_IRQ_MODE_FALLING, irq_callback, (void *)sensor); + } + else if (sensor->config.irq_pin.mode == PIN_MODE_INPUT) + { + rt_pin_attach_irq(sensor->config.irq_pin.pin, PIN_IRQ_MODE_RISING_FALLING, irq_callback, (void *)sensor); + } + + rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_TRUE); + + LOG_I("interrupt init success"); + + return 0; +} + +/* RT-Thread Device Interface */ +static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + RT_ASSERT(dev != RT_NULL); + rt_err_t res = RT_EOK; + + if (sensor->module) + { + /* take the module mutex */ + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + + if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf == RT_NULL) + { + /* Allocate memory for the sensor buffer */ + sensor->data_buf = rt_malloc(sizeof(struct rt_sensor_data) * sensor->info.fifo_max); + if (sensor->data_buf == RT_NULL) + { + res = -RT_ENOMEM; + goto __exit; + } + } + + if (oflag & RT_DEVICE_FLAG_RDONLY && dev->flag & RT_DEVICE_FLAG_RDONLY) + { + if (sensor->ops->control != RT_NULL) + { + /* If polling mode is supported, configure it to polling mode */ + sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING); + } + sensor->config.mode = RT_SENSOR_MODE_POLLING; + } + else if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) + { + if (sensor->ops->control != RT_NULL) + { + /* If interrupt mode is supported, configure it to interrupt mode */ + sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT); + } + /* Initialization sensor interrupt */ + rt_sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_INT; + } + else if (oflag & RT_DEVICE_FLAG_FIFO_RX && dev->flag & RT_DEVICE_FLAG_FIFO_RX) + { + if (sensor->ops->control != RT_NULL) + { + /* If fifo mode is supported, configure it to fifo mode */ + sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO); + } + /* Initialization sensor interrupt */ + rt_sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_FIFO; + } + else + { + res = -RT_EINVAL; + goto __exit; + } + + /* Configure power mode to normal mode */ + if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_NORMAL) == RT_EOK) + { + sensor->config.power = RT_SENSOR_POWER_NORMAL; + } + +__exit: + if (sensor->module) + { + /* release the module mutex */ + rt_mutex_release(sensor->module->lock); + } + + return res; +} + +static rt_err_t rt_sensor_close(rt_device_t dev) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + int i; + + RT_ASSERT(dev != RT_NULL); + + if (sensor->module) + { + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + + /* Configure power mode to power down mode */ + if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_DOWN) == RT_EOK) + { + sensor->config.power = RT_SENSOR_POWER_DOWN; + } + + /* Sensor disable interrupt */ + if (sensor->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); + } + + if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf != RT_NULL) + { + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->parent.ref_count > 0) + goto __exit; + } + + /* Free memory for the sensor buffer */ + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->data_buf != RT_NULL) + { + rt_free(sensor->module->sen[i]->data_buf); + sensor->module->sen[i]->data_buf = RT_NULL; + } + } + } + +__exit: + if (sensor->module) + { + rt_mutex_release(sensor->module->lock); + } + + return RT_EOK; +} + +static rt_size_t rt_sensor_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t len) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + rt_size_t result = 0; + RT_ASSERT(dev != RT_NULL); + + if (buf == NULL || len == 0) + { + return 0; + } + + if (sensor->module) + { + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + + /* The buffer is not empty. Read the data in the buffer first */ + if (sensor->data_len > 0) + { + if (len > sensor->data_len / sizeof(struct rt_sensor_data)) + { + len = sensor->data_len / sizeof(struct rt_sensor_data); + } + + rt_memcpy(buf, sensor->data_buf, len * sizeof(struct rt_sensor_data)); + + /* Clear the buffer */ + sensor->data_len = 0; + result = len; + } + else + { + /* If the buffer is empty read the data */ + result = sensor->ops->fetch_data(sensor, buf, len); + } + + if (sensor->module) + { + rt_mutex_release(sensor->module->lock); + } + + return result; +} + +static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + rt_err_t result = RT_EOK; + RT_ASSERT(dev != RT_NULL); + + if (sensor->module) + { + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + + switch (cmd) + { + case RT_SENSOR_CTRL_GET_ID: + if (args) + { + result = sensor->ops->control(sensor, RT_SENSOR_CTRL_GET_ID, args); + } + break; + case RT_SENSOR_CTRL_GET_INFO: + if (args) + { + rt_memcpy(args, &sensor->info, sizeof(struct rt_sensor_info)); + } + break; + case RT_SENSOR_CTRL_SET_RANGE: + + /* Configuration measurement range */ + result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_RANGE, args); + if (result == RT_EOK) + { + sensor->config.range = (rt_int32_t)args; + LOG_D("set range %d", sensor->config.range); + } + break; + case RT_SENSOR_CTRL_SET_ODR: + + /* Configuration data output rate */ + result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_ODR, args); + if (result == RT_EOK) + { + sensor->config.odr = (rt_uint32_t)args & 0xFFFF; + LOG_D("set odr %d", sensor->config.odr); + } + break; + case RT_SENSOR_CTRL_SET_POWER: + + /* Configuration sensor power mode */ + result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, args); + if (result == RT_EOK) + { + sensor->config.power = (rt_uint32_t)args & 0xFF; + LOG_D("set power mode code:", sensor->config.power); + } + break; + case RT_SENSOR_CTRL_SELF_TEST: + + /* Device self-test */ + result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SELF_TEST, args); + break; + default: + + if (cmd > RT_SENSOR_CTRL_USER_CMD_START) + { + /* Custom commands */ + result = sensor->ops->control(sensor, cmd, args); + } + else + { + result = -RT_ERROR; + } + break; + } + + if (sensor->module) + { + rt_mutex_release(sensor->module->lock); + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rt_sensor_ops = +{ + RT_NULL, + rt_sensor_open, + rt_sensor_close, + rt_sensor_read, + RT_NULL, + rt_sensor_control +}; +#endif + +/* + * sensor register + */ +int rt_hw_sensor_register(rt_sensor_t sensor, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_int8_t result; + rt_device_t device; + RT_ASSERT(sensor != RT_NULL); + + char *sensor_name = RT_NULL, *device_name = RT_NULL; + + /* Add a type name for the sensor device */ + sensor_name = sensor_name_str[sensor->info.type]; + device_name = (char *)rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name)); + if (device_name == RT_NULL) + { + LOG_E("device_name calloc failed!"); + return -RT_ERROR; + } + + rt_memcpy(device_name, sensor_name, rt_strlen(sensor_name) + 1); + strcat(device_name, name); + + if (sensor->module != RT_NULL && sensor->module->lock == RT_NULL) + { + /* Create a mutex lock for the module */ + sensor->module->lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO); + if (sensor->module->lock == RT_NULL) + { + rt_free(device_name); + return -RT_ERROR; + } + } + + device = &sensor->parent; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &rt_sensor_ops; +#else + device->init = RT_NULL; + device->open = rt_sensor_open; + device->close = rt_sensor_close; + device->read = rt_sensor_read; + device->write = RT_NULL; + device->control = rt_sensor_control; +#endif + device->type = RT_Device_Class_Sensor; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->user_data = data; + + result = rt_device_register(device, device_name, flag | RT_DEVICE_FLAG_STANDALONE); + if (result != RT_EOK) + { + rt_free(device_name); + LOG_E("rt_sensor register err code: %d", result); + return result; + } + + rt_free(device_name); + LOG_I("rt_sensor init success"); + return RT_EOK; +} diff --git a/components/drivers/sensors/sensor.cpp b/components/drivers/sensors/sensor.cpp deleted file mode 100644 index f986510f63..0000000000 --- a/components/drivers/sensors/sensor.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2014-08-03 Bernard the first version - */ - -#include <stddef.h> -#include <string.h> - -#include "sensor.h" - -/** - * SensorBase - */ -SensorBase::SensorBase(int type) -{ - memset(&(this->config), 0x0, sizeof(SensorConfig)); - - this->type = type; - this->next = this->prev = NULL; - subscribe(NULL, NULL); -} - -SensorBase::~SensorBase() -{ -} - -int SensorBase::getType(void) -{ - return this->type; -} - -int SensorBase::setConfig(SensorConfig *config) -{ - int result; - - /* configure to the low level sensor */ - result = this->configure(config); - if (result == 0) - { - this->config = *config; - } - - return result; -} - -int SensorBase::getConfig(SensorConfig *config) -{ - *config = this->config; - return 0; -} - -int SensorBase::subscribe(SensorEventHandler_t handler, void *user_data) -{ - this->evtHandler = handler; - this->userData = user_data; - - return 0; -} - -int SensorBase::publish(void) -{ - if (this->evtHandler != NULL) - { - /* invoke subscribed handler */ - (*evtHandler)(this->userData); - } - - return 0; -} - -/** - * Sensor Manager - */ -/* sensors list */ -static SensorBase *sensor_list = NULL; - -SensorManager::SensorManager() -{ -} - -SensorManager::~SensorManager() -{ -} - -int SensorManager::registerSensor(SensorBase *sensor) -{ - RT_ASSERT(sensor != RT_NULL); - - /* add sensor into the list */ - if (sensor_list == NULL) - { - sensor->prev = sensor->next = sensor; - } - else - { - sensor_list->prev->next = sensor; - sensor->prev = sensor_list->prev; - - sensor_list->prev = sensor; - sensor->next = sensor_list; - } - - /* point the sensorList to this sensor */ - sensor_list = sensor; - - return 0; -} - -int SensorManager::unregisterSensor(SensorBase *sensor) -{ - /* disconnect sensor list */ - sensor->next->prev = sensor->prev; - sensor->prev->next = sensor->next; - - /* check the sensorList */ - if (sensor == sensor_list) - { - if (sensor->next == sensor) sensor_list = NULL; /* empty list */ - else sensor_list = sensor->next; - } - - /* re-initialize sensor node */ - sensor->next = sensor->prev = sensor; - - return 0; -} - -SensorBase *SensorManager::getDefaultSensor(int type) -{ - SensorBase *sensor = sensor_list; - - if (sensor == NULL) return NULL; - - do - { - /* find the same type */ - if (sensor->getType() == type) return sensor; - - sensor = sensor->next; - }while (sensor != sensor_list); - - return NULL; -} - -int SensorManager::subscribe(int type, SensorEventHandler_t handler, void *user_data) -{ - SensorBase *sensor; - - sensor = SensorManager::getDefaultSensor(type); - if (sensor != NULL) - { - sensor->subscribe(handler, user_data); - return 0; - } - - return -1; -} - -int SensorManager::sensorEventReady(SensorBase *sensor) -{ - return 0; -} - -int SensorManager::pollSensor(SensorBase *sensor, sensors_event_t *events, int number, int duration) -{ - rt_tick_t tick; - int result, index; - - if (sensor == NULL) return -1; - - tick = rt_tick_get(); - for (index = 0; index < number; index ++) - { - result = sensor->poll(&events[index]); - if (result < 0) break; - - if (rt_tick_get() - tick > duration) break; - } - - return index; -} - -rt_sensor_t rt_sensor_get_default(int type) -{ - return (rt_sensor_t)SensorManager::getDefaultSensor(type); -} - -int rt_sensor_subscribe(rt_sensor_t sensor, SensorEventHandler_t handler, void *user_data) -{ - SensorBase *sensor_base; - if (sensor == NULL) return -1; - - sensor_base = (SensorBase*)sensor; - - return sensor_base->subscribe(handler, user_data); -} - -int rt_sensor_poll(rt_sensor_t sensor, sensors_event_t *event) -{ - SensorBase *sensor_base; - if (sensor == NULL || event == NULL) return -1; - - sensor_base = (SensorBase*)sensor; - return sensor_base->poll(event); -} - -int rt_sensor_configure(rt_sensor_t sensor, SensorConfig *config) -{ - SensorBase *sensor_base; - if (sensor == NULL || config == NULL) return -1; - - sensor_base = (SensorBase*)sensor; - return sensor_base->setConfig(config); -} - -int rt_sensor_activate(rt_sensor_t sensor, int enable) -{ - SensorBase *sensor_base; - if (sensor == NULL) return -1; - - sensor_base = (SensorBase*)sensor; - return sensor_base->activate(enable); -} diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index 916360d34b..5a069edc25 100644..100755 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -5,1125 +5,233 @@ * * Change Logs: * Date Author Notes - * 2014-08-03 Bernard the first version + * 2019-01-31 flybreak first version */ -/* Modified from: https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */ - -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SENSORS_H__ -#define SENSORS_H__ +#ifndef __SENSOR_H__ +#define __SENSOR_H__ +#include <rtthread.h> #include <rtdevice.h> -#include <stdint.h> -#ifdef __CC_ARM /* skip warning in armcc */ -#pragma anon_unions +#ifdef __cplusplus +extern "C" { #endif -/** - * Handles must be higher than SENSORS_HANDLE_BASE and must be unique. - * A Handle identifies a given sensors. The handle is used to activate - * and/or deactivate sensors. - * In this version of the API there can only be 256 handles. - */ -#define SENSORS_HANDLE_BASE 0 -#define SENSORS_HANDLE_BITS 8 -#define SENSORS_HANDLE_COUNT (1<<SENSORS_HANDLE_BITS) - - -/* - * flags for (*batch)() - * Availability: SENSORS_DEVICE_API_VERSION_1_0 - * see (*batch)() documentation for details - */ -enum -{ - SENSORS_BATCH_DRY_RUN = 0x00000001, - SENSORS_BATCH_WAKE_UPON_FIFO_FULL = 0x00000002 -}; - -/* - * what field for meta_data_event_t - */ -enum -{ - /* a previous flush operation has completed */ - META_DATA_FLUSH_COMPLETE = 1, - META_DATA_VERSION /* always last, leave auto-assigned */ -}; - -/** - * Definition of the axis used by the sensor HAL API - * - * This API is relative to the screen of the device in its default orientation, - * that is, if the device can be used in portrait or landscape, this API - * is only relative to the NATURAL orientation of the screen. In other words, - * the axis are not swapped when the device's screen orientation changes. - * Higher level services /may/ perform this transformation. - * - * x<0 x>0 - * ^ - * | - * +-----------+--> y>0 - * | | - * | | - * | | - * | | / z<0 - * | | / - * | | / - * O-----------+/ - * |[] [ ] []/ - * +----------/+ y<0 - * / - * / - * |/ z>0 (toward the sky) - * - * O: Origin (x=0,y=0,z=0) - * - */ - -/* - * Interaction with suspend mode - * - * Unless otherwise noted, an enabled sensor shall not prevent the - * SoC to go into suspend mode. It is the responsibility of applications - * to keep a partial wake-lock should they wish to receive sensor - * events while the screen is off. While in suspend mode, and unless - * otherwise noted (batch mode, sensor particularities, ...), enabled sensors' - * events are lost. - * - * Note that conceptually, the sensor itself is not de-activated while in - * suspend mode -- it's just that the data it returns are lost. As soon as - * the SoC gets out of suspend mode, operations resume as usual. Of course, - * in practice sensors shall be disabled while in suspend mode to - * save power, unless batch mode is active, in which case they must - * continue fill their internal FIFO (see the documentation of batch() to - * learn how suspend interacts with batch mode). - * - * In batch mode, and only when the flag SENSORS_BATCH_WAKE_UPON_FIFO_FULL is - * set and supported, the specified sensor must be able to wake-up the SoC and - * be able to buffer at least 10 seconds worth of the requested sensor events. - * - * There are notable exceptions to this behavior, which are sensor-dependent - * (see sensor types definitions below) - * - * - * The sensor type documentation below specifies the wake-up behavior of - * each sensor: - * wake-up: yes this sensor must wake-up the SoC to deliver events - * wake-up: no this sensor shall not wake-up the SoC, events are dropped - * - */ - -/* - * Sensor type - * - * Each sensor has a type which defines what this sensor measures and how - * measures are reported. All types are defined below. - * - * Device manufacturers (OEMs) can define their own sensor types, for - * their private use by applications or services provided by them. Such - * sensor types are specific to an OEM and can't be exposed in the SDK. - * These types must start at SENSOR_TYPE_DEVICE_PRIVATE_BASE. - */ - -/* - * Base for device manufacturers private sensor types. - * These sensor types can't be exposed in the SDK. - */ -#define SENSOR_TYPE_DEVICE_PRIVATE_BASE 0x10000 - -/* - * Sensor fusion and virtual sensors - * - * Many sensor types are or can be implemented as virtual sensors from - * physical sensors on the device. For instance the rotation vector sensor, - * orientation sensor, step-detector, step-counter, etc... - * - * From the point of view of this API these virtual sensors MUST appear as - * real, individual sensors. It is the responsibility of the driver and HAL - * to make sure this is the case. - * - * In particular, all sensors must be able to function concurrently. - * For example, if defining both an accelerometer and a step counter, - * then both must be able to work concurrently. - */ - -/* - * Trigger modes - * - * Sensors can report events in different ways called trigger modes, - * each sensor type has one and only one trigger mode associated to it. - * Currently there are four trigger modes defined: - * - * continuous: events are reported at a constant rate defined by setDelay(). - * eg: accelerometers, gyroscopes. - * on-change: events are reported only if the sensor's value has changed. - * setDelay() is used to set a lower limit to the reporting - * period (minimum time between two events). - * The HAL must return an event immediately when an on-change - * sensor is activated. - * eg: proximity, light sensors - * one-shot: upon detection of an event, the sensor deactivates itself and - * then sends a single event. Order matters to avoid race - * conditions. No other event is sent until the sensor get - * reactivated. setDelay() is ignored. - * eg: significant motion sensor - * special: see details in the sensor type specification below - * - */ - -/* - * SENSOR_TYPE_META_DATA - * trigger-mode: n/a - * wake-up sensor: n/a - * - * NO SENSOR OF THAT TYPE MUST BE RETURNED (*get_sensors_list)() - * - * SENSOR_TYPE_META_DATA is a special token used to populate the - * sensors_meta_data_event structure. It doesn't correspond to a physical - * sensor. sensors_meta_data_event are special, they exist only inside - * the HAL and are generated spontaneously, as opposed to be related to - * a physical sensor. - * - * sensors_meta_data_event_t.version must be META_DATA_VERSION - * sensors_meta_data_event_t.sensor must be 0 - * sensors_meta_data_event_t.type must be SENSOR_TYPE_META_DATA - * sensors_meta_data_event_t.reserved must be 0 - * sensors_meta_data_event_t.timestamp must be 0 - * - * The payload is a meta_data_event_t, where: - * meta_data_event_t.what can take the following values: - * - * META_DATA_FLUSH_COMPLETE - * This event indicates that a previous (*flush)() call has completed for the sensor - * handle specified in meta_data_event_t.sensor. - * see (*flush)() for more details - * - * All other values for meta_data_event_t.what are reserved and - * must not be used. - * - */ -#define SENSOR_TYPE_META_DATA (0) - -/* - * SENSOR_TYPE_ACCELEROMETER - * trigger-mode: continuous - * wake-up sensor: no - * - * All values are in SI units (m/s^2) and measure the acceleration of the - * device minus the force of gravity. - * - * Acceleration sensors return sensor events for all 3 axes at a constant - * rate defined by setDelay(). - * - * x: Acceleration on the x-axis - * y: Acceleration on the y-axis - * z: Acceleration on the z-axis - * - * Note that the readings from the accelerometer include the acceleration - * due to gravity (which is opposite to the direction of the gravity vector). - * - * Examples: - * The norm of <x, y, z> should be close to 0 when in free fall. - * - * When the device lies flat on a table and is pushed on its left side - * toward the right, the x acceleration value is positive. - * - * When the device lies flat on a table, the acceleration value is +9.81, - * which correspond to the acceleration of the device (0 m/s^2) minus the - * force of gravity (-9.81 m/s^2). - * - * When the device lies flat on a table and is pushed toward the sky, the - * acceleration value is greater than +9.81, which correspond to the - * acceleration of the device (+A m/s^2) minus the force of - * gravity (-9.81 m/s^2). - */ -#define SENSOR_TYPE_ACCELEROMETER (1) - -/* - * SENSOR_TYPE_GEOMAGNETIC_FIELD - * trigger-mode: continuous - * wake-up sensor: no - * - * All values are in micro-Tesla (uT) and measure the geomagnetic - * field in the X, Y and Z axis. - * - * Returned values include calibration mechanisms such that the vector is - * aligned with the magnetic declination and heading of the earth's - * geomagnetic field. - * - * Magnetic Field sensors return sensor events for all 3 axes at a constant - * rate defined by setDelay(). - */ -#define SENSOR_TYPE_GEOMAGNETIC_FIELD (2) -#define SENSOR_TYPE_MAGNETIC_FIELD SENSOR_TYPE_GEOMAGNETIC_FIELD - -/* - * SENSOR_TYPE_ORIENTATION - * trigger-mode: continuous - * wake-up sensor: no - * - * All values are angles in degrees. - * - * Orientation sensors return sensor events for all 3 axes at a constant - * rate defined by setDelay(). - * - * azimuth: angle between the magnetic north direction and the Y axis, around - * the Z axis (0<=azimuth<360). - * 0=North, 90=East, 180=South, 270=West - * - * pitch: Rotation around X axis (-180<=pitch<=180), with positive values when - * the z-axis moves toward the y-axis. - * - * roll: Rotation around Y axis (-90<=roll<=90), with positive values when - * the x-axis moves towards the z-axis. - * - * Note: For historical reasons the roll angle is positive in the clockwise - * direction (mathematically speaking, it should be positive in the - * counter-clockwise direction): - * - * Z - * ^ - * (+roll) .--> | - * / | - * | | roll: rotation around Y axis - * X <-------(.) - * Y - * note that +Y == -roll - * - * - * - * Note: This definition is different from yaw, pitch and roll used in aviation - * where the X axis is along the long side of the plane (tail to nose). - */ -#define SENSOR_TYPE_ORIENTATION (3) - -/* - * SENSOR_TYPE_GYROSCOPE - * trigger-mode: continuous - * wake-up sensor: no - * - * All values are in radians/second and measure the rate of rotation - * around the X, Y and Z axis. The coordinate system is the same as is - * used for the acceleration sensor. Rotation is positive in the - * counter-clockwise direction (right-hand rule). That is, an observer - * looking from some positive location on the x, y or z axis at a device - * positioned on the origin would report positive rotation if the device - * appeared to be rotating counter clockwise. Note that this is the - * standard mathematical definition of positive rotation and does not agree - * with the definition of roll given earlier. - * The range should at least be 17.45 rad/s (ie: ~1000 deg/s). - * - * automatic gyro-drift compensation is allowed but not required. - */ -#define SENSOR_TYPE_GYROSCOPE (4) - -/* - * SENSOR_TYPE_LIGHT - * trigger-mode: on-change - * wake-up sensor: no - * - * The light sensor value is returned in SI lux units. - */ -#define SENSOR_TYPE_LIGHT (5) - -/* - * SENSOR_TYPE_PRESSURE - * trigger-mode: continuous - * wake-up sensor: no - * - * The pressure sensor return the athmospheric pressure in hectopascal (hPa) - */ -#define SENSOR_TYPE_PRESSURE (6) - -/* SENSOR_TYPE_TEMPERATURE is deprecated in the HAL */ -#define SENSOR_TYPE_TEMPERATURE (7) - -/* - * SENSOR_TYPE_PROXIMITY - * trigger-mode: on-change - * wake-up sensor: yes - * - * The distance value is measured in centimeters. Note that some proximity - * sensors only support a binary "close" or "far" measurement. In this case, - * the sensor should report its maxRange value in the "far" state and a value - * less than maxRange in the "near" state. - */ -#define SENSOR_TYPE_PROXIMITY (8) - -/* - * SENSOR_TYPE_GRAVITY - * trigger-mode: continuous - * wake-up sensor: no - * - * A gravity output indicates the direction of and magnitude of gravity in - * the devices's coordinates. On Earth, the magnitude is 9.8 m/s^2. - * Units are m/s^2. The coordinate system is the same as is used for the - * acceleration sensor. When the device is at rest, the output of the - * gravity sensor should be identical to that of the accelerometer. - */ -#define SENSOR_TYPE_GRAVITY (9) - -/* - * SENSOR_TYPE_LINEAR_ACCELERATION - * trigger-mode: continuous - * wake-up sensor: no - * - * Indicates the linear acceleration of the device in device coordinates, - * not including gravity. - * - * The output is conceptually: - * output of TYPE_ACCELERATION - output of TYPE_GRAVITY - * - * Readings on all axes should be close to 0 when device lies on a table. - * Units are m/s^2. - * The coordinate system is the same as is used for the acceleration sensor. - */ -#define SENSOR_TYPE_LINEAR_ACCELERATION (10) - -/* - * SENSOR_TYPE_ROTATION_VECTOR - * trigger-mode: continuous - * wake-up sensor: no - * - * The rotation vector symbolizes the orientation of the device relative to the - * East-North-Up coordinates frame. It is usually obtained by integration of - * accelerometer, gyroscope and magnetometer readings. - * - * The East-North-Up coordinate system is defined as a direct orthonormal basis - * where: - * - X points east and is tangential to the ground. - * - Y points north and is tangential to the ground. - * - Z points towards the sky and is perpendicular to the ground. - * - * The orientation of the phone is represented by the rotation necessary to - * align the East-North-Up coordinates with the phone's coordinates. That is, - * applying the rotation to the world frame (X,Y,Z) would align them with the - * phone coordinates (x,y,z). - * - * The rotation can be seen as rotating the phone by an angle theta around - * an axis rot_axis to go from the reference (East-North-Up aligned) device - * orientation to the current device orientation. - * - * The rotation is encoded as the 4 (reordered) components of a unit quaternion: - * sensors_event_t.data[0] = rot_axis.x*sin(theta/2) - * sensors_event_t.data[1] = rot_axis.y*sin(theta/2) - * sensors_event_t.data[2] = rot_axis.z*sin(theta/2) - * sensors_event_t.data[3] = cos(theta/2) - * where - * - rot_axis.x,y,z are the North-East-Up coordinates of a unit length vector - * representing the rotation axis - * - theta is the rotation angle - * - * The quaternion must be of norm 1 (it is a unit quaternion). Failure to ensure - * this will cause erratic client behaviour. - * - * In addition, this sensor reports an estimated heading accuracy. - * sensors_event_t.data[4] = estimated_accuracy (in radians) - * The heading error must be less than estimated_accuracy 95% of the time - * - * This sensor must use a gyroscope and an accelerometer as main orientation - * change input. - * - * This sensor can also include magnetometer input to make up for gyro drift, - * but it cannot be implemented using only a magnetometer. - */ -#define SENSOR_TYPE_ROTATION_VECTOR (11) - -/* - * SENSOR_TYPE_RELATIVE_HUMIDITY - * trigger-mode: on-change - * wake-up sensor: no - * - * A relative humidity sensor measures relative ambient air humidity and - * returns a value in percent. - */ -#define SENSOR_TYPE_RELATIVE_HUMIDITY (12) - -/* - * SENSOR_TYPE_AMBIENT_TEMPERATURE - * trigger-mode: on-change - * wake-up sensor: no - * - * The ambient (room) temperature in degree Celsius. - */ -#define SENSOR_TYPE_AMBIENT_TEMPERATURE (13) - -/* - * SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED - * trigger-mode: continuous - * wake-up sensor: no - * - * Similar to SENSOR_TYPE_MAGNETIC_FIELD, but the hard iron calibration is - * reported separately instead of being included in the measurement. - * Factory calibration and temperature compensation should still be applied to - * the "uncalibrated" measurement. - * Separating away the hard iron calibration estimation allows the system to - * better recover from bad hard iron estimation. - * - * All values are in micro-Tesla (uT) and measure the ambient magnetic - * field in the X, Y and Z axis. Assumptions that the the magnetic field - * is due to the Earth's poles should be avoided. - * - * The uncalibrated_magnetic event contains - * - 3 fields for uncalibrated measurement: x_uncalib, y_uncalib, z_uncalib. - * Each is a component of the measured magnetic field, with soft iron - * and temperature compensation applied, but not hard iron calibration. - * These values should be continuous (no re-calibration should cause a jump). - * - 3 fields for hard iron bias estimates: x_bias, y_bias, z_bias. - * Each field is a component of the estimated hard iron calibration. - * They represent the offsets to apply to the calibrated readings to obtain - * uncalibrated readings (x_uncalib ~= x_calibrated + x_bias) - * These values are expected to jump as soon as the estimate of the hard iron - * changes, and they should be stable the rest of the time. - * - * If this sensor is present, then the corresponding - * SENSOR_TYPE_MAGNETIC_FIELD must be present and both must return the - * same sensor_t::name and sensor_t::vendor. - * - * Minimum filtering should be applied to this sensor. In particular, low pass - * filters should be avoided. - * - * See SENSOR_TYPE_MAGNETIC_FIELD for more information - */ -#define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED (14) +#ifdef RT_USING_RTC +#define rt_sensor_get_ts() time(RT_NULL) /* API for the sensor to get the timestamp */ +#else +#define rt_sensor_get_ts() rt_tick_get() /* API for the sensor to get the timestamp */ +#endif -/* - * SENSOR_TYPE_GAME_ROTATION_VECTOR - * trigger-mode: continuous - * wake-up sensor: no - * - * Similar to SENSOR_TYPE_ROTATION_VECTOR, but not using the geomagnetic - * field. Therefore the Y axis doesn't point north, but instead to some other - * reference. That reference is allowed to drift by the same order of - * magnitude than the gyroscope drift around the Z axis. - * - * This sensor does not report an estimated heading accuracy: - * sensors_event_t.data[4] is reserved and should be set to 0 - * - * In the ideal case, a phone rotated and returning to the same real-world - * orientation should report the same game rotation vector - * (without using the earth's geomagnetic field). - * - * This sensor must be based on a gyroscope. It cannot be implemented using - * a magnetometer. - * - * see SENSOR_TYPE_ROTATION_VECTOR for more details - */ -#define SENSOR_TYPE_GAME_ROTATION_VECTOR (15) +#define RT_PIN_NONE 0xFFFF /* RT PIN NONE */ +#define RT_DEVICE_FLAG_FIFO_RX 0x200 /* Flag to use when the sensor is open by fifo mode */ -/* - * SENSOR_TYPE_GYROSCOPE_UNCALIBRATED - * trigger-mode: continuous - * wake-up sensor: no - * - * All values are in radians/second and measure the rate of rotation - * around the X, Y and Z axis. An estimation of the drift on each axis is - * reported as well. - * - * No gyro-drift compensation shall be performed. - * Factory calibration and temperature compensation should still be applied - * to the rate of rotation (angular speeds). - * - * The coordinate system is the same as is - * used for the acceleration sensor. Rotation is positive in the - * counter-clockwise direction (right-hand rule). That is, an observer - * looking from some positive location on the x, y or z axis at a device - * positioned on the origin would report positive rotation if the device - * appeared to be rotating counter clockwise. Note that this is the - * standard mathematical definition of positive rotation and does not agree - * with the definition of roll given earlier. - * The range should at least be 17.45 rad/s (ie: ~1000 deg/s). - * - * Content of an uncalibrated_gyro event: (units are rad/sec) - * x_uncalib : angular speed (w/o drift compensation) around the X axis - * y_uncalib : angular speed (w/o drift compensation) around the Y axis - * z_uncalib : angular speed (w/o drift compensation) around the Z axis - * x_bias : estimated drift around X axis in rad/s - * y_bias : estimated drift around Y axis in rad/s - * z_bias : estimated drift around Z axis in rad/s - * - * IMPLEMENTATION NOTES: - * - * If the implementation is not able to estimate the drift, then this - * sensor MUST NOT be reported by this HAL. Instead, the regular - * SENSOR_TYPE_GYROSCOPE is used without drift compensation. - * - * If this sensor is present, then the corresponding - * SENSOR_TYPE_GYROSCOPE must be present and both must return the - * same sensor_t::name and sensor_t::vendor. - */ -#define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED (16) +#define RT_SENSOR_MODULE_MAX (3) /* The maximum number of members of a sensor module */ -/* - * SENSOR_TYPE_SIGNIFICANT_MOTION - * trigger-mode: one-shot - * wake-up sensor: yes - * - * A sensor of this type triggers an event each time significant motion - * is detected and automatically disables itself. - * The only allowed value to return is 1.0. - * - * A significant motion is a motion that might lead to a change in the user - * location. - * Examples of such motions are: - * walking, biking, sitting in a moving car, coach or train. - * Examples of situations that should not trigger significant motion: - * - phone in pocket and person is not moving - * - phone is on a table, even if the table shakes a bit due to nearby traffic - * or washing machine - * - * A note on false positive / false negative / power consumption tradeoff - * - The goal of this sensor is to save power. - * - Triggering an event when the user is not moving (false positive) is costly - * in terms of power, so it should be avoided. - * - Not triggering an event when the user is moving (false negative) is - * acceptable as long as it is not done repeatedly. If the user has been - * walking for 10 seconds, not triggering an event within those 10 seconds - * is not acceptable. - * - * IMPORTANT NOTE: this sensor type is very different from other types - * in that it must work when the screen is off without the need of - * holding a partial wake-lock and MUST allow the SoC to go into suspend. - * When significant motion is detected, the sensor must awaken the SoC and - * the event be reported. - * - * If a particular hardware cannot support this mode of operation then this - * sensor type MUST NOT be reported by the HAL. ie: it is not acceptable - * to "emulate" this sensor in the HAL. - * - * The whole point of this sensor type is to save power by keeping the - * SoC in suspend mode when the device is at rest. - * - * When the sensor is not activated, it must also be deactivated in the - * hardware: it must not wake up the SoC anymore, even in case of - * significant motion. - * - * setDelay() has no effect and is ignored. - * Once a "significant motion" event is returned, a sensor of this type - * must disables itself automatically, as if activate(..., 0) had been called. - */ +/* Sensor types */ -#define SENSOR_TYPE_SIGNIFICANT_MOTION (17) +#define RT_SENSOR_CLASS_NONE (0) +#define RT_SENSOR_CLASS_ACCE (1) /* Accelerometer */ +#define RT_SENSOR_CLASS_GYRO (2) /* Gyroscope */ +#define RT_SENSOR_CLASS_MAG (3) /* Magnetometer */ +#define RT_SENSOR_CLASS_TEMP (4) /* Temperature */ +#define RT_SENSOR_CLASS_HUMI (5) /* Relative Humidity */ +#define RT_SENSOR_CLASS_BARO (6) /* Barometer */ +#define RT_SENSOR_CLASS_LIGHT (7) /* Ambient light */ +#define RT_SENSOR_CLASS_PROXIMITY (8) /* Proximity */ +#define RT_SENSOR_CLASS_HR (9) /* Heart Rate */ +#define RT_SENSOR_CLASS_TVOC (10) /* TVOC Level */ +#define RT_SENSOR_CLASS_NOISE (11) /* Noise Loudness */ +#define RT_SENSOR_CLASS_STEP (12) /* Step sensor */ +#define RT_SENSOR_CLASS_FORCE (13) /* Force sensor */ +#define RT_SENSOR_CLASS_DUST (14) /* Dust sensor */ +#define RT_SENSOR_CLASS_ECO2 (15) /* eCO2 sensor */ +#define RT_SENSOR_CLASS_GNSS (16) /* GPS/GNSS sensor */ -/* - * SENSOR_TYPE_STEP_DETECTOR - * trigger-mode: special - * wake-up sensor: no - * - * A sensor of this type triggers an event each time a step is taken - * by the user. The only allowed value to return is 1.0 and an event is - * generated for each step. Like with any other event, the timestamp - * indicates when the event (here the step) occurred, this corresponds to when - * the foot hit the ground, generating a high variation in acceleration. - * - * While this sensor operates, it shall not disrupt any other sensors, in - * particular, but not limited to, the accelerometer; which might very well - * be in use as well. - * - * This sensor must be low power. That is, if the step detection cannot be - * done in hardware, this sensor should not be defined. Also, when the - * step detector is activated and the accelerometer is not, only steps should - * trigger interrupts (not accelerometer data). - * - * setDelay() has no impact on this sensor type - */ +/* Sensor vendor types */ -#define SENSOR_TYPE_STEP_DETECTOR (18) +#define RT_SENSOR_VENDOR_UNKNOWN (0) +#define RT_SENSOR_VENDOR_STM (1) /* STMicroelectronics */ +#define RT_SENSOR_VENDOR_BOSCH (2) /* Bosch */ +#define RT_SENSOR_VENDOR_INVENSENSE (3) /* Invensense */ +#define RT_SENSOR_VENDOR_SEMTECH (4) /* Semtech */ +#define RT_SENSOR_VENDOR_GOERTEK (5) /* Goertek */ +#define RT_SENSOR_VENDOR_MIRAMEMS (6) /* MiraMEMS */ +#define RT_SENSOR_VENDOR_DALLAS (7) /* Dallas */ +#define RT_SENSOR_VENDOR_ASAIR (8) /* Aosong */ +#define RT_SENSOR_VENDOR_SHARP (9) /* Sharp */ +#define RT_SENSOR_VENDOR_SENSIRION (10) /* Sensirion */ +#define RT_SENSOR_VENDOR_TI (11) /* Texas Instruments */ +#define RT_SENSOR_VENDOR_PLANTOWER (12) /* Plantower */ +#define RT_SENSOR_VENDOR_AMS (13) /* ams AG */ +#define RT_SENSOR_VENDOR_MAXIM (14) /* Maxim Integrated */ -/* - * SENSOR_TYPE_STEP_COUNTER - * trigger-mode: on-change - * wake-up sensor: no - * - * A sensor of this type returns the number of steps taken by the user since - * the last reboot while activated. The value is returned as a uint64_t and is - * reset to zero only on a system / android reboot. - * - * The timestamp of the event is set to the time when the first step - * for that event was taken. - * See SENSOR_TYPE_STEP_DETECTOR for the signification of the time of a step. - * - * The minimum size of the hardware's internal counter shall be 16 bits - * (this restriction is here to avoid too frequent wake-ups when the - * delay is very large). - * - * IMPORTANT NOTE: this sensor type is different from other types - * in that it must work when the screen is off without the need of - * holding a partial wake-lock and MUST allow the SoC to go into suspend. - * Unlike other sensors, while in suspend mode this sensor must stay active, - * no events are reported during that time but, steps continue to be - * accounted for; an event will be reported as soon as the SoC resumes if - * the timeout has expired. - * - * In other words, when the screen is off and the device allowed to - * go into suspend mode, we don't want to be woken up, regardless of the - * setDelay() value, but the steps shall continue to be counted. - * - * The driver must however ensure that the internal step count never - * overflows. It is allowed in this situation to wake the SoC up so the - * driver can do the counter maintenance. - * - * While this sensor operates, it shall not disrupt any other sensors, in - * particular, but not limited to, the accelerometer; which might very well - * be in use as well. - * - * If a particular hardware cannot support these modes of operation then this - * sensor type MUST NOT be reported by the HAL. ie: it is not acceptable - * to "emulate" this sensor in the HAL. - * - * This sensor must be low power. That is, if the step detection cannot be - * done in hardware, this sensor should not be defined. Also, when the - * step counter is activated and the accelerometer is not, only steps should - * trigger interrupts (not accelerometer data). - * - * The whole point of this sensor type is to save power by keeping the - * SoC in suspend mode when the device is at rest. - */ -#define SENSOR_TYPE_STEP_COUNTER (19) +/* Sensor unit types */ -/* - * SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR - * trigger-mode: continuous - * wake-up sensor: no - * - * Similar to SENSOR_TYPE_ROTATION_VECTOR, but using a magnetometer instead - * of using a gyroscope. - * - * This sensor must be based on a magnetometer. It cannot be implemented using - * a gyroscope, and gyroscope input cannot be used by this sensor, as the - * goal of this sensor is to be low power. - * The accelerometer can be (and usually is) used. - * - * Just like SENSOR_TYPE_ROTATION_VECTOR, this sensor reports an estimated - * heading accuracy: - * sensors_event_t.data[4] = estimated_accuracy (in radians) - * The heading error must be less than estimated_accuracy 95% of the time - * - * see SENSOR_TYPE_ROTATION_VECTOR for more details - */ -#define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR (20) +#define RT_SENSOR_UNIT_NONE (0) +#define RT_SENSOR_UNIT_MG (1) /* Accelerometer unit: mG */ +#define RT_SENSOR_UNIT_MDPS (2) /* Gyroscope unit: mdps */ +#define RT_SENSOR_UNIT_MGAUSS (3) /* Magnetometer unit: mGauss */ +#define RT_SENSOR_UNIT_LUX (4) /* Ambient light unit: lux */ +#define RT_SENSOR_UNIT_CM (5) /* Distance unit: cm */ +#define RT_SENSOR_UNIT_PA (6) /* Barometer unit: pa */ +#define RT_SENSOR_UNIT_PERMILLAGE (7) /* Relative Humidity unit: permillage */ +#define RT_SENSOR_UNIT_DCELSIUS (8) /* Temperature unit: dCelsius */ +#define RT_SENSOR_UNIT_HZ (9) /* Frequency unit: HZ */ +#define RT_SENSOR_UNIT_ONE (10) /* Dimensionless quantity unit: 1 */ +#define RT_SENSOR_UNIT_BPM (11) /* Heart rate unit: bpm */ +#define RT_SENSOR_UNIT_MM (12) /* Distance unit: mm */ +#define RT_SENSOR_UNIT_MN (13) /* Force unit: mN */ +#define RT_SENSOR_UNIT_PPM (14) /* Concentration unit: ppm */ +#define RT_SENSOR_UNIT_PPB (15) /* Concentration unit: ppb */ +#define RT_SENSOR_UNIT_DMS (16) /* Coordinates unit: DMS */ +#define RT_SENSOR_UNIT_DD (17) /* Coordinates unit: DD */ -/** - * Values returned by the accelerometer in various locations in the universe. - * all values are in SI units (m/s^2) - */ -#define SENSORS_GRAVITY_SUN (275.0f) -#define SENSORS_GRAVITY_MOON (1.6f) -#define SENSORS_GRAVITY_EARTH (9.80665f) -#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH) +/* Sensor communication interface types */ -/** Maximum magnetic field on Earth's surface */ -#define MAGNETIC_FIELD_EARTH_MAX (60.0f) +#define RT_SENSOR_INTF_I2C (1 << 0) +#define RT_SENSOR_INTF_SPI (1 << 1) +#define RT_SENSOR_INTF_UART (1 << 2) +#define RT_SENSOR_INTF_ONEWIRE (1 << 3) -/** Minimum magnetic field on Earth's surface */ -#define MAGNETIC_FIELD_EARTH_MIN (30.0f) +/* Sensor power mode types */ -/** Average sea level pressure is 1013.25 hPa */ -#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) +#define RT_SENSOR_POWER_NONE (0) +#define RT_SENSOR_POWER_DOWN (1) /* power down mode */ +#define RT_SENSOR_POWER_NORMAL (2) /* normal-power mode */ +#define RT_SENSOR_POWER_LOW (3) /* low-power mode */ +#define RT_SENSOR_POWER_HIGH (4) /* high-power mode */ -/** Degrees/s to rad/s multiplier */ -#define SENSORS_DPS_TO_RADS (0.017453293F) -/** Gauss to micro-Tesla multiplier */ -#define SENSORS_GAUSS_TO_MICROTESLA (100) +/* Sensor work mode types */ -/** - * status of orientation sensor - */ -#define SENSOR_STATUS_UNRELIABLE 0 -#define SENSOR_STATUS_ACCURACY_LOW 1 -#define SENSOR_STATUS_ACCURACY_MEDIUM 2 -#define SENSOR_STATUS_ACCURACY_HIGH 3 +#define RT_SENSOR_MODE_NONE (0) +#define RT_SENSOR_MODE_POLLING (1) /* One shot only read a data */ +#define RT_SENSOR_MODE_INT (2) /* TODO: One shot interrupt only read a data */ +#define RT_SENSOR_MODE_FIFO (3) /* TODO: One shot interrupt read all fifo data */ -/** - * sensor event data - */ -typedef struct -{ - union - { - float v[3]; - struct - { - float x; - float y; - float z; - }; - struct - { - float azimuth; - float pitch; - float roll; - }; - }; - int8_t status; - uint8_t reserved[3]; -} sensors_vec_t; +/* Sensor control cmd types */ -/** - * sensor raw vector data - */ -typedef struct -{ - struct - { - int16_t x; - int16_t y; - int16_t z; - }; +#define RT_SENSOR_CTRL_GET_ID (0) /* Get device id */ +#define RT_SENSOR_CTRL_GET_INFO (1) /* Get sensor info */ +#define RT_SENSOR_CTRL_SET_RANGE (2) /* Set the measure range of sensor. unit is info of sensor */ +#define RT_SENSOR_CTRL_SET_ODR (3) /* Set output date rate. unit is HZ */ +#define RT_SENSOR_CTRL_SET_MODE (4) /* Set sensor's work mode. ex. RT_SENSOR_MODE_POLLING,RT_SENSOR_MODE_INT */ +#define RT_SENSOR_CTRL_SET_POWER (5) /* Set power mode. args type of sensor power mode. ex. RT_SENSOR_POWER_DOWN,RT_SENSOR_POWER_NORMAL */ +#define RT_SENSOR_CTRL_SELF_TEST (6) /* Take a self test */ - int8_t status; - uint8_t reserved[1]; -} sensors_raw_vec_t; +#define RT_SENSOR_CTRL_USER_CMD_START 0x100 /* User commands should be greater than 0x100 */ -/** - * uncalibrated gyroscope and magnetometer event data - */ -typedef struct +struct rt_sensor_info { - union - { - float uncalib[3]; - struct - { - float x_uncalib; - float y_uncalib; - float z_uncalib; - }; - }; - union - { - float bias[3]; - struct - { - float x_bias; - float y_bias; - float z_bias; - }; - }; -} uncalibrated_event_t; + rt_uint8_t type; /* The sensor type */ + rt_uint8_t vendor; /* Vendor of sensors */ + const char *model; /* model name of sensor */ + rt_uint8_t unit; /* unit of measurement */ + rt_uint8_t intf_type; /* Communication interface type */ + rt_int32_t range_max; /* maximum range of this sensor's value. unit is 'unit' */ + rt_int32_t range_min; /* minimum range of this sensor's value. unit is 'unit' */ + rt_uint32_t period_min; /* Minimum measurement period,unit:ms. zero = not a constant rate */ + rt_uint8_t fifo_max; +}; -typedef struct meta_data_event +struct rt_sensor_intf { - int32_t what; - int32_t sensor; -} meta_data_event_t; + char *dev_name; /* The name of the communication device */ + rt_uint8_t type; /* Communication interface type */ + void *user_data; /* Private data for the sensor. ex. i2c addr,spi cs,control I/O */ +}; -/** - * Union of the various types of sensor data - * that can be returned. - */ -typedef struct sensors_event_t +struct rt_sensor_config { - /* must be sizeof(struct sensors_event_t) */ - int32_t version; - - /* sensor identifier */ - int32_t sensor; - - /* sensor type */ - int32_t type; - - /* reserved */ - int32_t reserved0; - - /* time is in nanosecond */ - int64_t timestamp; - - union - { - union - { - float data[16]; - - /* acceleration values are in meter per second per second (m/s^2) */ - sensors_vec_t acceleration; - /* raw acceleration data */ - sensors_raw_vec_t raw_acceleration; - - /* magnetic vector values are in micro-Tesla (uT) */ - sensors_vec_t magnetic; - /* raw magnetic data */ - sensors_raw_vec_t raw_magnetic; - - /* orientation values are in degrees */ - sensors_vec_t orientation; - - /* gyroscope values are in rad/s */ - sensors_vec_t gyro; - /* raw gyroscope data */ - sensors_raw_vec_t raw_gyro; - - /* temperature is in degrees centigrade (Celsius) */ - float temperature; - - /* distance in centimeters */ - float distance; - - /* light in SI lux units */ - float light; - - /* pressure in hectopascal (hPa) */ - float pressure; - - /* relative humidity in percent */ - float relative_humidity; - - /* uncalibrated gyroscope values are in rad/s */ - uncalibrated_event_t uncalibrated_gyro; - - /* uncalibrated magnetometer values are in micro-Teslas */ - uncalibrated_event_t uncalibrated_magnetic; - - /* this is a special event. see SENSOR_TYPE_META_DATA above. - * sensors_meta_data_event_t events are all reported with a type of - * SENSOR_TYPE_META_DATA. The handle is ignored and must be zero. - */ - meta_data_event_t meta_data; - }; - - union - { - uint64_t data[8]; - - /* step-counter */ - uint64_t step_counter; - } u64; - }; - uint32_t reserved1[4]; -} sensors_event_t; + struct rt_sensor_intf intf; /* sensor interface config */ + struct rt_device_pin_mode irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */ + rt_uint8_t mode; /* sensor work mode */ + rt_uint8_t power; /* sensor power mode */ + rt_uint16_t odr; /* sensor out data rate */ + rt_int32_t range; /* sensor range of measurement */ +}; -/* see SENSOR_TYPE_META_DATA */ -typedef sensors_event_t sensors_meta_data_event_t; +typedef struct rt_sensor_device *rt_sensor_t; -typedef struct sensor_t +struct rt_sensor_device { - /* Name of this sensor. - * All sensors of the same "type" must have a different "name". - */ - const char *name; - - /* vendor of the hardware part */ - const char *vendor; - - /* version of the hardware part + driver. The value of this field - * must increase when the driver is updated in a way that changes the - * output of this sensor. This is important for fused sensors when the - * fusion algorithm is updated. - */ - int version; - - /* handle that identifies this sensors. This handle is used to reference - * this sensor throughout the HAL API. - */ - int handle; - - /* this sensor's type. */ - int type; - - /* maximum range of this sensor's value in SI units */ - float maxRange; - - /* smallest difference between two values reported by this sensor */ - float resolution; - - /* rough estimate of this sensor's power consumption in mA */ - float power; + struct rt_device parent; /* The standard device */ - /* this value depends on the trigger mode: - * - * continuous: minimum sample period allowed in microseconds - * on-change : 0 - * one-shot :-1 - * special : 0, unless otherwise noted - */ - int32_t minDelay; + struct rt_sensor_info info; /* The sensor info data */ + struct rt_sensor_config config; /* The sensor config data */ - /* number of events reserved for this sensor in the batch mode FIFO. - * If there is a dedicated FIFO for this sensor, then this is the - * size of this FIFO. If the FIFO is shared with other sensors, - * this is the size reserved for that sensor and it can be zero. - */ - uint32_t fifoReservedEventCount; + void *data_buf; /* The buf of the data received */ + rt_size_t data_len; /* The size of the data received */ - /* maximum number of events of this sensor that could be batched. - * This is especially relevant when the FIFO is shared between - * several sensors; this value is then set to the size of that FIFO. - */ - uint32_t fifoMaxEventCount; + const struct rt_sensor_ops *ops; /* The sensor ops */ - /* reserved fields, must be zero */ - void *reserved[6]; -} sensor_t; - -enum SensorMode -{ - SENSOR_MODE_RAW, - SENSOR_MODE_CALIBRATED, - SENSOR_MODE_NORMAL, + struct rt_sensor_module *module; /* The sensor module */ + + rt_err_t (*irq_handle)(rt_sensor_t sensor); /* Called when an interrupt is generated, registered by the driver */ }; -enum SensorAccelRange +struct rt_sensor_module { - SENSOR_ACCEL_RANGE_2G, - SENSOR_ACCEL_RANGE_4G, - SENSOR_ACCEL_RANGE_8G, - SENSOR_ACCEL_RANGE_16G, + rt_mutex_t lock; /* The module lock */ + + rt_sensor_t sen[RT_SENSOR_MODULE_MAX]; /* The module contains a list of sensors */ + rt_uint8_t sen_num; /* Number of sensors contained in the module */ }; -#define SENSOR_ACCEL_SENSITIVITY_2G ((float)2/32768) -#define SENSOR_ACCEL_SENSITIVITY_4G ((float)4/32768) -#define SENSOR_ACCEL_SENSITIVITY_8G ((float)8/32768) -#define SENSOR_ACCEL_SENSITIVITY_16G ((float)16/32768) -enum SensorGyroRange +/* 3-axis Data Type */ +struct sensor_3_axis { - SENSOR_GYRO_RANGE_250DPS, - SENSOR_GYRO_RANGE_500DPS, - SENSOR_GYRO_RANGE_1000DPS, - SENSOR_GYRO_RANGE_2000DPS, + rt_int32_t x; + rt_int32_t y; + rt_int32_t z; }; -#define SENSOR_GYRO_SENSITIVITY_250DPS (0.00875F) -#define SENSOR_GYRO_SENSITIVITY_500DPS (0.0175F) -#define SENSOR_GYRO_SENSITIVITY_1000DPS (0.035F) -#define SENSOR_GYRO_SENSITIVITY_2000DPS (0.070F) -enum SensorDataRate +struct coordinates { - SENSOR_DATARATE_3200HZ, - SENSOR_DATARATE_1600HZ, - SENSOR_DATARATE_800HZ, - SENSOR_DATARATE_400HZ, - SENSOR_DATARATE_200HZ, - SENSOR_DATARATE_100HZ, - SENSOR_DATARATE_50HZ, - SENSOR_DATARATE_25HZ, - SENSOR_DATARATE_12_5HZ, - SENSOR_DATARATE_6_25HZ, - SENSOR_DATARATE_3_13HZ, - SENSOR_DATARATE_1_56HZ, - SENSOR_DATARATE_0_78HZ, - SENSOR_DATARATE_0_39HZ, - SENSOR_DATARATE_0_20HZ, - SENSOR_DATARATE_0_10HZ, + double longitude; + double latitude; }; -/** - * Sensor Configuration - */ -typedef struct SensorConfig +struct rt_sensor_data { - int mode; - - enum SensorDataRate data_rate; - - union range + rt_uint32_t timestamp; /* The timestamp when the data was received */ + rt_uint8_t type; /* The sensor type of the data */ + union { - int range; - enum SensorAccelRange accel_range; - enum SensorGyroRange gyro_range; - } range; -}SensorConfig; - -typedef void (*SensorEventHandler_t)(void *user_data); - -#ifdef __cplusplus -class SensorBase; -class SensorManager; - -/** - * Sensor Base Class - */ -class SensorBase -{ -private: - int type; - -public: - SensorBase(int type); - ~SensorBase(); - - virtual int configure(SensorConfig *config) = 0; - virtual int activate(int enable) = 0; - - virtual int poll(sensors_event_t *events) = 0; - virtual void getSensor(struct sensor_t *sensor) = 0; - - int getType(void); - - int setConfig(SensorConfig *config); - int getConfig(SensorConfig *config); - - int subscribe(SensorEventHandler_t handler, void *user_data); - int publish(void); - -protected: - SensorBase *next; - SensorBase *prev; - - /* sensor configuration */ - SensorConfig config; - - SensorEventHandler_t evtHandler; - void *userData; - - friend class SensorManager; + struct sensor_3_axis acce; /* Accelerometer. unit: mG */ + struct sensor_3_axis gyro; /* Gyroscope. unit: mdps */ + struct sensor_3_axis mag; /* Magnetometer. unit: mGauss */ + struct coordinates coord; /* Coordinates unit: degrees */ + rt_int32_t temp; /* Temperature. unit: dCelsius */ + rt_int32_t humi; /* Relative humidity. unit: permillage */ + rt_int32_t baro; /* Pressure. unit: pascal (Pa) */ + rt_int32_t light; /* Light. unit: lux */ + rt_int32_t proximity; /* Distance. unit: centimeters */ + rt_int32_t hr; /* Heart rate. unit: bpm */ + rt_int32_t tvoc; /* TVOC. unit: permillage */ + rt_int32_t noise; /* Noise Loudness. unit: HZ */ + rt_uint32_t step; /* Step sensor. unit: 1 */ + rt_int32_t force; /* Force sensor. unit: mN */ + rt_uint32_t dust; /* Dust sensor. unit: ug/m3 */ + rt_uint32_t eco2; /* eCO2 sensor. unit: ppm */ + } data; }; -/** - * Sensor Manager - */ -class SensorManager +struct rt_sensor_ops { -public: - SensorManager(); - ~SensorManager(); - - static int registerSensor(SensorBase *sensor); - static int unregisterSensor(SensorBase *sensor); - - static SensorBase *getDefaultSensor(int type); - static int subscribe(int type, SensorEventHandler_t handler, void *user_data); - - static int sensorEventReady(SensorBase *sensor); - static int pollSensor(SensorBase *sensor, sensors_event_t *events, int number, int duration); + rt_size_t (*fetch_data)(struct rt_sensor_device *sensor, void *buf, rt_size_t len); + rt_err_t (*control)(struct rt_sensor_device *sensor, int cmd, void *arg); }; -#endif - -/* C programming language APIs */ -/* rt_sensor_t is a C typedef for SensorBase */ -typedef void* rt_sensor_t; - -#ifdef __cplusplus -extern "C" { -#endif -rt_sensor_t rt_sensor_get_default(int type); - -int rt_sensor_subscribe(rt_sensor_t sensor, SensorEventHandler_t handler, void *user_data); -int rt_sensor_activate (rt_sensor_t sensor, int enable); -int rt_sensor_configure(rt_sensor_t sensor, SensorConfig *config); -int rt_sensor_poll(rt_sensor_t sensor, sensors_event_t *event); +int rt_hw_sensor_register(rt_sensor_t sensor, + const char *name, + rt_uint32_t flag, + void *data); #ifdef __cplusplus } #endif -#endif +#endif /* __SENSOR_H__ */ diff --git a/components/drivers/sensors/sensor_cmd.c b/components/drivers/sensors/sensor_cmd.c new file mode 100755 index 0000000000..284db75cf6 --- /dev/null +++ b/components/drivers/sensors/sensor_cmd.c @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-01-31 flybreak first version + * 2019-07-16 WillianChan Increase the output of sensor information + * 2020-02-22 luhuadong Add vendor info and sensor types for cmd + */ + +#include "sensor.h" + +#define DBG_TAG "sensor.cmd" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#include <stdlib.h> +#include <string.h> + +static rt_sem_t sensor_rx_sem = RT_NULL; + +static void sensor_show_data(rt_size_t num, rt_sensor_t sensor, struct rt_sensor_data *sensor_data) +{ + switch (sensor->info.type) + { + case RT_SENSOR_CLASS_ACCE: + LOG_I("num:%3d, x:%5d, y:%5d, z:%5d mg, timestamp:%5d", num, sensor_data->data.acce.x, sensor_data->data.acce.y, sensor_data->data.acce.z, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_GYRO: + LOG_I("num:%3d, x:%8d, y:%8d, z:%8d dps, timestamp:%5d", num, sensor_data->data.gyro.x / 1000, sensor_data->data.gyro.y / 1000, sensor_data->data.gyro.z / 1000, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_MAG: + LOG_I("num:%3d, x:%5d, y:%5d, z:%5d mGauss, timestamp:%5d", num, sensor_data->data.mag.x, sensor_data->data.mag.y, sensor_data->data.mag.z, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_GNSS: + LOG_I("num:%3d, lon:%5d, lat:%5d, timestamp:%5d", num, sensor_data->data.coord.longitude, sensor_data->data.coord.latitude, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_TEMP: + LOG_I("num:%3d, temp:%3d.%d C, timestamp:%5d", num, sensor_data->data.temp / 10, (rt_uint32_t)sensor_data->data.temp % 10, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_HUMI: + LOG_I("num:%3d, humi:%3d.%d%%, timestamp:%5d", num, sensor_data->data.humi / 10, sensor_data->data.humi % 10, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_BARO: + LOG_I("num:%3d, press:%5d pa, timestamp:%5d", num, sensor_data->data.baro, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_LIGHT: + LOG_I("num:%3d, light:%5d lux, timestamp:%5d", num, sensor_data->data.light, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_PROXIMITY: + LOG_I("num:%3d, distance:%5d, timestamp:%5d", num, sensor_data->data.proximity, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_HR: + LOG_I("num:%3d, heart rate:%5d bpm, timestamp:%5d", num, sensor_data->data.hr, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_TVOC: + LOG_I("num:%3d, tvoc:%5d ppb, timestamp:%5d", num, sensor_data->data.tvoc, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_NOISE: + LOG_I("num:%3d, noise:%5d, timestamp:%5d", num, sensor_data->data.noise, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_STEP: + LOG_I("num:%3d, step:%5d, timestamp:%5d", num, sensor_data->data.step, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_FORCE: + LOG_I("num:%3d, force:%5d, timestamp:%5d", num, sensor_data->data.force, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_DUST: + LOG_I("num:%3d, dust:%5d ug/m3, timestamp:%5d", num, sensor_data->data.dust, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_ECO2: + LOG_I("num:%3d, eco2:%5d ppm, timestamp:%5d", num, sensor_data->data.eco2, sensor_data->timestamp); + break; + default: + break; + } +} + +static rt_err_t rx_callback(rt_device_t dev, rt_size_t size) +{ + rt_sem_release(sensor_rx_sem); + return 0; +} + +static void sensor_fifo_rx_entry(void *parameter) +{ + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; + struct rt_sensor_data *data = RT_NULL; + struct rt_sensor_info info; + rt_size_t res, i; + + rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); + + data = (struct rt_sensor_data *)rt_malloc(sizeof(struct rt_sensor_data) * info.fifo_max); + if (data == RT_NULL) + { + LOG_E("Memory allocation failed!"); + } + + while (1) + { + rt_sem_take(sensor_rx_sem, RT_WAITING_FOREVER); + + res = rt_device_read(dev, 0, data, info.fifo_max); + for (i = 0; i < res; i++) + { + sensor_show_data(i, sensor, &data[i]); + } + } +} + +static void sensor_fifo(int argc, char **argv) +{ + static rt_thread_t tid1 = RT_NULL; + rt_device_t dev = RT_NULL; + rt_sensor_t sensor; + + dev = rt_device_find(argv[1]); + if (dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[1]); + return; + } + sensor = (rt_sensor_t)dev; + + if (rt_device_open(dev, RT_DEVICE_FLAG_FIFO_RX) != RT_EOK) + { + LOG_E("open device failed!"); + return; + } + + if (sensor_rx_sem == RT_NULL) + { + sensor_rx_sem = rt_sem_create("sen_rx_sem", 0, RT_IPC_FLAG_FIFO); + } + else + { + LOG_E("The thread is running, please reboot and try again"); + return; + } + + tid1 = rt_thread_create("sen_rx_thread", + sensor_fifo_rx_entry, sensor, + 1024, + 15, 5); + + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + rt_device_set_rx_indicate(dev, rx_callback); + + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)20); +} +#ifdef FINSH_USING_MSH +MSH_CMD_EXPORT(sensor_fifo, Sensor fifo mode test function); +#endif + +static void sensor_irq_rx_entry(void *parameter) +{ + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; + struct rt_sensor_data data; + rt_size_t res, i = 0; + + while (1) + { + rt_sem_take(sensor_rx_sem, RT_WAITING_FOREVER); + + res = rt_device_read(dev, 0, &data, 1); + if (res == 1) + { + sensor_show_data(i++, sensor, &data); + } + } +} + +static void sensor_int(int argc, char **argv) +{ + static rt_thread_t tid1 = RT_NULL; + rt_device_t dev = RT_NULL; + rt_sensor_t sensor; + + dev = rt_device_find(argv[1]); + if (dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[1]); + return; + } + sensor = (rt_sensor_t)dev; + + if (sensor_rx_sem == RT_NULL) + { + sensor_rx_sem = rt_sem_create("sen_rx_sem", 0, RT_IPC_FLAG_FIFO); + } + else + { + LOG_E("The thread is running, please reboot and try again"); + return; + } + + tid1 = rt_thread_create("sen_rx_thread", + sensor_irq_rx_entry, sensor, + 1024, + 15, 5); + + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + rt_device_set_rx_indicate(dev, rx_callback); + + if (rt_device_open(dev, RT_DEVICE_FLAG_INT_RX) != RT_EOK) + { + LOG_E("open device failed!"); + return; + } + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)20); +} +#ifdef FINSH_USING_MSH +MSH_CMD_EXPORT(sensor_int, Sensor interrupt mode test function); +#endif + +static void sensor_polling(int argc, char **argv) +{ + uint16_t num = 10; + rt_device_t dev = RT_NULL; + rt_sensor_t sensor; + struct rt_sensor_data data; + rt_size_t res, i; + rt_int32_t delay; + + dev = rt_device_find(argv[1]); + if (dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[1]); + return; + } + if (argc > 2) + num = atoi(argv[2]); + + sensor = (rt_sensor_t)dev; + delay = sensor->info.period_min > 100 ? sensor->info.period_min : 100; + + if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) + { + LOG_E("open device failed!"); + return; + } + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100); + + for (i = 0; i < num; i++) + { + res = rt_device_read(dev, 0, &data, 1); + if (res != 1) + { + LOG_E("read data failed!size is %d", res); + } + else + { + sensor_show_data(i, sensor, &data); + } + rt_thread_mdelay(delay); + } + rt_device_close(dev); +} +#ifdef FINSH_USING_MSH +MSH_CMD_EXPORT(sensor_polling, Sensor polling mode test function); +#endif + +static void sensor(int argc, char **argv) +{ + static rt_device_t dev = RT_NULL; + struct rt_sensor_data data; + rt_sensor_t sensor; + rt_size_t res, i; + rt_int32_t delay; + + /* If the number of arguments less than 2 */ + if (argc < 2) + { + rt_kprintf("\n"); + rt_kprintf("sensor [OPTION] [PARAM]\n"); + rt_kprintf(" probe <dev_name> Probe sensor by given name\n"); + rt_kprintf(" info Get sensor info\n"); + rt_kprintf(" sr <var> Set range to var\n"); + rt_kprintf(" sm <var> Set work mode to var\n"); + rt_kprintf(" sp <var> Set power mode to var\n"); + rt_kprintf(" sodr <var> Set output date rate to var\n"); + rt_kprintf(" read [num] Read [num] times sensor\n"); + rt_kprintf(" num default 5\n"); + return ; + } + else if (!strcmp(argv[1], "info")) + { + struct rt_sensor_info info; + if (dev == RT_NULL) + { + LOG_W("Please probe sensor device first!"); + return ; + } + rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); + switch (info.vendor) + { + case RT_SENSOR_VENDOR_UNKNOWN: + rt_kprintf("vendor :unknown vendor\n"); + break; + case RT_SENSOR_VENDOR_STM: + rt_kprintf("vendor :STMicroelectronics\n"); + break; + case RT_SENSOR_VENDOR_BOSCH: + rt_kprintf("vendor :Bosch\n"); + break; + case RT_SENSOR_VENDOR_INVENSENSE: + rt_kprintf("vendor :Invensense\n"); + break; + case RT_SENSOR_VENDOR_SEMTECH: + rt_kprintf("vendor :Semtech\n"); + break; + case RT_SENSOR_VENDOR_GOERTEK: + rt_kprintf("vendor :Goertek\n"); + break; + case RT_SENSOR_VENDOR_MIRAMEMS: + rt_kprintf("vendor :MiraMEMS\n"); + break; + case RT_SENSOR_VENDOR_DALLAS: + rt_kprintf("vendor :Dallas\n"); + break; + case RT_SENSOR_VENDOR_ASAIR: + rt_kprintf("vendor :Asair\n"); + break; + case RT_SENSOR_VENDOR_SHARP: + rt_kprintf("vendor :Sharp\n"); + break; + case RT_SENSOR_VENDOR_SENSIRION: + rt_kprintf("vendor :Sensirion\n"); + break; + case RT_SENSOR_VENDOR_TI: + rt_kprintf("vendor :Texas Instruments\n"); + break; + case RT_SENSOR_VENDOR_PLANTOWER: + rt_kprintf("vendor :Plantower\n"); + break; + case RT_SENSOR_VENDOR_AMS: + rt_kprintf("vendor :AMS\n"); + break; + case RT_SENSOR_VENDOR_MAXIM: + rt_kprintf("vendor :Maxim Integrated\n"); + break; + } + rt_kprintf("model :%s\n", info.model); + switch (info.unit) + { + case RT_SENSOR_UNIT_NONE: + rt_kprintf("unit :none\n"); + break; + case RT_SENSOR_UNIT_MG: + rt_kprintf("unit :mG\n"); + break; + case RT_SENSOR_UNIT_MDPS: + rt_kprintf("unit :mdps\n"); + break; + case RT_SENSOR_UNIT_MGAUSS: + rt_kprintf("unit :mGauss\n"); + break; + case RT_SENSOR_UNIT_LUX: + rt_kprintf("unit :lux\n"); + break; + case RT_SENSOR_UNIT_CM: + rt_kprintf("unit :cm\n"); + break; + case RT_SENSOR_UNIT_PA: + rt_kprintf("unit :pa\n"); + break; + case RT_SENSOR_UNIT_PERMILLAGE: + rt_kprintf("unit :permillage\n"); + break; + case RT_SENSOR_UNIT_DCELSIUS: + rt_kprintf("unit :Celsius\n"); + break; + case RT_SENSOR_UNIT_HZ: + rt_kprintf("unit :HZ\n"); + break; + case RT_SENSOR_UNIT_ONE: + rt_kprintf("unit :1\n"); + break; + case RT_SENSOR_UNIT_BPM: + rt_kprintf("unit :bpm\n"); + break; + case RT_SENSOR_UNIT_MM: + rt_kprintf("unit :mm\n"); + break; + case RT_SENSOR_UNIT_MN: + rt_kprintf("unit :mN\n"); + break; + case RT_SENSOR_UNIT_PPM: + rt_kprintf("unit :ppm\n"); + break; + case RT_SENSOR_UNIT_PPB: + rt_kprintf("unit :ppb\n"); + break; + } + rt_kprintf("range_max :%d\n", info.range_max); + rt_kprintf("range_min :%d\n", info.range_min); + rt_kprintf("period_min:%dms\n", info.period_min); + rt_kprintf("fifo_max :%d\n", info.fifo_max); + } + else if (!strcmp(argv[1], "read")) + { + uint16_t num = 5; + + if (dev == RT_NULL) + { + LOG_W("Please probe sensor device first!"); + return ; + } + if (argc == 3) + { + num = atoi(argv[2]); + } + + sensor = (rt_sensor_t)dev; + delay = sensor->info.period_min > 100 ? sensor->info.period_min : 100; + + for (i = 0; i < num; i++) + { + res = rt_device_read(dev, 0, &data, 1); + if (res != 1) + { + LOG_E("read data failed!size is %d", res); + } + else + { + sensor_show_data(i, sensor, &data); + } + rt_thread_mdelay(delay); + } + } + else if (argc == 3) + { + if (!strcmp(argv[1], "probe")) + { + rt_uint8_t reg = 0xFF; + if (dev) + { + rt_device_close(dev); + } + + dev = rt_device_find(argv[2]); + if (dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[1]); + return; + } + if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) + { + LOG_E("open device failed!"); + return; + } + rt_device_control(dev, RT_SENSOR_CTRL_GET_ID, ®); + LOG_I("device id: 0x%x!", reg); + + } + else if (dev == RT_NULL) + { + LOG_W("Please probe sensor first!"); + return ; + } + else if (!strcmp(argv[1], "sr")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_RANGE, (void *)atoi(argv[2])); + } + else if (!strcmp(argv[1], "sm")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_MODE, (void *)atoi(argv[2])); + } + else if (!strcmp(argv[1], "sp")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_POWER, (void *)atoi(argv[2])); + } + else if (!strcmp(argv[1], "sodr")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)atoi(argv[2])); + } + else + { + LOG_W("Unknown command, please enter 'sensor' get help information!"); + } + } + else + { + LOG_W("Unknown command, please enter 'sensor' get help information!"); + } +} +#ifdef FINSH_USING_MSH +MSH_CMD_EXPORT(sensor, sensor test function); +#endif diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index c5932df7d9..2511f18102 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -22,16 +22,16 @@ * 2017-11-15 JasonJia fix poll rx issue when data is full. * add TCFLSH and FIONREAD support. * 2018-12-08 Ernest Chen add DMA choice + * 2020-09-14 WillianChan add a line feed to the carriage return character + * when using interrupt tx */ #include <rthw.h> #include <rtthread.h> #include <rtdevice.h> -// #define DEBUG_ENABLE -#define DEBUG_LEVEL DBG_LOG -#define DBG_SECTION_NAME "UART" -#define DEBUG_COLOR +#define DBG_TAG "UART" +#define DBG_LVL DBG_INFO #include <rtdbg.h> #ifdef RT_USING_POSIX @@ -317,6 +317,19 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * while (length) { + /* + * to be polite with serial console add a line feed + * to the carriage return character + */ + if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) + { + if (serial->ops->putc(serial, '\r') == -1) + { + rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER); + continue; + } + } + if (serial->ops->putc(serial, *(char*)data) == -1) { rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER); @@ -329,6 +342,20 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * return size - length; } +static void _serial_check_buffer_size(void) +{ + static rt_bool_t already_output = RT_FALSE; + + if (already_output == RT_FALSE) + { +#if !defined(RT_USING_ULOG) || defined(ULOG_USING_ISR_LOG) + LOG_W("Warning: There is no enough buffer for saving data," + " please increase the RT_SERIAL_RB_BUFSZ option."); +#endif + already_output = RT_TRUE; + } +} + #if defined(RT_USING_POSIX) || defined(RT_SERIAL_USING_DMA) static rt_size_t _serial_fifo_calc_recved_len(struct rt_serial_device *serial) { @@ -430,12 +457,11 @@ static void rt_dma_recv_update_put_index(struct rt_serial_device *serial, rt_siz } } - if(rx_fifo->is_full == RT_TRUE) + if(rx_fifo->is_full == RT_TRUE) { - rx_fifo->get_index = rx_fifo->put_index; - } - - if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + _serial_check_buffer_size(); + rx_fifo->get_index = rx_fifo->put_index; + } } /* @@ -478,7 +504,7 @@ rt_inline int _serial_dma_rx(struct rt_serial_device *serial, rt_uint8_t *data, RT_ASSERT(rx_fifo != RT_NULL); - if (length < fifo_recved_len) + if (length < (int)fifo_recved_len) recv_len = length; else recv_len = fifo_recved_len; @@ -566,13 +592,11 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) LOG_D("open serial device: 0x%08x with open flag: 0x%04x", dev, oflag); -#ifdef RT_SERIAL_USING_DMA /* check device flag with the open flag */ if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX)) return -RT_EIO; if ((oflag & RT_DEVICE_FLAG_DMA_TX) && !(dev->flag & RT_DEVICE_FLAG_DMA_TX)) return -RT_EIO; -#endif /* RT_SERIAL_USING_DMA */ if ((oflag & RT_DEVICE_FLAG_INT_RX) && !(dev->flag & RT_DEVICE_FLAG_INT_RX)) return -RT_EIO; if ((oflag & RT_DEVICE_FLAG_INT_TX) && !(dev->flag & RT_DEVICE_FLAG_INT_TX)) @@ -679,6 +703,8 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) serial->serial_tx = tx_dma; dev->open_flag |= RT_DEVICE_FLAG_DMA_TX; + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CONFIG, (void *)RT_DEVICE_FLAG_DMA_TX); } #endif /* RT_SERIAL_USING_DMA */ else @@ -722,6 +748,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(rx_fifo); serial->serial_rx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; + /* configure low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX); } @@ -743,10 +770,11 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(rx_fifo); } - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX); serial->serial_rx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX; + + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX); } #endif /* RT_SERIAL_USING_DMA */ @@ -760,6 +788,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(tx_fifo); serial->serial_tx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; + /* configure low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); } @@ -771,10 +800,19 @@ static rt_err_t rt_serial_close(struct rt_device *dev) tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx; RT_ASSERT(tx_dma != RT_NULL); + rt_data_queue_deinit(&(tx_dma->data_queue)); + rt_free(tx_dma); serial->serial_tx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX; + + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_TX); } + + serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL); + dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; + #endif /* RT_SERIAL_USING_DMA */ return RT_EOK; } @@ -793,16 +831,16 @@ static rt_size_t rt_serial_read(struct rt_device *dev, if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) { - return _serial_int_rx(serial, buffer, size); + return _serial_int_rx(serial, (rt_uint8_t *)buffer, size); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) { - return _serial_dma_rx(serial, buffer, size); + return _serial_dma_rx(serial, (rt_uint8_t *)buffer, size); } #endif /* RT_SERIAL_USING_DMA */ - return _serial_poll_rx(serial, buffer, size); + return _serial_poll_rx(serial, (rt_uint8_t *)buffer, size); } static rt_size_t rt_serial_write(struct rt_device *dev, @@ -819,17 +857,17 @@ static rt_size_t rt_serial_write(struct rt_device *dev, if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) { - return _serial_int_tx(serial, buffer, size); + return _serial_int_tx(serial, (const rt_uint8_t *)buffer, size); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) { - return _serial_dma_tx(serial, buffer, size); + return _serial_dma_tx(serial, (const rt_uint8_t *)buffer, size); } #endif /* RT_SERIAL_USING_DMA */ else { - return _serial_poll_tx(serial, buffer, size); + return _serial_poll_tx(serial, (const rt_uint8_t *)buffer, size); } } @@ -884,6 +922,7 @@ static int _get_baudrate(speed_t speed) static void _tc_flush(struct rt_serial_device *serial, int queue) { + rt_base_t level; int ch = -1; struct rt_serial_rx_fifo *rx_fifo = RT_NULL; struct rt_device *device = RT_NULL; @@ -903,10 +942,12 @@ static void _tc_flush(struct rt_serial_device *serial, int queue) if((device->open_flag & RT_DEVICE_FLAG_INT_RX) || (device->open_flag & RT_DEVICE_FLAG_DMA_RX)) { RT_ASSERT(RT_NULL != rx_fifo); + level = rt_hw_interrupt_disable(); rt_memset(rx_fifo->buffer, 0, serial->config.bufsz); rx_fifo->put_index = 0; rx_fifo->get_index = 0; rx_fifo->is_full = RT_FALSE; + rt_hw_interrupt_enable(level); } else { @@ -1171,6 +1212,8 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) rx_fifo->get_index += 1; rx_fifo->is_full = RT_TRUE; if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + + _serial_check_buffer_size(); } /* enable interrupt */ @@ -1272,4 +1315,3 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) #endif /* RT_SERIAL_USING_DMA */ } } - diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript index b88671ebc9..e19f30861f 100644 --- a/components/drivers/spi/SConscript +++ b/components/drivers/spi/SConscript @@ -14,24 +14,9 @@ src_device = [] if GetDepend('RT_USING_SPI_WIFI'): src_device += ['spi_wifi_rw009.c'] -if GetDepend('RT_USING_W25QXX'): - src_device += ['spi_flash_w25qxx.c'] - -if GetDepend('RT_USING_W25QXX_MTD'): - src_device += ['spi_flash_w25qxx_mtd.c'] - if GetDepend('RT_USING_ENC28J60'): src_device += ['enc28j60.c'] -if GetDepend('RT_USING_AT45DBXX'): - src_device += ['spi_flash_at45dbxx.c'] - -if GetDepend('RT_USING_SST25VFXX'): - src_device += ['spi_flash_sst25vfxx.c'] - -if GetDepend('RT_USING_GD'): - src_device += ['spi_flash_gd.c'] - if GetDepend('RT_USING_SPI_MSD'): src_device += ['spi_msd.c'] diff --git a/components/drivers/spi/device_driver_list.txt b/components/drivers/spi/device_driver_list.txt index 2c9d6a16b8..939baa7531 100644 --- a/components/drivers/spi/device_driver_list.txt +++ b/components/drivers/spi/device_driver_list.txt @@ -5,11 +5,5 @@ http://www.rt-thread.com/ enc28j60.c/enc28j60.h http://www.microchip.com/ -spi_flash_at45dbxx.c/spi_flash_at45dbxx.h -http://www.atmel.com/ - -spi_flash_sst25vfxx.c/spi_flash_sst25vfxx.h -http://www.microchip.com/ - -spi_flash_w25qxx.c/spi_flash_w25qxx.h -http://www.winbond.com/ +spi_flash_sfud: Serial Flash Universal Driver +https://github.com/armink/SFUD
\ No newline at end of file diff --git a/components/drivers/spi/sfud/inc/sfud_cfg.h b/components/drivers/spi/sfud/inc/sfud_cfg.h index 051de6d577..01255775c8 100644 --- a/components/drivers/spi/sfud/inc/sfud_cfg.h +++ b/components/drivers/spi/sfud/inc/sfud_cfg.h @@ -38,6 +38,18 @@ #define SFUD_DEBUG_MODE #endif +#ifdef RT_DEBUG_SFUD +#define DBG_LVL DBG_LOG +#define SFUD_DEBUG(fmt, ...) LOG_D("(%s:%ld) "fmt"", __FILE__, __LINE__, ##__VA_ARGS__) +#else +#define DBG_LVL DBG_INFO +#endif /* RT_DEBUG_SFUD */ + +#define DBG_TAG "SFUD" +#include <rtdbg.h> +extern void rt_kprintf(const char *fmt, ...); +#define SFUD_INFO(...) LOG_I(__VA_ARGS__) + /** * Using probe flash JEDEC SFDP parameter. */ @@ -59,6 +71,6 @@ #define SFUD_USING_FLASH_INFO_TABLE #endif -#define SFUD_FLASH_DEVICE_TABLE {0} +#define SFUD_FLASH_DEVICE_TABLE {{0}} #endif /* _SFUD_CFG_H_ */ diff --git a/components/drivers/spi/sfud/inc/sfud_flash_def.h b/components/drivers/spi/sfud/inc/sfud_flash_def.h index 8922375557..03b95cd008 100644 --- a/components/drivers/spi/sfud/inc/sfud_flash_def.h +++ b/components/drivers/spi/sfud/inc/sfud_flash_def.h @@ -87,7 +87,7 @@ typedef struct { #define SFUD_MF_ID_FUDAN 0xA1 #define SFUD_MF_ID_HYUNDAI 0xAD #define SFUD_MF_ID_SST 0xBF -#define SFUD_MF_ID_MICRONIX 0xC2 +#define SFUD_MF_ID_MACRONIX 0xC2 #define SFUD_MF_ID_GIGADEVICE 0xC8 #define SFUD_MF_ID_ISSI 0xD5 #define SFUD_MF_ID_WINBOND 0xEF @@ -110,7 +110,7 @@ typedef struct { {"GigaDevice", SFUD_MF_ID_GIGADEVICE}, \ {"ISSI", SFUD_MF_ID_ISSI}, \ {"Winbond", SFUD_MF_ID_WINBOND}, \ - {"Micronix", SFUD_MF_ID_MICRONIX}, \ + {"Macronix", SFUD_MF_ID_MACRONIX}, \ } #ifdef SFUD_USING_FLASH_INFO_TABLE @@ -124,6 +124,8 @@ typedef struct { {"AT45DB161E", SFUD_MF_ID_ATMEL, 0x26, 0x00, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER, 512, 0x81}, \ {"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ + {"W25Q64CV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ + {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20}, \ @@ -142,7 +144,7 @@ typedef struct { #endif /* SFUD_USING_FLASH_INFO_TABLE */ #ifdef SFUD_USING_QSPI -/* This table saves flash read-fast instructions in QSPI mode, +/* This table saves flash read-fast instructions in QSPI mode, * SFUD can use this table to select the most appropriate read instruction for flash. * | mf_id | type_id | capacity_id | qspi_read_mode | */ @@ -155,7 +157,7 @@ typedef struct { /* W25Q16BV */ \ {SFUD_MF_ID_WINBOND, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT}, \ /* W25Q32BV */ \ - {SFUD_MF_ID_WINBOND, 0x40, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT}, \ + {SFUD_MF_ID_WINBOND, 0x40, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT|QUAD_OUTPUT|QUAD_IO}, \ /* W25Q64JV */ \ {SFUD_MF_ID_WINBOND, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \ /* W25Q128JV */ \ @@ -171,7 +173,9 @@ typedef struct { /* A25LQ64 */ \ {SFUD_MF_ID_AMIC, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_IO}, \ /* MX25L3206E and KH25L3206E */ \ - {SFUD_MF_ID_MICRONIX, 0x20, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT}, \ + {SFUD_MF_ID_MACRONIX, 0x20, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT}, \ + /* MX25L51245G */ \ + {SFUD_MF_ID_MACRONIX, 0x20, 0x1A, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \ /* GD25Q64B */ \ {SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT}, \ } diff --git a/components/drivers/spi/sfud/src/sfud.c b/components/drivers/spi/sfud/src/sfud.c index 6cfd1191ef..e5b03131ff 100644 --- a/components/drivers/spi/sfud/src/sfud.c +++ b/components/drivers/spi/sfud/src/sfud.c @@ -603,7 +603,8 @@ static sfud_err page256_or_1_byte_write(const sfud_flash *flash, uint32_t addr, const uint8_t *data) { sfud_err result = SFUD_SUCCESS; const sfud_spi *spi = &flash->spi; - uint8_t cmd_data[5 + SFUD_WRITE_MAX_PAGE_SIZE], cmd_size; + static uint8_t cmd_data[5 + SFUD_WRITE_MAX_PAGE_SIZE]; + uint8_t cmd_size; size_t data_size; SFUD_ASSERT(flash); @@ -690,7 +691,7 @@ __exit: static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) { sfud_err result = SFUD_SUCCESS; const sfud_spi *spi = &flash->spi; - uint8_t cmd_data[6], cmd_size; + uint8_t cmd_data[8], cmd_size; bool first_write = true; SFUD_ASSERT(flash); @@ -896,7 +897,7 @@ static sfud_err set_write_enabled(const sfud_flash *flash, bool enabled) { if (enabled && (register_status & SFUD_STATUS_REGISTER_WEL) == 0) { SFUD_INFO("Error: Can't enable write status."); return SFUD_ERR_WRITE; - } else if (!enabled && (register_status & SFUD_STATUS_REGISTER_WEL) == 1) { + } else if (!enabled && (register_status & SFUD_STATUS_REGISTER_WEL) != 0) { SFUD_INFO("Error: Can't disable write status."); return SFUD_ERR_WRITE; } diff --git a/components/drivers/spi/spi_flash_at45dbxx.c b/components/drivers/spi/spi_flash_at45dbxx.c deleted file mode 100644 index 0a30f0a328..0000000000 --- a/components/drivers/spi/spi_flash_at45dbxx.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#include <stdint.h> -#include "spi_flash_at45dbxx.h" - -#define FLASH_DEBUG -#define DMA_BUFFER_SIZE 512 - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /**< #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0x1F) /* atmel */ -#define DENSITY_CODE_011D (0x02) /* AT45DB011D Density Code : 00010 = 1-Mbit */ -#define DENSITY_CODE_021D (0x03) /* AT45DB021D Density Code : 00011 = 2-Mbit */ -#define DENSITY_CODE_041D (0x04) /* AT45DB041D Density Code : 00100 = 4-Mbit */ -#define DENSITY_CODE_081D (0x05) /* AT45DB081D Density Code : 00101 = 8-Mbit */ -#define DENSITY_CODE_161D (0x06) /* AT45DB161D Density Code : 00110 = 16-Mbit */ -#define DENSITY_CODE_321D (0x07) /* AT45DB321D Density Code : 00111 = 32-Mbit */ -#define DENSITY_CODE_642D (0x08) /* AT45DB642D Density Code : 01000 = 64-Mbit */ - -struct JEDEC_ID -{ - uint8_t manufacturer_id; /* Manufacturer ID */ - uint8_t density_code:5; /* Density Code */ - uint8_t family_code:3; /* Family Code */ - uint8_t version_code:5; /* Product Version Code */ - uint8_t mlc_code:3; /* MLC Code */ - uint8_t byte_count; /* Byte Count */ -}; - -#define AT45DB_BUFFER_1_WRITE 0x84 -#define AT45DB_BUFFER_2_WRITE 0x87 -#define AT45DB_BUFFER_1_READ 0xD4 -#define AT45DB_BUFFER_2_READ 0xD6 -#define AT45DB_B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83 -#define AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86 -#define AT45DB_MM_PAGE_TO_B1_XFER 0x53 -#define AT45DB_MM_PAGE_TO_B2_XFER 0x55 -#define AT45DB_PAGE_ERASE 0x81 -#define AT45DB_SECTOR_ERASE 0x7C -#define AT45DB_READ_STATE_REGISTER 0xD7 -#define AT45DB_MM_PAGE_READ 0xD2 -#define AT45DB_MM_PAGE_PROG_THRU_BUFFER1 0x82 -#define AT45DB_CMD_JEDEC_ID 0x9F - -static struct spi_flash_at45dbxx spi_flash_at45dbxx; - -/*****************************************************************************/ -/*Status Register Format: */ -/* ------------------------------------------------------------------------- */ -/* | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | */ -/* |--------|--------|--------|--------|--------|--------|--------|--------| */ -/* |RDY/BUSY| COMP | device density | X | X | */ -/* ------------------------------------------------------------------------- */ -/* 0:busy | | AT45DB041:0111 | protect|page size */ -/* 1:ready | | AT45DB161:1011 | */ -/* --------------------------------------------------------------------------*/ -/*****************************************************************************/ -static uint8_t AT45DB_StatusRegisterRead(void) -{ - return rt_spi_sendrecv8(spi_flash_at45dbxx.rt_spi_device, AT45DB_READ_STATE_REGISTER); -} - -static void wait_busy(void) -{ - uint16_t i = 0; - while (i++ < 10000) - { - if (AT45DB_StatusRegisterRead() & 0x80) - { - return; - } - } - FLASH_TRACE("\r\nSPI_FLASH timeout!!!\r\n"); -} - -/* RT-Thread Device Driver Interface */ -static rt_err_t AT45DB_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t AT45DB_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - - return RT_EOK; -} - -static rt_err_t AT45DB_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t AT45DB_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = 512; - geometry->sector_count = 4096; - geometry->block_size = 4096; /* block erase: 4k */ - } - - return RT_EOK; -} - -static rt_size_t AT45DB_flash_read_page_256(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 7); - send_buffer[2] = (uint8_t)(page << 1); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 256); - read_buffer += 256; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_read_page_512(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 6); - send_buffer[2] = (uint8_t)(page << 2); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 512); - read_buffer += 512; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_read_page_1024(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 5); - send_buffer[2] = (uint8_t)(page << 3); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 1024); - read_buffer += 1024; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_256(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 7); - send_buffer[2] = (uint8_t) (page << 1); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 256); - - write_buffer += 256; - page++; - - wait_busy(); - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_512(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 6); - send_buffer[2] = (uint8_t) (page << 2); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 512); - - write_buffer += 512; - page++; - - wait_busy(); - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_1024(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 5); - send_buffer[2] = (uint8_t) (page << 3); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 1024); - - write_buffer += 1024; - page++; - - wait_busy(); - } - - return size; -} - -rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - struct JEDEC_ID * JEDEC_ID; - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_at45dbxx.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 and 3 */ - cfg.max_hz = 66000000; /* Atmel RapidS Serial Interface: 66MHz Maximum Clock Frequency */ - rt_spi_configure(spi_flash_at45dbxx.rt_spi_device, &cfg); - } - - /* read JEDEC ID */ - { - uint8_t cmd; - uint8_t id_recv[6]; - JEDEC_ID = (struct JEDEC_ID *)id_recv; - - cmd = AT45DB_CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, &cmd, 1, id_recv, 6); - - /**< 1FH = Atmel */ - /**< 001 = Atmel DataFlash */ - if(JEDEC_ID->manufacturer_id != 0x1F || JEDEC_ID->family_code != 0x01) - { - FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - if(JEDEC_ID->density_code == DENSITY_CODE_011D) - { - /**< AT45DB011D Density Code : 00010 = 1-Mbit */ - FLASH_TRACE("AT45DB011D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512; /* 1-Mbit / 8 / 256 = 512 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_021D) - { - /**< AT45DB021D Density Code : 00011 = 2-Mbit */ - FLASH_TRACE("AT45DB021D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*2; /* 2-Mbit / 8 / 256 = 1024 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_041D) - { - /**< AT45DB041D Density Code : 00100 = 4-Mbit */ - FLASH_TRACE("AT45DB041D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*4; /* 4-Mbit / 8 / 256 = 2048 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_081D) - { - /**< AT45DB081D Density Code : 00101 = 8-Mbit */ - FLASH_TRACE("AT45DB081D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*8; /* 8-Mbit / 8 / 256 = 4096 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_161D) - { - /**< AT45DB161D Density Code : 00110 = 16-Mbit */ - FLASH_TRACE("AT45DB161D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 256*16; /* 16-Mbit / 8 / 512 = 4096 */ - spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_321D) - { - /**< AT45DB321D Density Code : 00111 = 32-Mbit */ - FLASH_TRACE("AT45DB321D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 256*32; /* 32-Mbit / 8 / 512 = 8192 */ - spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_642D) - { - /**< AT45DB642D Density Code : 01000 = 64-Mbit */ - FLASH_TRACE("AT45DB642D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 1024; /* Page Erase (1 Kbyte) */ - spi_flash_at45dbxx.geometry.sector_count = 128*64; /* 64-Mbit / 8 / 1024 = 8192 */ - spi_flash_at45dbxx.geometry.block_size = 1024*8; /* Block Erase (8 Kbytes) */ - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* register device */ - spi_flash_at45dbxx.flash_device.type = RT_Device_Class_Block; - spi_flash_at45dbxx.flash_device.init = AT45DB_flash_init; - spi_flash_at45dbxx.flash_device.open = AT45DB_flash_open; - spi_flash_at45dbxx.flash_device.close = AT45DB_flash_close; - spi_flash_at45dbxx.flash_device.control = AT45DB_flash_control; - - if(JEDEC_ID->density_code == DENSITY_CODE_642D) - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_1024; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_1024; - } - else if(JEDEC_ID->density_code == DENSITY_CODE_161D - || JEDEC_ID->density_code == DENSITY_CODE_321D ) - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_512; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_512; - } - else - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_256; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_256; - } - - /* no private */ - spi_flash_at45dbxx.flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash_at45dbxx.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_at45dbxx.h b/components/drivers/spi/spi_flash_at45dbxx.h deleted file mode 100644 index d1bc1a2aeb..0000000000 --- a/components/drivers/spi/spi_flash_at45dbxx.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#ifndef SPI_FLASH_AT45DBXX_H_INCLUDED -#define SPI_FLASH_AT45DBXX_H_INCLUDED - -#include <rtthread.h> -#include <drivers/spi.h> - -struct spi_flash_at45dbxx -{ - struct rt_device flash_device; - struct rt_device_blk_geometry geometry; - struct rt_spi_device * rt_spi_device; -}; - -extern rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name); - - -#endif // SPI_FLASH_AT45DBXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_gd.c b/components/drivers/spi/spi_flash_gd.c deleted file mode 100644 index 3c52035372..0000000000 --- a/components/drivers/spi/spi_flash_gd.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-10-11 fullhan copy from winbond flash - */ - -#include <stdint.h> -#include <rtthread.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_gd.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -#define PAGE_SIZE 4096 - -/* JEDEC Manufacturer's ID */ -#define MF_ID (0xC8) -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_GD25Q128 (0x4018) - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ - -#define DUMMY (0xFF) - -static struct spi_flash_device spi_flash_device; - -static void flash_lock(struct spi_flash_device * flash_device) -{ - rt_mutex_take(&flash_device->lock, RT_WAITING_FOREVER); -} - -static void flash_unlock(struct spi_flash_device * flash_device) -{ - rt_mutex_release(&flash_device->lock); -} - -static uint8_t w25qxx_read_status(void) -{ - return rt_spi_sendrecv8(spi_flash_device.rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(void) -{ - while( w25qxx_read_status() & (0x01)); -} - -/** \brief read [size] byte from [offset] to [buffer] - * - * \param offset uint32_t unit : byte - * \param buffer uint8_t* - * \param size uint32_t unit : byte - * \return uint32_t byte for read - * - */ -static uint32_t w25qxx_read(uint32_t offset, uint8_t * buffer, uint32_t size) -{ - uint8_t send_buffer[4]; - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, - send_buffer, 4, - buffer, size); - - return size; -} - -/** \brief write N page on [page] - * - * \param page_addr uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \return uint32_t - * - */ -static uint32_t w25qxx_page_write(uint32_t page_addr, const uint8_t* buffer) -{ - uint32_t index; - uint8_t send_buffer[4]; - - RT_ASSERT((page_addr&0xFF) == 0); /* page addr must align to 256byte. */ - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page_addr >> 16); - send_buffer[2] = (page_addr >> 8); - send_buffer[3] = (page_addr); - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 4); - - w25qxx_wait_busy(); // wait erase done. - - for(index=0; index < (PAGE_SIZE / 256); index++) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_PP; - send_buffer[1] = (uint8_t)(page_addr >> 16); - send_buffer[2] = (uint8_t)(page_addr >> 8); - send_buffer[3] = (uint8_t)(page_addr); - - rt_spi_send_then_send(spi_flash_device.rt_spi_device, - send_buffer, - 4, - buffer, - 256); - - buffer += 256; - page_addr += 256; - w25qxx_wait_busy(); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - return PAGE_SIZE; -} - -/* RT-Thread device interface */ -static rt_err_t w25qxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - uint8_t send_buffer[3]; - - flash_lock((struct spi_flash_device *)dev); - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 3); - - w25qxx_wait_busy(); - - flash_unlock((struct spi_flash_device *)dev); - - return RT_EOK; -} - -static rt_err_t w25qxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector; - geometry->sector_count = spi_flash_device.geometry.sector_count; - geometry->block_size = spi_flash_device.geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t w25qxx_flash_read(rt_device_t dev, - rt_off_t pos, - void* buffer, - rt_size_t size) -{ - flash_lock((struct spi_flash_device *)dev); - - w25qxx_read(pos*spi_flash_device.geometry.bytes_per_sector, - buffer, - size*spi_flash_device.geometry.bytes_per_sector); - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -static rt_size_t w25qxx_flash_write(rt_device_t dev, - rt_off_t pos, - const void* buffer, - rt_size_t size) -{ - rt_size_t i = 0; - rt_size_t block = size; - const uint8_t * ptr = buffer; - - flash_lock((struct spi_flash_device *)dev); - - while(block--) - { - w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector, - ptr); - ptr += PAGE_SIZE; - i++; - } - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops gd_device_ops = -{ - w25qxx_flash_init, - w25qxx_flash_open, - w25qxx_flash_close, - w25qxx_flash_read, - w25qxx_flash_write, - w25qxx_flash_control -}; -#endif - -rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - - /* initialize mutex */ - if (rt_mutex_init(&spi_flash_device.lock, spi_device_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - rt_kprintf("init sd lock mutex failed\n"); - return -RT_ENOSYS; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_device.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50 * 1000 * 1000; /* 50M */ - rt_spi_configure(spi_flash_device.rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - uint16_t memory_type_capacity; - - flash_lock(&spi_flash_device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, &cmd, 1, id_recv, 3); - - flash_unlock(&spi_flash_device); - - if(id_recv[0] != MF_ID) - { - FLASH_TRACE("Manufacturers ID error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash_device.geometry.bytes_per_sector = 4096; - spi_flash_device.geometry.block_size = 4096; /* block erase: 4k */ - - /* get memory type and capacity */ - memory_type_capacity = id_recv[1]; - memory_type_capacity = (memory_type_capacity << 8) | id_recv[2]; - - if(memory_type_capacity == MTC_GD25Q128) - { - FLASH_TRACE("GD128 detection\r\n"); - spi_flash_device.geometry.sector_count = 4096; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* register device */ - spi_flash_device.flash_device.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - spi_flash_device.flash_device.ops = &gd_device_ops; -#else - spi_flash_device.flash_device.init = w25qxx_flash_init; - spi_flash_device.flash_device.open = w25qxx_flash_open; - spi_flash_device.flash_device.close = w25qxx_flash_close; - spi_flash_device.flash_device.read = w25qxx_flash_read; - spi_flash_device.flash_device.write = w25qxx_flash_write; - spi_flash_device.flash_device.control = w25qxx_flash_control; -#endif - /* no private */ - spi_flash_device.flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash_device.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_gd.h b/components/drivers/spi/spi_flash_gd.h deleted file mode 100644 index 904d976ed0..0000000000 --- a/components/drivers/spi/spi_flash_gd.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-10-11 fullhan copy from winbond flash - */ - -#ifndef SPI_FLASH_GD_H_ -#define SPI_FLASH_GD_H_ - -#include <rtthread.h> - -extern rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name); - -#endif /* SPI_FLASH_GD_H_ */ diff --git a/components/drivers/spi/spi_flash_sfud.c b/components/drivers/spi/spi_flash_sfud.c index c8ff8f1b3b..2333c9ccb3 100644 --- a/components/drivers/spi/spi_flash_sfud.c +++ b/components/drivers/spi/spi_flash_sfud.c @@ -15,21 +15,20 @@ #ifdef RT_USING_SFUD -#ifdef RT_DEBUG_SFUD -#define DEBUG_TRACE rt_kprintf("[SFUD] "); rt_kprintf -#else -#define DEBUG_TRACE(...) -#endif /* RT_DEBUG_SFUD */ - #ifndef RT_SFUD_DEFAULT_SPI_CFG + +#ifndef RT_SFUD_SPI_MAX_HZ +#define RT_SFUD_SPI_MAX_HZ 50000000 +#endif + /* read the JEDEC SFDP command must run at 50 MHz or less */ #define RT_SFUD_DEFAULT_SPI_CFG \ { \ .mode = RT_SPI_MODE_0 | RT_SPI_MSB, \ .data_width = 8, \ - .max_hz = 50 * 1000 * 1000, \ + .max_hz = RT_SFUD_SPI_MAX_HZ, \ } -#endif +#endif /* RT_SFUD_DEFAULT_SPI_CFG */ #ifdef SFUD_USING_QSPI #define RT_SFUD_DEFAULT_QSPI_CFG \ @@ -39,14 +38,10 @@ .ddr_mode = 0, \ .qspi_dl_width = 4, \ } -#endif - -static char log_buf[RT_CONSOLEBUF_SIZE]; - -void sfud_log_debug(const char *file, const long line, const char *format, ...); +#endif /* SFUD_USING_QSPI */ static rt_err_t rt_sfud_control(rt_device_t dev, int cmd, void *args) { - RT_ASSERT(dev != RT_NULL); + RT_ASSERT(dev); switch (cmd) { case RT_DEVICE_CTRL_BLK_GETGEOME: { @@ -93,6 +88,10 @@ static rt_err_t rt_sfud_control(rt_device_t dev, int cmd, void *args) { static rt_size_t rt_sfud_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data); sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data); + + RT_ASSERT(dev); + RT_ASSERT(rtt_dev); + RT_ASSERT(sfud_dev); /* change the block device's logic address to physical address */ rt_off_t phy_pos = pos * rtt_dev->geometry.bytes_per_sector; rt_size_t phy_size = size * rtt_dev->geometry.bytes_per_sector; @@ -107,6 +106,10 @@ static rt_size_t rt_sfud_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_si static rt_size_t rt_sfud_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data); sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data); + + RT_ASSERT(dev); + RT_ASSERT(rtt_dev); + RT_ASSERT(sfud_dev); /* change the block device's logic address to physical address */ rt_off_t phy_pos = pos * rtt_dev->geometry.bytes_per_sector; rt_size_t phy_size = size * rtt_dev->geometry.bytes_per_sector; @@ -126,6 +129,10 @@ static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, si sfud_err result = SFUD_SUCCESS; sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data); struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data); + + RT_ASSERT(spi); + RT_ASSERT(sfud_dev); + RT_ASSERT(rtt_dev); #ifdef SFUD_USING_QSPI struct rt_qspi_device *qspi_dev = RT_NULL; #endif @@ -139,11 +146,11 @@ static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, si if(rtt_dev->rt_spi_device->bus->mode & RT_SPI_BUS_MODE_QSPI) { qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device); if (write_size && read_size) { - if (rt_qspi_send_then_recv(qspi_dev, write_buf, write_size, read_buf, read_size) == 0) { + if (rt_qspi_send_then_recv(qspi_dev, write_buf, write_size, read_buf, read_size) <= 0) { result = SFUD_ERR_TIMEOUT; } } else if (write_size) { - if (rt_qspi_send(qspi_dev, write_buf, write_size) == 0) { + if (rt_qspi_send(qspi_dev, write_buf, write_size) <= 0) { result = SFUD_ERR_TIMEOUT; } } @@ -156,11 +163,11 @@ static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, si result = SFUD_ERR_TIMEOUT; } } else if (write_size) { - if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) == 0) { + if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) <= 0) { result = SFUD_ERR_TIMEOUT; } } else { - if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) == 0) { + if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) <= 0) { result = SFUD_ERR_TIMEOUT; } } @@ -180,7 +187,12 @@ static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data); struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data); struct rt_qspi_device *qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device); - + + RT_ASSERT(spi); + RT_ASSERT(sfud_dev); + RT_ASSERT(rtt_dev); + RT_ASSERT(qspi_dev); + /* set message struct */ message.instruction.content = qspi_read_cmd_format->instruction; message.instruction.qspi_lines = qspi_read_cmd_format->instruction_lines; @@ -201,11 +213,11 @@ static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi message.parent.cs_release = 1; message.parent.cs_take = 1; message.qspi_data_lines = qspi_read_cmd_format->data_lines; - + if (rt_qspi_transfer_message(qspi_dev, &message) != read_size) { result = SFUD_ERR_TIMEOUT; } - + return result; } #endif @@ -214,6 +226,10 @@ static void spi_lock(const sfud_spi *spi) { sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data); struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data); + RT_ASSERT(spi); + RT_ASSERT(sfud_dev); + RT_ASSERT(rtt_dev); + rt_mutex_take(&(rtt_dev->lock), RT_WAITING_FOREVER); } @@ -221,6 +237,10 @@ static void spi_unlock(const sfud_spi *spi) { sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data); struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data); + RT_ASSERT(spi); + RT_ASSERT(sfud_dev); + RT_ASSERT(rtt_dev); + rt_mutex_release(&(rtt_dev->lock)); } @@ -229,47 +249,11 @@ static void retry_delay_100us(void) { rt_thread_delay((RT_TICK_PER_SECOND * 1 + 9999) / 10000); } -/** - * This function is print debug info. - * - * @param file the file which has call this function - * @param line the line number which has call this function - * @param format output format - * @param ... args - */ -void sfud_log_debug(const char *file, const long line, const char *format, ...) { - va_list args; - - /* args point to the first variable parameter */ - va_start(args, format); - rt_kprintf("[SFUD] (%s:%ld) ", file, line); - /* must use vprintf to print */ - rt_vsnprintf(log_buf, sizeof(log_buf), format, args); - rt_kprintf("%s\n", log_buf); - va_end(args); -} - -/** - * This function is print routine info. - * - * @param format output format - * @param ... args - */ -void sfud_log_info(const char *format, ...) { - va_list args; - - /* args point to the first variable parameter */ - va_start(args, format); - rt_kprintf("[SFUD] "); - /* must use vprintf to print */ - rt_vsnprintf(log_buf, sizeof(log_buf), format, args); - rt_kprintf("%s\n", log_buf); - va_end(args); -} - sfud_err sfud_spi_port_init(sfud_flash *flash) { sfud_err result = SFUD_SUCCESS; + RT_ASSERT(flash); + /* port SPI device interface */ flash->spi.wr = spi_write_read; #ifdef SFUD_USING_QSPI @@ -279,18 +263,18 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) { flash->spi.unlock = spi_unlock; flash->spi.user_data = flash; if (RT_TICK_PER_SECOND < 1000) { - rt_kprintf("[SFUD] Warning: The OS tick(%d) is less than 1000. So the flash write will take more time.\n", RT_TICK_PER_SECOND); + LOG_W("[SFUD] Warning: The OS tick(%d) is less than 1000. So the flash write will take more time.", RT_TICK_PER_SECOND); } /* 100 microsecond delay */ flash->retry.delay = retry_delay_100us; /* 60 seconds timeout */ flash->retry.times = 60 * 10000; - + return result; } #ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops flash_device_ops = +const static struct rt_device_ops flash_device_ops = { RT_NULL, RT_NULL, @@ -302,23 +286,23 @@ const static struct rt_device_ops flash_device_ops = #endif /** - * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device. + * Probe SPI flash by SFUD (Serial Flash Universal Driver) driver library and though SPI device by specified configuration. * * @param spi_flash_dev_name the name which will create SPI flash device * @param spi_dev_name using SPI device name + * @param spi_cfg SPI device configuration + * @param qspi_cfg QSPI device configuration * * @return probed SPI flash device, probe failed will return RT_NULL */ -rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name) { +rt_spi_flash_device_t rt_sfud_flash_probe_ex(const char *spi_flash_dev_name, const char *spi_dev_name, + struct rt_spi_configuration *spi_cfg, struct rt_qspi_configuration *qspi_cfg) +{ rt_spi_flash_device_t rtt_dev = RT_NULL; sfud_flash *sfud_dev = RT_NULL; char *spi_flash_dev_name_bak = RT_NULL, *spi_dev_name_bak = RT_NULL; - /* using default flash SPI configuration for initialize SPI Flash - * @note you also can change the SPI to other configuration after initialized finish */ - struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG; extern sfud_err sfud_device_init(sfud_flash *flash); #ifdef SFUD_USING_QSPI - struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG; struct rt_qspi_device *qspi_dev = RT_NULL; #endif @@ -348,7 +332,7 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const /* RT-Thread SPI device initialize */ rtt_dev->rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name); if (rtt_dev->rt_spi_device == RT_NULL || rtt_dev->rt_spi_device->parent.type != RT_Device_Class_SPIDevice) { - rt_kprintf("ERROR: SPI device %s not found!\n", spi_dev_name); + LOG_E("ERROR: SPI device %s not found!", spi_dev_name); goto error; } sfud_dev->spi.name = spi_dev_name_bak; @@ -357,12 +341,12 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const /* set the qspi line number and configure the QSPI bus */ if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) { qspi_dev = (struct rt_qspi_device *)rtt_dev->rt_spi_device; - qspi_cfg.qspi_dl_width = qspi_dev->config.qspi_dl_width; - rt_qspi_configure(qspi_dev, &qspi_cfg); + qspi_cfg->qspi_dl_width = qspi_dev->config.qspi_dl_width; + rt_qspi_configure(qspi_dev, qspi_cfg); } else -#endif - rt_spi_configure(rtt_dev->rt_spi_device, &cfg); +#endif + rt_spi_configure(rtt_dev->rt_spi_device, spi_cfg); } /* SFUD flash device initialize */ { @@ -374,7 +358,7 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const sfud_dev->user_data = rtt_dev; /* initialize SFUD device */ if (sfud_device_init(sfud_dev) != SFUD_SUCCESS) { - rt_kprintf("ERROR: SPI flash probe failed by SPI device %s.\n", spi_dev_name); + LOG_E("ERROR: SPI flash probe failed by SPI device %s.", spi_dev_name); goto error; } /* when initialize success, then copy SFUD flash device's geometry to RT-Thread SPI flash device */ @@ -384,13 +368,14 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const #ifdef SFUD_USING_QSPI /* reconfigure the QSPI bus for medium size */ if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) { - qspi_cfg.medium_size = sfud_dev->chip.capacity; - rt_qspi_configure(qspi_dev, &qspi_cfg); + qspi_cfg->medium_size = sfud_dev->chip.capacity; + rt_qspi_configure(qspi_dev, qspi_cfg); if(qspi_dev->enter_qspi_mode != RT_NULL) qspi_dev->enter_qspi_mode(qspi_dev); + + /* set data lines width */ + sfud_qspi_fast_read_enable(sfud_dev, qspi_dev->config.qspi_dl_width); } - /* set data lines width */ - sfud_qspi_fast_read_enable(sfud_dev, qspi_dev->config.qspi_dl_width); #endif /* SFUD_USING_QSPI */ } @@ -409,10 +394,10 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const rt_device_register(&(rtt_dev->flash_device), spi_flash_dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - DEBUG_TRACE("Probe SPI flash %s by SPI device %s success.\n",spi_flash_dev_name, spi_dev_name); + LOG_I("Probe SPI flash %s by SPI device %s success.",spi_flash_dev_name, spi_dev_name); return rtt_dev; } else { - rt_kprintf("ERROR: Low memory.\n"); + LOG_E("ERROR: Low memory."); goto error; } @@ -431,6 +416,26 @@ error: } /** + * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device. + * + * @param spi_flash_dev_name the name which will create SPI flash device + * @param spi_dev_name using SPI device name + * + * @return probed SPI flash device, probe failed will return RT_NULL + */ +rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name) +{ + struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG; +#ifndef SFUD_USING_QSPI + return rt_sfud_flash_probe_ex(spi_flash_dev_name, spi_dev_name, &cfg, RT_NULL); +#else + struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG; + + return rt_sfud_flash_probe_ex(spi_flash_dev_name, spi_dev_name, &cfg, &qspi_cfg); +#endif +} + +/** * Delete SPI flash device * * @param spi_flash_dev SPI flash device @@ -455,12 +460,62 @@ rt_err_t rt_sfud_flash_delete(rt_spi_flash_device_t spi_flash_dev) { return RT_EOK; } +sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name) +{ + rt_spi_flash_device_t rtt_dev = RT_NULL; + struct rt_spi_device *rt_spi_device = RT_NULL; + sfud_flash_t sfud_dev = RT_NULL; + + rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name); + if (rt_spi_device == RT_NULL || rt_spi_device->parent.type != RT_Device_Class_SPIDevice) { + LOG_E("ERROR: SPI device %s not found!", spi_dev_name); + goto __error; + } + + rtt_dev = (rt_spi_flash_device_t) (rt_spi_device->user_data); + if (rtt_dev && rtt_dev->user_data) { + sfud_dev = (sfud_flash_t) (rtt_dev->user_data); + return sfud_dev; + } else { + LOG_E("ERROR: SFUD flash device not found!"); + goto __error; + } + +__error: + return RT_NULL; +} + +sfud_flash_t rt_sfud_flash_find_by_dev_name(const char *flash_dev_name) +{ + rt_spi_flash_device_t rtt_dev = RT_NULL; + sfud_flash_t sfud_dev = RT_NULL; + + rtt_dev = (rt_spi_flash_device_t) rt_device_find(flash_dev_name); + if (rtt_dev == RT_NULL || rtt_dev->flash_device.type != RT_Device_Class_Block) { + LOG_E("ERROR: Flash device %s not found!", flash_dev_name); + goto __error; + } + + if (rtt_dev->user_data) { + sfud_dev = (sfud_flash_t) (rtt_dev->user_data); + return sfud_dev; + } else { + LOG_E("ERROR: SFUD flash device not found!"); + goto __error; + } + +__error: + return RT_NULL; +} + #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) #include <finsh.h> static void sf(uint8_t argc, char **argv) { +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +#define HEXDUMP_WIDTH 16 #define CMD_PROBE_INDEX 0 #define CMD_READ_INDEX 1 #define CMD_WRITE_INDEX 2 @@ -471,7 +526,7 @@ static void sf(uint8_t argc, char **argv) { sfud_err result = SFUD_SUCCESS; static const sfud_flash *sfud_dev = NULL; static rt_spi_flash_device_t rtt_dev = NULL, rtt_dev_bak = NULL; - size_t i = 0; + size_t i = 0, j = 0; const char* sf_help_info[] = { [CMD_PROBE_INDEX] = "sf probe [spi_device] - probe and init SPI flash by given 'spi_device'", @@ -498,12 +553,12 @@ 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; @@ -527,8 +582,8 @@ static void sf(uint8_t argc, char **argv) { rt_kprintf("Usage: %s.\n", sf_help_info[CMD_READ_INDEX]); return; } else { - addr = atol(argv[2]); - size = atol(argv[3]); + addr = strtol(argv[2], NULL, 0); + size = strtol(argv[3], NULL, 0); uint8_t *data = rt_malloc(size); if (data) { result = sfud_read(sfud_dev, addr, size, data); @@ -536,14 +591,24 @@ static void sf(uint8_t argc, char **argv) { rt_kprintf("Read the %s flash data success. Start from 0x%08X, size is %ld. The data is:\n", sfud_dev->name, addr, size); rt_kprintf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); - for (i = 0; i < size; i++) { - if (i % 16 == 0) { - rt_kprintf("[%08X] ", addr + i); + for (i = 0; i < size; i += HEXDUMP_WIDTH) + { + rt_kprintf("[%08X] ", addr + i); + /* dump hex */ + for (j = 0; j < HEXDUMP_WIDTH; j++) { + if (i + j < size) { + rt_kprintf("%02X ", data[i + j]); + } else { + rt_kprintf(" "); + } } - rt_kprintf("%02X ", data[i]); - if (((i + 1) % 16 == 0) || i == size - 1) { - rt_kprintf("\n"); + /* dump char for hex */ + for (j = 0; j < HEXDUMP_WIDTH; j++) { + if (i + j < size) { + rt_kprintf("%c", __is_print(data[i + j]) ? data[i + j] : '.'); + } } + rt_kprintf("\n"); } rt_kprintf("\n"); } @@ -557,12 +622,12 @@ static void sf(uint8_t argc, char **argv) { rt_kprintf("Usage: %s.\n", sf_help_info[CMD_WRITE_INDEX]); return; } else { - addr = atol(argv[2]); + addr = strtol(argv[2], NULL, 0); size = argc - 3; uint8_t *data = rt_malloc(size); if (data) { for (i = 0; i < size; i++) { - data[i] = atoi(argv[3 + i]); + data[i] = strtol(argv[3 + i], NULL, 0); } result = sfud_write(sfud_dev, addr, size, data); if (result == SFUD_SUCCESS) { @@ -584,8 +649,8 @@ static void sf(uint8_t argc, char **argv) { rt_kprintf("Usage: %s.\n", sf_help_info[CMD_ERASE_INDEX]); return; } else { - addr = atol(argv[2]); - size = atol(argv[3]); + addr = strtol(argv[2], NULL, 0); + size = strtol(argv[3], NULL, 0); result = sfud_erase(sfud_dev, addr, size); if (result == SFUD_SUCCESS) { rt_kprintf("Erase the %s flash data success. Start from 0x%08X, size is %ld.\n", sfud_dev->name, @@ -600,8 +665,8 @@ static void sf(uint8_t argc, char **argv) { rt_kprintf("The %s flash status register current value is 0x%02X.\n", sfud_dev->name, status); } } else if (argc == 4) { - bool is_volatile = atoi(argv[2]); - uint8_t status = atoi(argv[3]); + bool is_volatile = strtol(argv[2], NULL, 0); + uint8_t status = strtol(argv[3], NULL, 0); result = sfud_write_status(sfud_dev, is_volatile, status); if (result == SFUD_SUCCESS) { rt_kprintf("Write the %s flash status register to 0x%02X success.\n", sfud_dev->name, status); @@ -619,11 +684,13 @@ static void sf(uint8_t argc, char **argv) { addr = 0; size = sfud_dev->chip.capacity; uint32_t start_time, time_cast; - size_t write_size = SFUD_WRITE_MAX_PAGE_SIZE, read_size = SFUD_WRITE_MAX_PAGE_SIZE; + size_t write_size = SFUD_WRITE_MAX_PAGE_SIZE, read_size = SFUD_WRITE_MAX_PAGE_SIZE, cur_op_size; uint8_t *write_data = rt_malloc(write_size), *read_data = rt_malloc(read_size); if (write_data && read_data) { - rt_memset(write_data, 0x55, write_size); + for (i = 0; i < write_size; i ++) { + write_data[i] = i & 0xFF; + } /* benchmark testing */ rt_kprintf("Erasing the %s %ld bytes data, waiting...\n", sfud_dev->name, size); start_time = rt_tick_get(); @@ -639,8 +706,14 @@ static void sf(uint8_t argc, char **argv) { rt_kprintf("Writing the %s %ld bytes data, waiting...\n", sfud_dev->name, size); start_time = rt_tick_get(); for (i = 0; i < size; i += write_size) { - result = sfud_write(sfud_dev, addr + i, write_size, write_data); + if (i + write_size <= size) { + cur_op_size = write_size; + } else { + cur_op_size = size - i; + } + result = sfud_write(sfud_dev, addr + i, cur_op_size, write_data); if (result != SFUD_SUCCESS) { + rt_kprintf("Writing %s failed, already wr for %lu bytes, write %d each time\n", sfud_dev->name, i, write_size); break; } } @@ -656,18 +729,20 @@ static void sf(uint8_t argc, char **argv) { start_time = rt_tick_get(); for (i = 0; i < size; i += read_size) { if (i + read_size <= size) { - result = sfud_read(sfud_dev, addr + i, read_size, read_data); + cur_op_size = read_size; } else { - result = sfud_read(sfud_dev, addr + i, size - i, read_data); + cur_op_size = size - i; } + result = sfud_read(sfud_dev, addr + i, cur_op_size, read_data); /* data check */ - if (memcmp(write_data, read_data, read_size)) + if (memcmp(write_data, read_data, cur_op_size)) { rt_kprintf("Data check ERROR! Please check you flash by other command.\n"); result = SFUD_ERR_READ; } - + if (result != SFUD_SUCCESS) { + rt_kprintf("Read %s failed, already rd for %lu bytes, read %d each time\n", sfud_dev->name, i, read_size); break; } } @@ -698,36 +773,6 @@ static void sf(uint8_t argc, char **argv) { } } MSH_CMD_EXPORT(sf, SPI Flash operate.); - -sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name) -{ - rt_spi_flash_device_t rtt_dev = RT_NULL; - struct rt_spi_device *rt_spi_device = RT_NULL; - sfud_flash_t sfud_dev = RT_NULL; - - rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name); - if (rt_spi_device == RT_NULL || rt_spi_device->parent.type != RT_Device_Class_SPIDevice) - { - rt_kprintf("ERROR: SPI device %s not found!\n", spi_dev_name); - goto error; - } - - rtt_dev = (rt_spi_flash_device_t)(rt_spi_device->user_data); - if (rtt_dev && rtt_dev->user_data) - { - sfud_dev = (sfud_flash_t)(rtt_dev->user_data); - return sfud_dev; - } - else - { - rt_kprintf("ERROR: SFUD flash device not found!\n"); - goto error; - } - -error: - return RT_NULL; -} - #endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ #endif /* RT_USING_SFUD */ diff --git a/components/drivers/spi/spi_flash_sfud.h b/components/drivers/spi/spi_flash_sfud.h index af1ed58790..932b7f879c 100644 --- a/components/drivers/spi/spi_flash_sfud.h +++ b/components/drivers/spi/spi_flash_sfud.h @@ -27,6 +27,19 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name); /** + * Probe SPI flash by SFUD (Serial Flash Universal Driver) driver library and though SPI device by specified configuration. + * + * @param spi_flash_dev_name the name which will create SPI flash device + * @param spi_dev_name using SPI device name + * @param spi_cfg SPI device configuration + * @param qspi_cfg QSPI device configuration + * + * @return probed SPI flash device, probe failed will return RT_NULL + */ +rt_spi_flash_device_t rt_sfud_flash_probe_ex(const char *spi_flash_dev_name, const char *spi_dev_name, + struct rt_spi_configuration *spi_cfg, struct rt_qspi_configuration *qspi_cfg); + +/** * Delete SPI flash device * * @param spi_flash_dev SPI flash device @@ -36,7 +49,7 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const rt_err_t rt_sfud_flash_delete(rt_spi_flash_device_t spi_flash_dev); /** - * Find sfud flash device + * Find sfud flash device by SPI device name * * @param spi_dev_name using SPI device name * @@ -44,4 +57,13 @@ rt_err_t rt_sfud_flash_delete(rt_spi_flash_device_t spi_flash_dev); */ sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name); +/** + * Find sfud flash device by flash device name + * + * @param flash_dev_name using flash device name + * + * @return sfud flash device if success, otherwise return RT_NULL + */ +sfud_flash_t rt_sfud_flash_find_by_dev_name(const char *flash_dev_name); + #endif /* _SPI_FLASH_SFUD_H_ */ diff --git a/components/drivers/spi/spi_flash_sst25vfxx.c b/components/drivers/spi/spi_flash_sst25vfxx.c deleted file mode 100644 index bd618a8e9b..0000000000 --- a/components/drivers/spi/spi_flash_sst25vfxx.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#include <stdint.h> -#include "spi_flash_sst25vfxx.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0xBF) -/* JEDEC Device ID : Memory Type */ -#define MT_ID (0x25) -/* JEDEC Device ID: Memory Capacity */ -#define MC_ID_SST25VF020B (0x8C) /* 2Mbit */ -#define MC_ID_SST25VF040B (0x8D) /* 4Mbit */ -#define MC_ID_SST25VF080B (0x8E) /* 8Mbit */ -#define MC_ID_SST25VF016B (0x41) /* 16Mbit */ -#define MC_ID_SST25VF032B (0x4A) /* 32Mbit */ -#define MC_ID_SST25VF064C (0x4B) /* 64Mbit */ - -/* command list */ -#define CMD_RDSR (0x05) -#define CMD_WRSR (0x01) -#define CMD_EWSR (0x50) -#define CMD_WRDI (0x04) -#define CMD_WREN (0x06) -#define CMD_READ (0x03) -#define CMD_FAST_READ (0x0B) -#define CMD_BP (0x02) -#define CMD_AAIP (0xAD) -#define CMD_ERASE_4K (0x20) -#define CMD_ERASE_32K (0x52) -#define CMD_ERASE_64K (0xD8) -#define CMD_ERASE_full (0xC7) -#define CMD_JEDEC_ID (0x9F) -#define CMD_EBSY (0x70) -#define CMD_DBSY (0x80) - -#define DUMMY (0xFF) - -static struct spi_flash_sst25vfxx spi_flash_sst25vfxx; - -static uint8_t sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash) -{ - return rt_spi_sendrecv8(spi_flash->rt_spi_device, CMD_RDSR); -} - -static void sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash) -{ - while( sst25vfxx_read_status(spi_flash) & (0x01)); -} - -/** \brief write N page on [page] - * - * \param page uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \param size uint32_t unit : byte ( 4096*N ) - * \return uint32_t - * - */ -static uint32_t sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash, uint32_t page, const uint8_t * buffer, uint32_t size) -{ - uint32_t index; - uint32_t need_wirte = size; - uint8_t send_buffer[6]; - - page &= ~0xFFF; // page size = 4096byte - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page >> 16); - send_buffer[2] = (page >> 8); - send_buffer[3] = (page); - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 4); - - sst25vfxx_wait_busy(spi_flash); // wait erase done. - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_AAIP; - send_buffer[1] = (uint8_t)(page >> 16); - send_buffer[2] = (uint8_t)(page >> 8); - send_buffer[3] = (uint8_t)(page); - send_buffer[4] = *buffer++; - send_buffer[5] = *buffer++; - need_wirte -= 2; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 6); - - sst25vfxx_wait_busy(spi_flash); - - for(index=0; index < need_wirte/2; index++) - { - send_buffer[0] = CMD_AAIP; - send_buffer[1] = *buffer++; - send_buffer[2] = *buffer++; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 3); - sst25vfxx_wait_busy(spi_flash); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - return size; -} - -/* RT-Thread device interface */ -static rt_err_t sst25vfxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - rt_err_t result; - uint8_t send_buffer[2]; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return result; - } - - send_buffer[0] = CMD_DBSY; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_EWSR; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 2); - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - struct spi_flash_sst25vfxx * spi_flash; - - spi_flash = (struct spi_flash_sst25vfxx *)dev; - - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash->geometry.bytes_per_sector; - geometry->sector_count = spi_flash->geometry.sector_count; - geometry->block_size = spi_flash->geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t sst25vfxx_flash_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - rt_err_t result; - uint8_t send_buffer[4]; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - uint32_t offset = pos * spi_flash->geometry.bytes_per_sector; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return 0; - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - rt_spi_send_then_recv(spi_flash->rt_spi_device, send_buffer, 4, buffer, size * spi_flash->geometry.bytes_per_sector); - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return size; -} - -static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - uint32_t i; - rt_err_t result; - const uint8_t * write_buffer = buffer; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return 0; - } - - for(i=0; i<size; i++) - { - sst25vfxx_page_write(spi_flash, - (pos + i) * spi_flash->geometry.bytes_per_sector, - write_buffer, - spi_flash->geometry.bytes_per_sector); - write_buffer += spi_flash->geometry.bytes_per_sector; - } - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return size; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops sst25vfxx_device_ops = -{ - sst25vfxx_flash_init, - sst25vfxx_flash_open, - sst25vfxx_flash_close, - sst25vfxx_flash_read, - sst25vfxx_flash_write, - sst25vfxx_flash_control -}; -#endif - -rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - struct spi_flash_sst25vfxx * spi_flash = &spi_flash_sst25vfxx; - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash->rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50000000; /* 50M */ - rt_spi_configure(spi_flash->rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - - cmd = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash->rt_spi_device, &cmd, 1, id_recv, 3); - - if(id_recv[0] != MF_ID || id_recv[1] != MT_ID) - { - FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash->geometry.bytes_per_sector = 4096; - spi_flash->geometry.block_size = 4096; /* block erase: 4k */ - - if(id_recv[2] == MC_ID_SST25VF020B) - { - FLASH_TRACE("SST25VF020B detection\r\n"); - spi_flash->geometry.sector_count = 64; - } - else if(id_recv[2] == MC_ID_SST25VF040B) - { - FLASH_TRACE("SST25VF040B detection\r\n"); - spi_flash->geometry.sector_count = 128; - } - else if(id_recv[2] == MC_ID_SST25VF080B) - { - FLASH_TRACE("SST25VF080B detection\r\n"); - spi_flash->geometry.sector_count = 256; - } - else if(id_recv[2] == MC_ID_SST25VF016B) - { - FLASH_TRACE("SST25VF016B detection\r\n"); - spi_flash->geometry.sector_count = 512; - } - else if(id_recv[2] == MC_ID_SST25VF032B) - { - FLASH_TRACE("SST25VF032B detection\r\n"); - spi_flash->geometry.sector_count = 1024; - } - else if(id_recv[2] == MC_ID_SST25VF064C) - { - FLASH_TRACE("SST25VF064C detection\r\n"); - spi_flash->geometry.sector_count = 2048; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* initialize mutex lock */ - rt_mutex_init(&spi_flash->lock, flash_device_name, RT_IPC_FLAG_PRIO); - - /* register device */ - spi_flash->flash_device.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - spi_flash->flash_device.ops = &sst25vfxx_device_ops; -#else - spi_flash->flash_device.init = sst25vfxx_flash_init; - spi_flash->flash_device.open = sst25vfxx_flash_open; - spi_flash->flash_device.close = sst25vfxx_flash_close; - spi_flash->flash_device.read = sst25vfxx_flash_read; - spi_flash->flash_device.write = sst25vfxx_flash_write; - spi_flash->flash_device.control = sst25vfxx_flash_control; -#endif - /* no private */ - spi_flash->flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash->flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_sst25vfxx.h b/components/drivers/spi/spi_flash_sst25vfxx.h deleted file mode 100644 index 7a7283f753..0000000000 --- a/components/drivers/spi/spi_flash_sst25vfxx.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#ifndef SPI_FLASH_SST25VFXX_H_INCLUDED -#define SPI_FLASH_SST25VFXX_H_INCLUDED - -#include <rtthread.h> -#include <drivers/spi.h> - -struct spi_flash_sst25vfxx -{ - struct rt_device flash_device; - struct rt_device_blk_geometry geometry; - struct rt_spi_device * rt_spi_device; - struct rt_mutex lock; -}; - -extern rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name); - - -#endif // SPI_FLASH_SST25VFXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_w25qxx.c b/components/drivers/spi/spi_flash_w25qxx.c deleted file mode 100644 index bba9c0b5cc..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-05-06 aozima can page write. - * 2012-08-23 aozima add flash lock. - * 2012-08-24 aozima fixed write status register BUG. - */ - -#include <stdint.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_w25qxx.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -#define PAGE_SIZE 4096 - -/* JEDEC Manufacturer ID */ -#define MF_ID (0xEF) - -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_W25Q80_BV (0x4014) /* W25Q80BV */ -#define MTC_W25Q16_BV_CL_CV (0x4015) /* W25Q16BV W25Q16CL W25Q16CV */ -#define MTC_W25Q16_DW (0x6015) /* W25Q16DW */ -#define MTC_W25Q32_BV (0x4016) /* W25Q32BV */ -#define MTC_W25Q32_DW (0x6016) /* W25Q32DW */ -#define MTC_W25Q64_BV_CV (0x4017) /* W25Q64BV W25Q64CV */ -#define MTC_W25Q64_DW (0x4017) /* W25Q64DW */ -#define MTC_W25Q128_BV (0x4018) /* W25Q128BV */ -#define MTC_W25Q256_FV (TBD) /* W25Q256FV */ - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ - -#define DUMMY (0xFF) - -static struct spi_flash_device spi_flash_device; - -static void flash_lock(struct spi_flash_device * flash_device) -{ - rt_mutex_take(&flash_device->lock, RT_WAITING_FOREVER); -} - -static void flash_unlock(struct spi_flash_device * flash_device) -{ - rt_mutex_release(&flash_device->lock); -} - -static uint8_t w25qxx_read_status(void) -{ - return rt_spi_sendrecv8(spi_flash_device.rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(void) -{ - while( w25qxx_read_status() & (0x01)); -} - -/** \brief read [size] byte from [offset] to [buffer] - * - * \param offset uint32_t unit : byte - * \param buffer uint8_t* - * \param size uint32_t unit : byte - * \return uint32_t byte for read - * - */ -static uint32_t w25qxx_read(uint32_t offset, uint8_t * buffer, uint32_t size) -{ - uint8_t send_buffer[4]; - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, - send_buffer, 4, - buffer, size); - - return size; -} - -/** \brief write N page on [page] - * - * \param page_addr uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \return uint32_t - * - */ -uint32_t w25qxx_page_write(uint32_t page_addr, const uint8_t* buffer) -{ - uint32_t index; - uint8_t send_buffer[4]; - - RT_ASSERT((page_addr&0xFF) == 0); /* page addr must align to 256byte. */ - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page_addr >> 16); - send_buffer[2] = (page_addr >> 8); - send_buffer[3] = (page_addr); - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 4); - - w25qxx_wait_busy(); // wait erase done. - - for(index=0; index < (PAGE_SIZE / 256); index++) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_PP; - send_buffer[1] = (uint8_t)(page_addr >> 16); - send_buffer[2] = (uint8_t)(page_addr >> 8); - send_buffer[3] = (uint8_t)(page_addr); - - rt_spi_send_then_send(spi_flash_device.rt_spi_device, - send_buffer, - 4, - buffer, - 256); - - buffer += 256; - page_addr += 256; - w25qxx_wait_busy(); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - return PAGE_SIZE; -} - -/* RT-Thread device interface */ -static rt_err_t w25qxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - uint8_t send_buffer[3]; - - flash_lock((struct spi_flash_device *)dev); - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 3); - - w25qxx_wait_busy(); - - flash_unlock((struct spi_flash_device *)dev); - - return RT_EOK; -} - -static rt_err_t w25qxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector; - geometry->sector_count = spi_flash_device.geometry.sector_count; - geometry->block_size = spi_flash_device.geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t w25qxx_flash_read(rt_device_t dev, - rt_off_t pos, - void* buffer, - rt_size_t size) -{ - flash_lock((struct spi_flash_device *)dev); - - w25qxx_read(pos*spi_flash_device.geometry.bytes_per_sector, - buffer, - size*spi_flash_device.geometry.bytes_per_sector); - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -static rt_size_t w25qxx_flash_write(rt_device_t dev, - rt_off_t pos, - const void* buffer, - rt_size_t size) -{ - rt_size_t i = 0; - rt_size_t block = size; - const uint8_t * ptr = buffer; - - flash_lock((struct spi_flash_device *)dev); - - while(block--) - { - w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector, - ptr); - ptr += PAGE_SIZE; - i++; - } - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops w25qxx_device_ops = -{ - w25qxx_flash_init, - w25qxx_flash_open, - w25qxx_flash_close, - w25qxx_flash_read, - w25qxx_flash_write, - w25qxx_flash_control -}; -#endif - -rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - - /* initialize mutex */ - if (rt_mutex_init(&spi_flash_device.lock, spi_device_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - rt_kprintf("init sd lock mutex failed\n"); - return -RT_ENOSYS; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_device.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50 * 1000 * 1000; /* 50M */ - rt_spi_configure(spi_flash_device.rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - uint16_t memory_type_capacity; - - flash_lock(&spi_flash_device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, &cmd, 1, id_recv, 3); - - flash_unlock(&spi_flash_device); - - if(id_recv[0] != MF_ID) - { - FLASH_TRACE("Manufacturers ID error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash_device.geometry.bytes_per_sector = 4096; - spi_flash_device.geometry.block_size = 4096; /* block erase: 4k */ - - /* get memory type and capacity */ - memory_type_capacity = id_recv[1]; - memory_type_capacity = (memory_type_capacity << 8) | id_recv[2]; - - if(memory_type_capacity == MTC_W25Q128_BV) - { - FLASH_TRACE("W25Q128BV detection\r\n"); - spi_flash_device.geometry.sector_count = 4096; - } - else if(memory_type_capacity == MTC_W25Q64_BV_CV) - { - FLASH_TRACE("W25Q64BV or W25Q64CV detection\r\n"); - spi_flash_device.geometry.sector_count = 2048; - } - else if(memory_type_capacity == MTC_W25Q64_DW) - { - FLASH_TRACE("W25Q64DW detection\r\n"); - spi_flash_device.geometry.sector_count = 2048; - } - else if(memory_type_capacity == MTC_W25Q32_BV) - { - FLASH_TRACE("W25Q32BV detection\r\n"); - spi_flash_device.geometry.sector_count = 1024; - } - else if(memory_type_capacity == MTC_W25Q32_DW) - { - FLASH_TRACE("W25Q32DW detection\r\n"); - spi_flash_device.geometry.sector_count = 1024; - } - else if(memory_type_capacity == MTC_W25Q16_BV_CL_CV) - { - FLASH_TRACE("W25Q16BV or W25Q16CL or W25Q16CV detection\r\n"); - spi_flash_device.geometry.sector_count = 512; - } - else if(memory_type_capacity == MTC_W25Q16_DW) - { - FLASH_TRACE("W25Q16DW detection\r\n"); - spi_flash_device.geometry.sector_count = 512; - } - else if(memory_type_capacity == MTC_W25Q80_BV) - { - FLASH_TRACE("W25Q80BV detection\r\n"); - spi_flash_device.geometry.sector_count = 256; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* register device */ - spi_flash_device.flash_device.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - spi_flash_device.flash_device.ops = &w25qxx_device_ops; -#else - spi_flash_device.flash_device.init = w25qxx_flash_init; - spi_flash_device.flash_device.open = w25qxx_flash_open; - spi_flash_device.flash_device.close = w25qxx_flash_close; - spi_flash_device.flash_device.read = w25qxx_flash_read; - spi_flash_device.flash_device.write = w25qxx_flash_write; - spi_flash_device.flash_device.control = w25qxx_flash_control; -#endif - /* no private */ - spi_flash_device.flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash_device.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_w25qxx.h b/components/drivers/spi/spi_flash_w25qxx.h deleted file mode 100644 index 14837bc87c..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-08-23 aozima add flash lock. - */ - -#ifndef SPI_FLASH_W25QXX_H_INCLUDED -#define SPI_FLASH_W25QXX_H_INCLUDED - -#include <rtthread.h> - -extern rt_err_t w25qxx_init(const char * flash_device_name, - const char * spi_device_name); - -#endif // SPI_FLASH_W25QXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_w25qxx_mtd.c b/components/drivers/spi/spi_flash_w25qxx_mtd.c deleted file mode 100644 index 9f1ef802f6..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx_mtd.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#include <rtthread.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_w25qxx_mtd.h" - -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE printf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0xEF) -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_W25Q80_BV (0x4014) /* W25Q80BV */ -#define MTC_W25Q16_BV_CL_CV (0x4015) /* W25Q16BV W25Q16CL W25Q16CV */ -#define MTC_W25Q16_DW (0x6015) /* W25Q16DW */ -#define MTC_W25Q32_BV (0x4016) /* W25Q32BV */ -#define MTC_W25Q32_DW (0x6016) /* W25Q32DW */ -#define MTC_W25Q64_BV_CV (0x4017) /* W25Q64BV W25Q64CV */ -#define MTC_W25Q64_DW (0x4017) /* W25Q64DW */ -#define MTC_W25Q128_BV (0x4018) /* W25Q128BV */ -#define MTC_W25Q256_FV (TBD) /* W25Q256FV */ - -#define MTC_W25X80 (0x3014) - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ -#define CMD_MANU_ID (0x90) - -#define DUMMY (0xFF) - -#define FLASH_ERASE_CMD CMD_ERASE_4K -#define FLASH_BLOCK_SIZE 4096 -#define FLASH_PAGE_SIZE 256 - -static void w25qxx_lock(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_mutex_take(&mtd->lock, RT_WAITING_FOREVER); -} - -static void w25qxx_unlock(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_mutex_release(&mtd->lock); -} - -static rt_uint8_t w25qxx_read_status(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - return rt_spi_sendrecv8(mtd->rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(struct rt_mtd_nor_device *device) -{ - while( w25qxx_read_status(device) & (0x01)); -} - -static rt_err_t w25qxx_read_id(struct rt_mtd_nor_device *device) -{ - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - - w25qxx_lock(device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(mtd->rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(mtd->rt_spi_device, &cmd, 1, id_recv, 3); - - w25qxx_unlock(device); - - return (rt_uint32_t)(id_recv[0] << 16) | (id_recv[1] << 8) | id_recv[2]; -} - -static rt_size_t w25qxx_read(struct rt_mtd_nor_device *device, rt_off_t offset, rt_uint8_t *buffer, rt_size_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - - w25qxx_lock(device); - - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (rt_uint8_t)(offset>>16); - send_buffer[2] = (rt_uint8_t)(offset>>8); - send_buffer[3] = (rt_uint8_t)(offset); - rt_spi_send_then_recv(mtd->rt_spi_device, - send_buffer, 4, - buffer, length); - - w25qxx_unlock(device); - return length; -} - -static rt_size_t w25qxx_write(struct rt_mtd_nor_device *device, rt_off_t offset, const rt_uint8_t *buffer, rt_size_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - rt_uint8_t *write_ptr ; - rt_size_t write_size,write_total; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - w25qxx_lock(device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(device); // wait erase done. - - write_size = 0; - write_total = 0; - write_ptr = (rt_uint8_t *)buffer; - while(write_total < length) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - //write first page... - send_buffer[0] = CMD_PP; - send_buffer[1] = (rt_uint8_t)(offset >> 16); - send_buffer[2] = (rt_uint8_t)(offset >> 8); - send_buffer[3] = (rt_uint8_t)(offset); - - //address % FLASH_PAGE_SIZE + length - if(((offset & (FLASH_PAGE_SIZE - 1)) + (length - write_total)) > FLASH_PAGE_SIZE) - { - write_size = FLASH_PAGE_SIZE - (offset & (FLASH_PAGE_SIZE - 1)); - } - else - { - write_size = (length - write_total); - } - - rt_spi_send_then_send(mtd->rt_spi_device, - send_buffer, 4, - write_ptr + write_total, write_size); - w25qxx_wait_busy(device); - - - offset += write_size; - write_total += write_size; - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - w25qxx_unlock(device); - - return length; -} - -static rt_err_t w25qxx_erase_block(struct rt_mtd_nor_device *device, rt_off_t offset, rt_uint32_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - rt_uint32_t erase_size = 0; - - //offset must be ALIGN_DOWN to BLOCKSIZE - if(offset != RT_ALIGN_DOWN(offset,FLASH_BLOCK_SIZE)) - return 0; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - /* check length must align to block size */ - if(length % device->block_size != 0) - { - rt_kprintf("param length = %d ,error\n",length); - return 0; - } - - w25qxx_lock(device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(device); // wait erase done. - while (erase_size < length) - { - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (rt_uint8_t) (offset >> 16); - send_buffer[2] = (rt_uint8_t) (offset >> 8); - send_buffer[3] = (rt_uint8_t) (offset); - rt_spi_send(mtd->rt_spi_device, send_buffer, 4); - w25qxx_wait_busy(device); // wait erase done. - - erase_size += 4096; - offset += 4096; - } - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - w25qxx_unlock(device); - return RT_EOK; -} - -const static struct rt_mtd_nor_driver_ops w25qxx_mtd_ops = -{ - w25qxx_read_id, - w25qxx_read, - w25qxx_write, - w25qxx_erase_block, -}; - -rt_err_t w25qxx_mtd_init(const char *mtd_name,const char * spi_device_name) -{ - rt_err_t result = RT_EOK; - rt_uint32_t id; - rt_uint8_t send_buffer[3]; - - struct rt_spi_device* rt_spi_device; - struct spi_flash_mtd* mtd = (struct spi_flash_mtd *)rt_malloc(sizeof(struct spi_flash_mtd)); - - RT_ASSERT(mtd != RT_NULL); - - /* initialize mutex */ - if (rt_mutex_init(&mtd->lock, mtd_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - FLASH_TRACE("init mtd lock mutex failed\n"); - result = -RT_ENOSYS; - - goto _error_exit; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - result = -RT_ENOSYS; - - goto _error_exit; - } - mtd->rt_spi_device = rt_spi_device; - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 20 * 1000 * 1000; /* 20 */ - rt_spi_configure(rt_spi_device, &cfg); - } - - /* Init Flash device */ - { - w25qxx_lock(&mtd->mtd_device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(&mtd->mtd_device); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(mtd->rt_spi_device, send_buffer, 3); - w25qxx_wait_busy(&mtd->mtd_device); - - w25qxx_unlock(&mtd->mtd_device); - } - - id = w25qxx_read_id(&mtd->mtd_device); - - mtd->mtd_device.block_size = 4096; - mtd->mtd_device.block_start = 0; - switch(id & 0xFFFF) - { - case MTC_W25Q80_BV: /* W25Q80BV */ - mtd->mtd_device.block_end = 256; - break; - case MTC_W25Q16_BV_CL_CV: /* W25Q16BV W25Q16CL W25Q16CV */ - case MTC_W25Q16_DW: /* W25Q16DW */ - mtd->mtd_device.block_end = 512; - break; - case MTC_W25Q32_BV: /* W25Q32BV */ - case MTC_W25Q32_DW: /* W25Q32DW */ - mtd->mtd_device.block_end = 1024; - break; - case MTC_W25Q64_BV_CV: /* W25Q64BV W25Q64CV */ - mtd->mtd_device.block_end = 2048; - break; - case MTC_W25Q128_BV: /* W25Q128BV */ - mtd->mtd_device.block_end = 4086; - break; - } - mtd->mtd_device.ops = &w25qxx_mtd_ops; - rt_mtd_nor_register_device(mtd_name,&mtd->mtd_device); - - return RT_EOK; - -_error_exit: - if(mtd != RT_NULL) - rt_free(mtd); - return result; -} diff --git a/components/drivers/spi/spi_flash_w25qxx_mtd.h b/components/drivers/spi/spi_flash_w25qxx_mtd.h deleted file mode 100644 index 28f6828ffb..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx_mtd.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-08-23 aozima add flash lock. - * 2017-02-11 urey add mtd fucntion - */ - -#ifndef SPI_FLASH_W25QXX_H_INCLUDED -#define SPI_FLASH_W25QXX_H_INCLUDED - -#include <rtthread.h> - -extern rt_err_t w25qxx_mtd_init(const char *mtd_name,const char * spi_device_name); - -#endif // SPI_FLASH_W25QXX_H_INCLUDED diff --git a/components/drivers/spi/spi_msd.c b/components/drivers/spi/spi_msd.c index a109fd9488..191933e421 100644 --- a/components/drivers/spi/spi_msd.c +++ b/components/drivers/spi/spi_msd.c @@ -234,24 +234,30 @@ static rt_err_t _send_cmd( else if (type == response_r2) { /* initial message */ + /* Prevent non-aligned address access, use recv_buffer to receive data */ message.send_buf = RT_NULL; - message.recv_buf = response + 1; + message.recv_buf = recv_buffer; message.length = 1; message.cs_take = message.cs_release = 0; /* transfer message */ device->bus->ops->xfer(device, &message); + response[1] = recv_buffer[0]; } else if ((type == response_r3) || (type == response_r7)) { /* initial message */ message.send_buf = RT_NULL; - message.recv_buf = response + 1; + message.recv_buf = recv_buffer; message.length = 4; message.cs_take = message.cs_release = 0; /* transfer message */ device->bus->ops->xfer(device, &message); + response[1] = recv_buffer[0]; + response[2] = recv_buffer[1]; + response[3] = recv_buffer[2]; + response[4] = recv_buffer[3]; } else { diff --git a/components/drivers/src/dataqueue.c b/components/drivers/src/dataqueue.c index 7553986b9f..bfe8e12573 100644 --- a/components/drivers/src/dataqueue.c +++ b/components/drivers/src/dataqueue.c @@ -13,6 +13,8 @@ #include <rtdevice.h> #include <rthw.h> +#define DATAQUEUE_MAGIC 0xbead0e0e + struct rt_data_item { const void *data_ptr; @@ -26,14 +28,18 @@ rt_data_queue_init(struct rt_data_queue *queue, void (*evt_notify)(struct rt_data_queue *queue, rt_uint32_t event)) { RT_ASSERT(queue != RT_NULL); + RT_ASSERT(size > 0); queue->evt_notify = evt_notify; + queue->magic = DATAQUEUE_MAGIC; queue->size = size; queue->lwm = lwm; queue->get_index = 0; queue->put_index = 0; + queue->is_empty = 1; + queue->is_full = 0; rt_list_init(&(queue->suspended_push_list)); rt_list_init(&(queue->suspended_pop_list)); @@ -58,12 +64,13 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue, rt_err_t result; RT_ASSERT(queue != RT_NULL); + RT_ASSERT(queue->magic == DATAQUEUE_MAGIC); result = RT_EOK; thread = rt_thread_self(); level = rt_hw_interrupt_disable(); - while (queue->put_index - queue->get_index == queue->size) + while (queue->is_full) { /* queue is full */ if (timeout == 0) @@ -104,9 +111,18 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue, if (result != RT_EOK) goto __exit; } - queue->queue[queue->put_index % queue->size].data_ptr = data_ptr; - queue->queue[queue->put_index % queue->size].data_size = data_size; + queue->queue[queue->put_index].data_ptr = data_ptr; + queue->queue[queue->put_index].data_size = data_size; queue->put_index += 1; + if (queue->put_index == queue->size) + { + queue->put_index = 0; + } + queue->is_empty = 0; + if (queue->put_index == queue->get_index) + { + queue->is_full = 1; + } /* there is at least one thread in suspended list */ if (!rt_list_isempty(&(queue->suspended_pop_list))) @@ -145,8 +161,9 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue, rt_ubase_t level; rt_thread_t thread; rt_err_t result; - + RT_ASSERT(queue != RT_NULL); + RT_ASSERT(queue->magic == DATAQUEUE_MAGIC); RT_ASSERT(data_ptr != RT_NULL); RT_ASSERT(size != RT_NULL); @@ -154,7 +171,7 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue, thread = rt_thread_self(); level = rt_hw_interrupt_disable(); - while (queue->get_index == queue->put_index) + while (queue->is_empty) { /* queue is empty */ if (timeout == 0) @@ -195,12 +212,20 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue, goto __exit; } - *data_ptr = queue->queue[queue->get_index % queue->size].data_ptr; - *size = queue->queue[queue->get_index % queue->size].data_size; - + *data_ptr = queue->queue[queue->get_index].data_ptr; + *size = queue->queue[queue->get_index].data_size; queue->get_index += 1; + if (queue->get_index == queue->size) + { + queue->get_index = 0; + } + queue->is_full = 0; + if (queue->put_index == queue->get_index) + { + queue->is_empty = 1; + } - if ((queue->put_index - queue->get_index) <= queue->lwm) + if (rt_data_queue_len(queue) <= queue->lwm) { /* there is at least one thread in suspended list */ if (!rt_list_isempty(&(queue->suspended_push_list))) @@ -244,20 +269,19 @@ rt_err_t rt_data_queue_peak(struct rt_data_queue *queue, rt_size_t *size) { rt_ubase_t level; - + RT_ASSERT(queue != RT_NULL); + RT_ASSERT(queue->magic == DATAQUEUE_MAGIC); - level = rt_hw_interrupt_disable(); - - if (queue->get_index == queue->put_index) + if (queue->is_empty) { - rt_hw_interrupt_enable(level); - return -RT_EEMPTY; } - *data_ptr = queue->queue[queue->get_index % queue->size].data_ptr; - *size = queue->queue[queue->get_index % queue->size].data_size; + level = rt_hw_interrupt_disable(); + + *data_ptr = queue->queue[queue->get_index].data_ptr; + *size = queue->queue[queue->get_index].data_size; rt_hw_interrupt_enable(level); @@ -267,9 +291,21 @@ RTM_EXPORT(rt_data_queue_peak); void rt_data_queue_reset(struct rt_data_queue *queue) { + rt_ubase_t level; struct rt_thread *thread; - register rt_ubase_t temp; + + RT_ASSERT(queue != RT_NULL); + RT_ASSERT(queue->magic == DATAQUEUE_MAGIC); + + level = rt_hw_interrupt_disable(); + queue->get_index = 0; + queue->put_index = 0; + queue->is_empty = 1; + queue->is_full = 0; + + rt_hw_interrupt_enable(level); + rt_enter_critical(); /* wakeup all suspend threads */ @@ -277,7 +313,7 @@ void rt_data_queue_reset(struct rt_data_queue *queue) while (!rt_list_isempty(&(queue->suspended_pop_list))) { /* disable interrupt */ - temp = rt_hw_interrupt_disable(); + level = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(queue->suspended_pop_list.next, @@ -294,14 +330,14 @@ void rt_data_queue_reset(struct rt_data_queue *queue) rt_thread_resume(thread); /* enable interrupt */ - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); } /* resume on push list */ while (!rt_list_isempty(&(queue->suspended_push_list))) { /* disable interrupt */ - temp = rt_hw_interrupt_disable(); + level = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(queue->suspended_push_list.next, @@ -318,10 +354,61 @@ void rt_data_queue_reset(struct rt_data_queue *queue) rt_thread_resume(thread); /* enable interrupt */ - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); } rt_exit_critical(); rt_schedule(); } RTM_EXPORT(rt_data_queue_reset); + +rt_err_t rt_data_queue_deinit(struct rt_data_queue *queue) +{ + rt_ubase_t level; + + RT_ASSERT(queue != RT_NULL); + RT_ASSERT(queue->magic == DATAQUEUE_MAGIC); + + /* wakeup all suspend threads */ + rt_data_queue_reset(queue); + + level = rt_hw_interrupt_disable(); + queue->magic = 0; + rt_hw_interrupt_enable(level); + + rt_free(queue->queue); + + return RT_EOK; +} +RTM_EXPORT(rt_data_queue_deinit); + +rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue) +{ + rt_ubase_t level; + rt_int16_t len; + + RT_ASSERT(queue != RT_NULL); + RT_ASSERT(queue->magic == DATAQUEUE_MAGIC); + + if (queue->is_empty) + { + return 0; + } + + level = rt_hw_interrupt_disable(); + + if (queue->put_index > queue->get_index) + { + len = queue->put_index - queue->get_index; + } + else + { + len = queue->size + queue->put_index - queue->get_index; + } + + rt_hw_interrupt_enable(level); + + return len; +} +RTM_EXPORT(rt_data_queue_len); + diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 065fd21dc1..2a7e143f6c 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -19,6 +19,7 @@ static int pipe_fops_open(struct dfs_fd *fd) { + int rc = 0; rt_device_t device; rt_pipe_t *pipe; @@ -31,6 +32,11 @@ static int pipe_fops_open(struct dfs_fd *fd) if (device->ref_count == 0) { pipe->fifo = rt_ringbuffer_create(pipe->bufsz); + if (pipe->fifo == RT_NULL) + { + rc = -RT_ENOMEM; + goto __exit; + } } switch (fd->flags & O_ACCMODE) @@ -48,9 +54,10 @@ static int pipe_fops_open(struct dfs_fd *fd) } device->ref_count ++; +__exit: rt_mutex_release(&(pipe->lock)); - return 0; + return rc; } static int pipe_fops_close(struct dfs_fd *fd) @@ -90,13 +97,20 @@ static int pipe_fops_close(struct dfs_fd *fd) if (device->ref_count == 1) { - rt_ringbuffer_destroy(pipe->fifo); + if (pipe->fifo != RT_NULL) + rt_ringbuffer_destroy(pipe->fifo); pipe->fifo = RT_NULL; } device->ref_count --; rt_mutex_release(&(pipe->lock)); + if (device->ref_count == 0 && pipe->is_named == RT_FALSE) + { + /* delete the unamed pipe */ + rt_pipe_delete(device->parent.name); + } + return 0; } @@ -309,18 +323,29 @@ static const struct dfs_file_ops pipe_fops = rt_err_t rt_pipe_open (rt_device_t device, rt_uint16_t oflag) { rt_pipe_t *pipe = (rt_pipe_t *)device; + rt_err_t ret = RT_EOK; - if (device == RT_NULL) return -RT_EINVAL; + if (device == RT_NULL) + { + ret = -RT_EINVAL; + goto __exit; + } + rt_mutex_take(&(pipe->lock), RT_WAITING_FOREVER); if (pipe->fifo == RT_NULL) { pipe->fifo = rt_ringbuffer_create(pipe->bufsz); + if (pipe->fifo == RT_NULL) + { + ret = -RT_ENOMEM; + } } rt_mutex_release(&(pipe->lock)); - return RT_EOK; +__exit: + return ret; } rt_err_t rt_pipe_close (rt_device_t device) @@ -419,10 +444,11 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz) rt_pipe_t *pipe; rt_device_t dev; - pipe = rt_malloc(sizeof(rt_pipe_t)); + pipe = (rt_pipe_t *)rt_malloc(sizeof(rt_pipe_t)); if (pipe == RT_NULL) return RT_NULL; rt_memset(pipe, 0, sizeof(rt_pipe_t)); + pipe->is_named = RT_TRUE; /* initialize as a named pipe */ rt_mutex_init(&(pipe->lock), name, RT_IPC_FLAG_FIFO); rt_wqueue_init(&(pipe->reader_queue)); rt_wqueue_init(&(pipe->writer_queue)); @@ -517,6 +543,7 @@ int pipe(int fildes[2]) return -1; } + pipe->is_named = RT_FALSE; /* unamed pipe */ rt_snprintf(dev_name, sizeof(dev_name), "/dev/%s", dname); fildes[0] = open(dev_name, O_RDONLY, 0); if (fildes[0] < 0) diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/src/ringblk_buf.c index 74ced674fe..7d83149c5e 100644 --- a/components/drivers/src/ringblk_buf.c +++ b/components/drivers/src/ringblk_buf.c @@ -95,9 +95,9 @@ void rt_rbb_destroy(rt_rbb_t rbb) { RT_ASSERT(rbb); - rt_free(rbb); rt_free(rbb->buf); rt_free(rbb->blk_set); + rt_free(rbb); } RTM_EXPORT(rt_rbb_destroy); @@ -134,16 +134,16 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) { rt_base_t level; rt_size_t empty1 = 0, empty2 = 0; - rt_rbb_blk_t head, tail, new = NULL; + rt_rbb_blk_t head, tail, new_rbb = NULL; RT_ASSERT(rbb); RT_ASSERT(blk_size < (1L << 24)); level = rt_hw_interrupt_disable(); - new = find_empty_blk_in_set(rbb); + new_rbb = find_empty_blk_in_set(rbb); - if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new) + if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new_rbb) { if (rt_slist_len(&rbb->blk_list) > 0) { @@ -163,22 +163,22 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) if (empty1 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = tail->buf + tail->size; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = tail->buf + tail->size; + new_rbb->size = blk_size; } else if (empty2 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = rbb->buf; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = rbb->buf; + new_rbb->size = blk_size; } else { /* no space */ - new = NULL; + new_rbb = NULL; } } else @@ -194,35 +194,35 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) if (empty1 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = tail->buf + tail->size; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = tail->buf + tail->size; + new_rbb->size = blk_size; } else { /* no space */ - new = NULL; + new_rbb = NULL; } } } else { /* the list is empty */ - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = rbb->buf; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = rbb->buf; + new_rbb->size = blk_size; } } else { - new = NULL; + new_rbb = NULL; } rt_hw_interrupt_enable(level); - return new; + return new_rbb; } RTM_EXPORT(rt_rbb_blk_alloc); diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index 2e078ae053..c6a491a7cc 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -332,14 +332,15 @@ struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t size) size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); - rb = rt_malloc(sizeof(struct rt_ringbuffer)); + rb = (struct rt_ringbuffer *)rt_malloc(sizeof(struct rt_ringbuffer)); if (rb == RT_NULL) goto exit; - pool = rt_malloc(size); + pool = (rt_uint8_t *)rt_malloc(size); if (pool == RT_NULL) { rt_free(rb); + rb = RT_NULL; goto exit; } rt_ringbuffer_init(rb, pool, size); diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index 158ea8b69b..2e0280df3a 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -13,11 +13,14 @@ #include <rtdevice.h> #ifdef RT_USING_HEAP + +static void _delayed_work_timeout_handler(void *parameter); + rt_inline rt_err_t _workqueue_work_completion(struct rt_workqueue *queue) { rt_err_t result; - - rt_enter_critical(); + + rt_enter_critical(); while (1) { /* try to take condition semaphore */ @@ -40,17 +43,17 @@ rt_inline rt_err_t _workqueue_work_completion(struct rt_workqueue *queue) } } rt_exit_critical(); - + return result; } -static void _workqueue_thread_entry(void* parameter) +static void _workqueue_thread_entry(void *parameter) { rt_base_t level; - struct rt_work* work; - struct rt_workqueue* queue; + struct rt_work *work; + struct rt_workqueue *queue; - queue = (struct rt_workqueue*) parameter; + queue = (struct rt_workqueue *) parameter; RT_ASSERT(queue != RT_NULL); while (1) @@ -67,6 +70,8 @@ static void _workqueue_thread_entry(void* parameter) work = rt_list_entry(queue->work_list.next, struct rt_work, list); rt_list_remove(&(work->list)); queue->work_current = work; + work->flags &= ~RT_WORK_STATE_PENDING; + work->workqueue = RT_NULL; rt_hw_interrupt_enable(level); /* do work */ @@ -81,11 +86,172 @@ static void _workqueue_thread_entry(void* parameter) } } -struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_size, rt_uint8_t priority) +static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work) +{ + rt_base_t level; + + level = rt_hw_interrupt_disable(); + if (work->flags & RT_WORK_STATE_PENDING) + { + rt_hw_interrupt_enable(level); + return -RT_EBUSY; + } + + if (queue->work_current == work) + { + rt_hw_interrupt_enable(level); + return -RT_EBUSY; + } + + /* NOTE: the work MUST be initialized firstly */ + rt_list_remove(&(work->list)); + + rt_list_insert_after(queue->work_list.prev, &(work->list)); + work->flags |= RT_WORK_STATE_PENDING; + + /* whether the workqueue is doing work */ + if (queue->work_current == RT_NULL) + { + rt_hw_interrupt_enable(level); + /* resume work thread */ + rt_thread_resume(queue->work_thread); + rt_schedule(); + } + else + { + rt_hw_interrupt_enable(level); + } + + return RT_EOK; +} + +static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work) +{ + rt_base_t level; + + level = rt_hw_interrupt_disable(); + if (queue->work_current == work) + { + rt_hw_interrupt_enable(level); + return -RT_EBUSY; + } + rt_list_remove(&(work->list)); + work->flags &= ~RT_WORK_STATE_PENDING; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t _workqueue_cancel_delayed_work(struct rt_work *work) +{ + rt_base_t level; + int ret = RT_EOK; + + if (!work->workqueue) + { + ret = -EINVAL; + goto __exit; + } + + if (work->flags & RT_WORK_STATE_PENDING) + { + /* Remove from the queue if already submitted */ + ret = _workqueue_cancel_work(work->workqueue, work); + if (ret) + { + goto __exit; + } + } + else + { + if (work->flags & RT_WORK_STATE_SUBMITTING) + { + level = rt_hw_interrupt_disable(); + rt_timer_stop(&(work->timer)); + rt_timer_detach(&(work->timer)); + work->flags &= ~RT_WORK_STATE_SUBMITTING; + rt_hw_interrupt_enable(level); + } + } + + level = rt_hw_interrupt_disable(); + /* Detach from workqueue */ + work->workqueue = RT_NULL; + work->flags &= ~(RT_WORK_STATE_PENDING); + rt_hw_interrupt_enable(level); + +__exit: + return ret; +} + +static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue, + struct rt_work *work, rt_tick_t ticks) +{ + rt_base_t level; + rt_err_t ret = RT_EOK; + + /* Work cannot be active in multiple queues */ + if (work->workqueue && work->workqueue != queue) + { + ret = -RT_EINVAL; + goto __exit; + } + + /* Cancel if work has been submitted */ + if (work->workqueue == queue) + { + ret = _workqueue_cancel_delayed_work(work); + if (ret < 0) + { + goto __exit; + } + } + + level = rt_hw_interrupt_disable(); + /* Attach workqueue so the timeout callback can submit it */ + work->workqueue = queue; + rt_hw_interrupt_enable(level); + + if (!ticks) + { + /* Submit work if no ticks is 0 */ + ret = _workqueue_submit_work(work->workqueue, work); + } + else + { + level = rt_hw_interrupt_disable(); + /* Add timeout */ + work->flags |= RT_WORK_STATE_SUBMITTING; + rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler, work, ticks, + RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); + rt_hw_interrupt_enable(level); + rt_timer_start(&(work->timer)); + } + +__exit: + return ret; +} + +static void _delayed_work_timeout_handler(void *parameter) +{ + struct rt_work *delayed_work; + rt_base_t level; + + delayed_work = (struct rt_work *)parameter; + level = rt_hw_interrupt_disable(); + rt_timer_stop(&(delayed_work->timer)); + rt_timer_detach(&(delayed_work->timer)); + delayed_work->flags &= ~RT_WORK_STATE_SUBMITTING; + delayed_work->type &= ~RT_WORK_TYPE_DELAYED; + rt_hw_interrupt_enable(level); + _workqueue_submit_work(delayed_work->workqueue, delayed_work); +} + +struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority) { struct rt_workqueue *queue = RT_NULL; - queue = (struct rt_workqueue*)RT_KERNEL_MALLOC(sizeof(struct rt_workqueue)); + queue = (struct rt_workqueue *)RT_KERNEL_MALLOC(sizeof(struct rt_workqueue)); if (queue != RT_NULL) { /* initialize work list */ @@ -107,7 +273,7 @@ struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_siz return queue; } -rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue) +rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue) { RT_ASSERT(queue != RT_NULL); @@ -117,37 +283,35 @@ rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue) return RT_EOK; } -rt_err_t rt_workqueue_dowork(struct rt_workqueue* queue, struct rt_work* work) +rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work) { - rt_base_t level; RT_ASSERT(queue != RT_NULL); RT_ASSERT(work != RT_NULL); - level = rt_hw_interrupt_disable(); - if (queue->work_current == work) - { - rt_hw_interrupt_enable(level); - return -RT_EBUSY; - } + return _workqueue_submit_work(queue, work); +} - /* NOTE: the work MUST be initialized firstly */ - rt_list_remove(&(work->list)); +rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time) +{ + RT_ASSERT(queue != RT_NULL); + RT_ASSERT(work != RT_NULL); - rt_list_insert_after(queue->work_list.prev, &(work->list)); - /* whether the workqueue is doing work */ - if (queue->work_current == RT_NULL) + if (time > 0) { - rt_hw_interrupt_enable(level); - /* resume work thread */ - rt_thread_resume(queue->work_thread); - rt_schedule(); + work->type |= RT_WORK_TYPE_DELAYED; } - else rt_hw_interrupt_enable(level); - return RT_EOK; + if (work->type & RT_WORK_TYPE_DELAYED) + { + return _workqueue_submit_delayed_work(queue, work, time); + } + else + { + return _workqueue_submit_work(queue, work); + } } -rt_err_t rt_workqueue_critical_work(struct rt_workqueue* queue, struct rt_work* work) +rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *work) { rt_base_t level; RT_ASSERT(queue != RT_NULL); @@ -176,26 +340,22 @@ rt_err_t rt_workqueue_critical_work(struct rt_workqueue* queue, struct rt_work* return RT_EOK; } -rt_err_t rt_workqueue_cancel_work(struct rt_workqueue* queue, struct rt_work* work) +rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work) { - rt_base_t level; - RT_ASSERT(queue != RT_NULL); RT_ASSERT(work != RT_NULL); - level = rt_hw_interrupt_disable(); - if (queue->work_current == work) + if (work->type & RT_WORK_TYPE_DELAYED) { - rt_hw_interrupt_enable(level); - return -RT_EBUSY; + return _workqueue_cancel_delayed_work(work); + } + else + { + return _workqueue_cancel_work(queue, work); } - rt_list_remove(&(work->list)); - rt_hw_interrupt_enable(level); - - return RT_EOK; } -rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue* queue, struct rt_work* work) +rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work) { rt_base_t level; @@ -212,12 +372,13 @@ rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue* queue, struct rt_wor { rt_list_remove(&(work->list)); } + work->flags &= ~RT_WORK_STATE_PENDING; rt_hw_interrupt_enable(level); return RT_EOK; } -rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue* queue) +rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue) { struct rt_list_node *node, *next; RT_ASSERT(queue != RT_NULL); @@ -233,5 +394,36 @@ rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue* queue) return RT_EOK; } -#endif +void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work, + void *work_data), void *work_data) +{ + rt_work_init(&work->work, work_func, work_data); +} + +#ifdef RT_USING_SYSTEM_WORKQUEUE +static struct rt_workqueue *sys_workq; + +rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time) +{ + return rt_workqueue_submit_work(sys_workq, work, time); +} + +rt_err_t rt_work_cancel(struct rt_work *work) +{ + return rt_workqueue_cancel_work(sys_workq, work); +} + +int rt_work_sys_workqueue_init(void) +{ + if (sys_workq != RT_NULL) + return 0; + + sys_workq = rt_workqueue_create("sys_work", RT_SYSTEM_WORKQUEUE_STACKSIZE, + RT_SYSTEM_WORKQUEUE_PRIORITY); + return RT_EOK; +} + +INIT_DEVICE_EXPORT(rt_work_sys_workqueue_init); +#endif +#endif diff --git a/components/drivers/touch/SConscript b/components/drivers/touch/SConscript new file mode 100644 index 0000000000..f370b2aba6 --- /dev/null +++ b/components/drivers/touch/SConscript @@ -0,0 +1,11 @@ +# SConscript for touch framework + +from building import * + +cwd = GetCurrentDir() +src = ['touch.c'] +CPPPATH = [cwd, cwd + '/../include'] + +group = DefineGroup('Touch', src, depend = ['RT_USING_TOUCH', 'RT_USING_DEVICE'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/touch/touch.c b/components/drivers/touch/touch.c new file mode 100644 index 0000000000..80ba6378bb --- /dev/null +++ b/components/drivers/touch/touch.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-20 tyustli the first version + */ + +#include "touch.h" +#include <string.h> + +#define DBG_TAG "touch" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +/* ISR for touch interrupt */ +static void irq_callback(void *args) +{ + rt_touch_t touch; + + touch = (rt_touch_t)args; + + if (touch->parent.rx_indicate == RT_NULL) + { + return; + } + + if (touch->irq_handle != RT_NULL) + { + touch->irq_handle(touch); + } + + touch->parent.rx_indicate(&touch->parent, 1); +} + +/* touch interrupt initialization function */ +static rt_err_t rt_touch_irq_init(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin == RT_PIN_NONE) + { + return -RT_EINVAL; + } + + rt_pin_mode(touch->config.irq_pin.pin, touch->config.irq_pin.mode); + + if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLDOWN) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING, irq_callback, (void *)touch); + } + else if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLUP) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_FALLING, irq_callback, (void *)touch); + } + else if (touch->config.irq_pin.mode == PIN_MODE_INPUT) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING_FALLING, irq_callback, (void *)touch); + } + + rt_pin_irq_enable(touch->config.irq_pin.pin, PIN_IRQ_ENABLE); + + return RT_EOK; +} + +/* touch interrupt enable */ +static void rt_touch_irq_enable(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(touch->config.irq_pin.pin, RT_TRUE); + } +} + +/* touch interrupt disable */ +static void rt_touch_irq_disable(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(touch->config.irq_pin.pin, RT_FALSE); + } +} + +static rt_err_t rt_touch_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_touch_t touch; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* Initialization touch interrupt */ + rt_touch_irq_init(touch); + } + + return RT_EOK; +} + +static rt_err_t rt_touch_close(rt_device_t dev) +{ + rt_touch_t touch; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + /* touch disable interrupt */ + rt_touch_irq_disable(touch); + + return RT_EOK; +} + +static rt_size_t rt_touch_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t len) +{ + rt_touch_t touch; + rt_size_t result = 0; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + if (buf == NULL || len == 0) + { + return 0; + } + + result = touch->ops->touch_readpoint(touch, buf, len); + + return result; +} + +static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args) +{ + rt_touch_t touch; + rt_err_t result = RT_EOK; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + switch (cmd) + { + case RT_TOUCH_CTRL_GET_ID: + if (args) + { + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_ID, args); + } + else + { + result = -RT_ERROR; + } + + break; + case RT_TOUCH_CTRL_GET_INFO: + if (args) + { + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_INFO, args); + } + else + { + result = -RT_ERROR; + } + + break; + case RT_TOUCH_CTRL_SET_MODE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_MODE, args); + + if (result == RT_EOK) + { + rt_uint16_t mode; + mode = *(rt_uint16_t*)args; + if (mode == RT_DEVICE_FLAG_INT_RX) + { + rt_touch_irq_enable(touch); /* enable interrupt */ + } + } + + break; + case RT_TOUCH_CTRL_SET_X_RANGE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_X_RANGE, args); + + if (result == RT_EOK) + { + touch->info.range_x = *(rt_int32_t *)args; + LOG_D("set x coordinate range :%d\n", touch->info.range_x); + } + + break; + case RT_TOUCH_CTRL_SET_Y_RANGE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_Y_RANGE, args); + + if (result == RT_EOK) + { + touch->info.range_y = *(rt_uint32_t *)args; + LOG_D("set y coordinate range :%d \n", touch->info.range_x); + } + + break; + case RT_TOUCH_CTRL_DISABLE_INT: + rt_touch_irq_disable(touch); + break; + case RT_TOUCH_CTRL_ENABLE_INT: + rt_touch_irq_enable(touch); + break; + default: + return -RT_ERROR; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rt_touch_ops = +{ + RT_NULL, + rt_touch_open, + rt_touch_close, + rt_touch_read, + RT_NULL, + rt_touch_control +}; +#endif + +/* + * touch register + */ +int rt_hw_touch_register(rt_touch_t touch, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_int8_t result; + rt_device_t device; + RT_ASSERT(touch != RT_NULL); + + device = &touch->parent; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &rt_touch_ops; +#else + device->init = RT_NULL; + device->open = rt_touch_open; + device->close = rt_touch_close; + device->read = rt_touch_read; + device->write = RT_NULL; + device->control = rt_touch_control; +#endif + device->type = RT_Device_Class_Touch; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->user_data = data; + + result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_STANDALONE); + + if (result != RT_EOK) + { + LOG_E("rt_touch register err code: %d", result); + return result; + } + + LOG_I("rt_touch init success"); + + return RT_EOK; +} diff --git a/components/drivers/touch/touch.h b/components/drivers/touch/touch.h new file mode 100644 index 0000000000..c33fe17520 --- /dev/null +++ b/components/drivers/touch/touch.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-20 tyustli the first version + */ + +#ifndef __TOUCH_H__ +#define __TOUCH_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef RT_USING_RTC +#define rt_touch_get_ts() time(RT_NULL) /* API for the touch to get the timestamp */ +#else +#define rt_touch_get_ts() rt_tick_get() /* API for the touch to get the timestamp */ +#endif + +#define RT_PIN_NONE 0xFFFF /* RT PIN NONE */ + +/* Touch vendor types */ +#define RT_TOUCH_VENDOR_UNKNOWN (0) /* unknown */ +#define RT_TOUCH_VENDOR_GT (1) /* GTxx series */ +#define RT_TOUCH_VENDOR_FT (2) /* FTxx series */ + +/* Touch ic type*/ +#define RT_TOUCH_TYPE_NONE (0) /* touch ic none */ +#define RT_TOUCH_TYPE_CAPACITANCE (1) /* capacitance ic */ +#define RT_TOUCH_TYPE_RESISTANCE (2) /* resistance ic */ + +/* Touch control cmd types */ +#define RT_TOUCH_CTRL_GET_ID (0) /* Get device id */ +#define RT_TOUCH_CTRL_GET_INFO (1) /* Get touch info */ +#define RT_TOUCH_CTRL_SET_MODE (2) /* Set touch's work mode. ex. RT_TOUCH_MODE_POLLING,RT_TOUCH_MODE_INT */ +#define RT_TOUCH_CTRL_SET_X_RANGE (3) /* Set x coordinate range */ +#define RT_TOUCH_CTRL_SET_Y_RANGE (4) /* Set y coordinate range */ +#define RT_TOUCH_CTRL_SET_X_TO_Y (5) /* Set X Y coordinate exchange */ +#define RT_TOUCH_CTRL_DISABLE_INT (6) /* Disable interrupt */ +#define RT_TOUCH_CTRL_ENABLE_INT (7) /* Enable interrupt */ +#define RT_TOUCH_CTRL_POWER_ON (8) /* Touch Power On */ +#define RT_TOUCH_CTRL_POWER_OFF (9) /* Touch Power Off */ +#define RT_TOUCH_CTRL_GET_STATUS (10) /* Get Touch Power Status */ + +/* Touch event */ +#define RT_TOUCH_EVENT_NONE (0) /* Touch none */ +#define RT_TOUCH_EVENT_UP (1) /* Touch up event */ +#define RT_TOUCH_EVENT_DOWN (2) /* Touch down event */ +#define RT_TOUCH_EVENT_MOVE (3) /* Touch move event */ + +struct rt_touch_info +{ + rt_uint8_t type; /* The touch type */ + rt_uint8_t vendor; /* Vendor of touchs */ + rt_uint8_t point_num; /* Support point num */ + rt_int32_t range_x; /* X coordinate range */ + rt_int32_t range_y; /* Y coordinate range */ +}; + +struct rt_touch_config +{ + struct rt_device_pin_mode irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */ + char *dev_name; /* The name of the communication device */ + void *user_data; +}; + +typedef struct rt_touch_device *rt_touch_t; +struct rt_touch_device +{ + struct rt_device parent; /* The standard device */ + struct rt_touch_info info; /* The touch info data */ + struct rt_touch_config config; /* The touch config data */ + + const struct rt_touch_ops *ops; /* The touch ops */ + rt_err_t (*irq_handle)(rt_touch_t touch); /* Called when an interrupt is generated, registered by the driver */ +}; + +struct rt_touch_data +{ + rt_uint8_t event; /* The touch event of the data */ + rt_uint8_t track_id; /* Track id of point */ + rt_uint8_t width; /* Point of width */ + rt_uint16_t x_coordinate; /* Point of x coordinate */ + rt_uint16_t y_coordinate; /* Point of y coordinate */ + rt_tick_t timestamp; /* The timestamp when the data was received */ +}; + +struct rt_touch_ops +{ + rt_size_t (*touch_readpoint)(struct rt_touch_device *touch, void *buf, rt_size_t touch_num); + rt_err_t (*touch_control)(struct rt_touch_device *touch, int cmd, void *arg); +}; + +int rt_hw_touch_register(rt_touch_t touch, + const char *name, + rt_uint32_t flag, + void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* __TOUCH_H__ */ diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript index be0b0c7b50..b6dfa8da10 100644 --- a/components/drivers/usb/usbdevice/SConscript +++ b/components/drivers/usb/usbdevice/SConscript @@ -3,7 +3,7 @@ from building import * cwd = GetCurrentDir() src = Split(""" -core/core.c +core/usbdevice_core.c core/usbdevice.c """) @@ -24,6 +24,12 @@ if GetDepend('RT_USB_DEVICE_RNDIS'): if GetDepend('RT_USB_DEVICE_WINUSB'): src += Glob('class/winusb.c') + +if GetDepend('RT_USB_DEVICE_AUDIO_MIC'): + src += Glob('class/audio_mic.c') + +if GetDepend('RT_USB_DEVICE_AUDIO_SPEAKER'): + src += Glob('class/audio_speaker.c') CPPPATH = [cwd] diff --git a/components/drivers/usb/usbdevice/class/audio.h b/components/drivers/usb/usbdevice/class/audio.h new file mode 100644 index 0000000000..4bb8994b47 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio.h @@ -0,0 +1,676 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * <linux/usb/audio.h> -- USB Audio definitions. + * + * Copyright (C) 2006 Thumtronics Pty Ltd. + * Developed for Thumtronics by Grey Innovation + * Ben Williamson <[email protected]> + * + * This software is distributed under the terms of the GNU General Public + * License ("GPL") version 2, as published by the Free Software Foundation. + * + * This file holds USB constants and structures defined + * by the USB Device Class Definition for Audio Devices. + * Comments below reference relevant sections of that document: + * + * http://www.usb.org/developers/devclass_docs/audio10.pdf + * + * Types and defines in this file are either specific to version 1.0 of + * this standard or common for newer versions. + */ + +#ifndef _UAPI__LINUX_USB_AUDIO_H +#define _UAPI__LINUX_USB_AUDIO_H + +//#include <linux/types.h> +#include <rtthread.h> + +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; + +#define UAC_USE_FEATURE_UNIT 0 /* Feature unit does not support */ + +/* + * Below are truly Linux-specific types that should never collide with + * any application/library that wants linux/types.h. + */ + +#ifdef __CHECKER__ +#define __bitwise__ __attribute__((bitwise)) +#else +#define __bitwise__ +#endif +#ifdef __CHECK_ENDIAN__ +#define __bitwise __bitwise__ +#else +#define __bitwise +#endif + +typedef __u16 __bitwise __le16; +typedef __u16 __bitwise __be16; +typedef __u32 __bitwise __le32; +typedef __u32 __bitwise __be32; +typedef __u64 __bitwise __le64; +typedef __u64 __bitwise __be64; + +typedef __u16 __bitwise __sum16; +typedef __u32 __bitwise __wsum; + +/* bInterfaceProtocol values to denote the version of the standard used */ +#define UAC_VERSION_1 0x00 +#define UAC_VERSION_2 0x20 +#define UAC_VERSION_3 0x30 + +/* A.2 Audio Interface Subclass Codes */ +#define USB_SUBCLASS_AUDIOCONTROL 0x01 +#define USB_SUBCLASS_AUDIOSTREAMING 0x02 +#define USB_SUBCLASS_MIDISTREAMING 0x03 + +/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ +#define UAC_HEADER 0x01 +#define UAC_INPUT_TERMINAL 0x02 +#define UAC_OUTPUT_TERMINAL 0x03 +#define UAC_MIXER_UNIT 0x04 +#define UAC_SELECTOR_UNIT 0x05 +#define UAC_FEATURE_UNIT 0x06 +#define UAC1_PROCESSING_UNIT 0x07 +#define UAC1_EXTENSION_UNIT 0x08 + +/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ +#define UAC_AS_GENERAL 0x01 +#define UAC_FORMAT_TYPE 0x02 +#define UAC_FORMAT_SPECIFIC 0x03 + +/* A.7 Processing Unit Process Types */ +#define UAC_PROCESS_UNDEFINED 0x00 +#define UAC_PROCESS_UP_DOWNMIX 0x01 +#define UAC_PROCESS_DOLBY_PROLOGIC 0x02 +#define UAC_PROCESS_STEREO_EXTENDER 0x03 +#define UAC_PROCESS_REVERB 0x04 +#define UAC_PROCESS_CHORUS 0x05 +#define UAC_PROCESS_DYN_RANGE_COMP 0x06 + +/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_EP_GENERAL 0x01 + +/* A.9 Audio Class-Specific Request Codes */ +#define UAC_SET_ 0x00 +#define UAC_GET_ 0x80 + +#define UAC__CUR 0x1 +#define UAC__MIN 0x2 +#define UAC__MAX 0x3 +#define UAC__RES 0x4 +#define UAC__MEM 0x5 + +#define UAC_SET_CUR (UAC_SET_ | UAC__CUR) +#define UAC_GET_CUR (UAC_GET_ | UAC__CUR) +#define UAC_SET_MIN (UAC_SET_ | UAC__MIN) +#define UAC_GET_MIN (UAC_GET_ | UAC__MIN) +#define UAC_SET_MAX (UAC_SET_ | UAC__MAX) +#define UAC_GET_MAX (UAC_GET_ | UAC__MAX) +#define UAC_SET_RES (UAC_SET_ | UAC__RES) +#define UAC_GET_RES (UAC_GET_ | UAC__RES) +#define UAC_SET_MEM (UAC_SET_ | UAC__MEM) +#define UAC_GET_MEM (UAC_GET_ | UAC__MEM) + +#define UAC_GET_STAT 0xff + +/* A.10 Control Selector Codes */ + +/* A.10.1 Terminal Control Selectors */ +#define UAC_TERM_COPY_PROTECT 0x01 + +/* A.10.2 Feature Unit Control Selectors */ +#define UAC_FU_MUTE 0x01 +#define UAC_FU_VOLUME 0x02 +#define UAC_FU_BASS 0x03 +#define UAC_FU_MID 0x04 +#define UAC_FU_TREBLE 0x05 +#define UAC_FU_GRAPHIC_EQUALIZER 0x06 +#define UAC_FU_AUTOMATIC_GAIN 0x07 +#define UAC_FU_DELAY 0x08 +#define UAC_FU_BASS_BOOST 0x09 +#define UAC_FU_LOUDNESS 0x0a + +#define UAC_CONTROL_BIT(CS) (1 << ((CS) - 1)) + +/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */ +#define UAC_UD_ENABLE 0x01 +#define UAC_UD_MODE_SELECT 0x02 + +/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */ +#define UAC_DP_ENABLE 0x01 +#define UAC_DP_MODE_SELECT 0x02 + +/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */ +#define UAC_3D_ENABLE 0x01 +#define UAC_3D_SPACE 0x02 + +/* A.10.3.4 Reverberation Processing Unit Control Selectors */ +#define UAC_REVERB_ENABLE 0x01 +#define UAC_REVERB_LEVEL 0x02 +#define UAC_REVERB_TIME 0x03 +#define UAC_REVERB_FEEDBACK 0x04 + +/* A.10.3.5 Chorus Processing Unit Control Selectors */ +#define UAC_CHORUS_ENABLE 0x01 +#define UAC_CHORUS_LEVEL 0x02 +#define UAC_CHORUS_RATE 0x03 +#define UAC_CHORUS_DEPTH 0x04 + +/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */ +#define UAC_DCR_ENABLE 0x01 +#define UAC_DCR_RATE 0x02 +#define UAC_DCR_MAXAMPL 0x03 +#define UAC_DCR_THRESHOLD 0x04 +#define UAC_DCR_ATTACK_TIME 0x05 +#define UAC_DCR_RELEASE_TIME 0x06 + +/* A.10.4 Extension Unit Control Selectors */ +#define UAC_XU_ENABLE 0x01 + +/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ +#define UAC_MS_HEADER 0x01 +#define UAC_MIDI_IN_JACK 0x02 +#define UAC_MIDI_OUT_JACK 0x03 + +/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_MS_GENERAL 0x01 + +/* Terminals - 2.1 USB Terminal Types */ +#define UAC_TERMINAL_UNDEFINED 0x100 +#define UAC_TERMINAL_STREAMING 0x101 +#define UAC_TERMINAL_VENDOR_SPEC 0x1FF + +/* Terminal Control Selectors */ +/* 4.3.2 Class-Specific AC Interface Descriptor */ +struct uac1_ac_header_descriptor { + __u8 bLength; /* 8 + n */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* UAC_MS_HEADER */ + __le16 bcdADC; /* 0x0100 */ + __le16 wTotalLength; /* includes Unit and Terminal desc. */ + __u8 bInCollection; /* n */ + __u8 baInterfaceNr[]; /* [n] */ +} __attribute__ ((packed)); + +#define UAC_DT_AC_HEADER_SIZE(n) (8 + (n)) + +/* As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n) \ +struct uac1_ac_header_descriptor_##n { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __le16 bcdADC; \ + __le16 wTotalLength; \ + __u8 bInCollection; \ + __u8 baInterfaceNr[n]; \ +} __attribute__ ((packed)) + +/* 4.3.2.1 Input Terminal Descriptor */ +struct uac_input_terminal_descriptor { + __u8 bLength; /* in bytes: 12 */ + __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ + __u8 bDescriptorSubtype; /* INPUT_TERMINAL descriptor subtype */ + __u8 bTerminalID; /* Constant uniquely terminal ID */ + __le16 wTerminalType; /* USB Audio Terminal Types */ + __u8 bAssocTerminal; /* ID of the Output Terminal associated */ + __u8 bNrChannels; /* Number of logical output channels */ + __le16 wChannelConfig; + __u8 iChannelNames; + __u8 iTerminal; +} __attribute__ ((packed)); + +#define UAC_DT_INPUT_TERMINAL_SIZE 12 + +/* Terminals - 2.2 Input Terminal Types */ +#define UAC_INPUT_TERMINAL_UNDEFINED 0x200 +#define UAC_INPUT_TERMINAL_MICROPHONE 0x201 +#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202 +#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203 +#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204 +#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205 +#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206 + +/* Terminals - control selectors */ + +#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL 0x01 + +/* 4.3.2.2 Output Terminal Descriptor */ +struct uac1_output_terminal_descriptor { + __u8 bLength; /* in bytes: 9 */ + __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ + __u8 bDescriptorSubtype; /* OUTPUT_TERMINAL descriptor subtype */ + __u8 bTerminalID; /* Constant uniquely terminal ID */ + __le16 wTerminalType; /* USB Audio Terminal Types */ + __u8 bAssocTerminal; /* ID of the Input Terminal associated */ + __u8 bSourceID; /* ID of the connected Unit or Terminal*/ + __u8 iTerminal; +} __attribute__ ((packed)); + +#define UAC_DT_OUTPUT_TERMINAL_SIZE 9 + +/* Terminals - 2.3 Output Terminal Types */ +#define UAC_OUTPUT_TERMINAL_UNDEFINED 0x300 +#define UAC_OUTPUT_TERMINAL_SPEAKER 0x301 +#define UAC_OUTPUT_TERMINAL_HEADPHONES 0x302 +#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303 +#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304 +#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305 +#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306 +#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307 + +/* Terminals - 2.4 Bi-directional Terminal Types */ +#define UAC_BIDIR_TERMINAL_UNDEFINED 0x400 +#define UAC_BIDIR_TERMINAL_HANDSET 0x401 +#define UAC_BIDIR_TERMINAL_HEADSET 0x402 +#define UAC_BIDIR_TERMINAL_SPEAKER_PHONE 0x403 +#define UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING 0x404 +#define UAC_BIDIR_TERMINAL_ECHO_CANCELING 0x405 + +/* Set bControlSize = 2 as default setting */ +#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2) + +/* As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) \ +struct uac_feature_unit_descriptor_##ch { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __u8 bUnitID; \ + __u8 bSourceID; \ + __u8 bControlSize; \ + __le16 bmaControls[ch + 1]; \ + __u8 iFeature; \ +} __attribute__ ((packed)) + +/* 4.3.2.3 Mixer Unit Descriptor */ +struct uac_mixer_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc) +{ + return desc->baSourceID[desc->bNrInPins]; +} + +static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + if (protocol == UAC_VERSION_1) + return (desc->baSourceID[desc->bNrInPins + 2] << 8) | + desc->baSourceID[desc->bNrInPins + 1]; + else + return (desc->baSourceID[desc->bNrInPins + 4] << 24) | + (desc->baSourceID[desc->bNrInPins + 3] << 16) | + (desc->baSourceID[desc->bNrInPins + 2] << 8) | + (desc->baSourceID[desc->bNrInPins + 1]); +} + +static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + desc->baSourceID[desc->bNrInPins + 3] : + desc->baSourceID[desc->bNrInPins + 5]; +} + +static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return &desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return &desc->baSourceID[desc->bNrInPins + 6]; + case UAC_VERSION_3: + return &desc->baSourceID[desc->bNrInPins + 2]; + default: + return NULL; + } +} + +static inline __u16 uac3_mixer_unit_wClusterDescrID(struct uac_mixer_unit_descriptor *desc) +{ + return (desc->baSourceID[desc->bNrInPins + 1] << 8) | + desc->baSourceID[desc->bNrInPins]; +} + +static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} + +/* 4.3.2.4 Selector Unit Descriptor */ +struct uac_selector_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUintID; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} +#if UAC_USE_FEATURE_UNIT +/* 4.3.2.5 Feature Unit Descriptor */ +struct uac_feature_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u8 bSourceID; + __u8 bControlSize; + __u8 bmaControls[0]; /* variable length */ +} __attribute__((packed)); + +static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} +#endif +/* 4.3.2.6 Processing Unit Descriptors */ +struct uac_processing_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __le16 wProcessType; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc) +{ + return desc->baSourceID[desc->bNrInPins]; +} + +static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + if (protocol == UAC_VERSION_1) + return (desc->baSourceID[desc->bNrInPins + 2] << 8) | + desc->baSourceID[desc->bNrInPins + 1]; + else + return (desc->baSourceID[desc->bNrInPins + 4] << 24) | + (desc->baSourceID[desc->bNrInPins + 3] << 16) | + (desc->baSourceID[desc->bNrInPins + 2] << 8) | + (desc->baSourceID[desc->bNrInPins + 1]); +} + +static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + desc->baSourceID[desc->bNrInPins + 3] : + desc->baSourceID[desc->bNrInPins + 5]; +} + +static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return 2; /* in UAC2, this value is constant */ + case UAC_VERSION_3: + return 4; /* in UAC3, this value is constant */ + default: + return 1; + } +} + +static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return &desc->baSourceID[desc->bNrInPins + 5]; + case UAC_VERSION_2: + return &desc->baSourceID[desc->bNrInPins + 6]; + case UAC_VERSION_3: + return &desc->baSourceID[desc->bNrInPins + 2]; + default: + return NULL; + } +} + +static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); + case UAC_VERSION_3: + return 0; /* UAC3 does not have this field */ + } +} + +static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return uac_processing_unit_bmControls(desc, protocol) + + control_size + 1; + case UAC_VERSION_3: + return uac_processing_unit_bmControls(desc, protocol) + + control_size; + } +} + +/* + * Extension Unit (XU) has almost compatible layout with Processing Unit, but + * on UAC2, it has a different bmControls size (bControlSize); it's 1 byte for + * XU while 2 bytes for PU. The last iExtension field is a one-byte index as + * well as iProcessing field of PU. + */ +static inline __u8 uac_extension_unit_bControlSize(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return 1; /* in UAC2, this value is constant */ + case UAC_VERSION_3: + return 4; /* in UAC3, this value is constant */ + default: + return 1; + } +} + +static inline __u8 uac_extension_unit_iExtension(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_extension_unit_bControlSize(desc, protocol); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); + case UAC_VERSION_3: + return 0; /* UAC3 does not have this field */ + } +} + +/* 4.5.2 Class-Specific AS Interface Descriptor */ +struct uac1_as_header_descriptor { + __u8 bLength; /* in bytes: 7 */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* AS_GENERAL */ + __u8 bTerminalLink; /* Terminal ID of connected Terminal */ + __u8 bDelay; /* Delay introduced by the data path */ + __le16 wFormatTag; /* The Audio Data Format */ +} __attribute__ ((packed)); + +#define UAC_DT_AS_HEADER_SIZE 7 + +/* Formats - A.1.1 Audio Data Format Type I Codes */ +#define UAC_FORMAT_TYPE_I_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I_PCM 0x1 +#define UAC_FORMAT_TYPE_I_PCM8 0x2 +#define UAC_FORMAT_TYPE_I_IEEE_FLOAT 0x3 +#define UAC_FORMAT_TYPE_I_ALAW 0x4 +#define UAC_FORMAT_TYPE_I_MULAW 0x5 + +struct uac_format_type_i_continuous_descriptor { + __u8 bLength; /* in bytes: 8 + (ns * 3) */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* FORMAT_TYPE */ + __u8 bFormatType; /* FORMAT_TYPE_1 */ + __u8 bNrChannels; /* physical channels in the stream */ + __u8 bSubframeSize; /* */ + __u8 bBitResolution; + __u8 bSamFreqType; + __u8 tLowerSamFreq[3]; + __u8 tUpperSamFreq[3]; +} __attribute__ ((packed)); + +#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14 + +struct uac_format_type_i_discrete_descriptor { + __u8 bLength; /* in bytes: 8 + (ns * 3) */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* FORMAT_TYPE */ + __u8 bFormatType; /* FORMAT_TYPE_1 */ + __u8 bNrChannels; /* physical channels in the stream */ + __u8 bSubframeSize; /* */ + __u8 bBitResolution; + __u8 bSamFreqType; + __u8 tSamFreq[][3]; +} __attribute__ ((packed)); + +#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n) \ +struct uac_format_type_i_discrete_descriptor_##n { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __u8 bFormatType; \ + __u8 bNrChannels; \ + __u8 bSubframeSize; \ + __u8 bBitResolution; \ + __u8 bSamFreqType; \ + __u8 tSamFreq[n][3]; \ +} __attribute__ ((packed)) + +#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n) (8 + (n * 3)) + +struct uac_format_type_i_ext_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __u8 bSubslotSize; + __u8 bBitResolution; + __u8 bHeaderLength; + __u8 bControlSize; + __u8 bSideBandProtocol; +} __attribute__((packed)); + +/* Formats - Audio Data Format Type I Codes */ + +#define UAC_FORMAT_TYPE_II_MPEG 0x1001 +#define UAC_FORMAT_TYPE_II_AC3 0x1002 + +struct uac_format_type_ii_discrete_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __le16 wMaxBitRate; + __le16 wSamplesPerFrame; + __u8 bSamFreqType; + __u8 tSamFreq[][3]; +} __attribute__((packed)); + +struct uac_format_type_ii_ext_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __le16 wMaxBitRate; + __le16 wSamplesPerFrame; + __u8 bHeaderLength; + __u8 bSideBandProtocol; +} __attribute__((packed)); + +/* type III */ +#define UAC_FORMAT_TYPE_III_IEC1937_AC3 0x2001 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1 0x2002 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT 0x2003 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT 0x2004 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS 0x2005 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS 0x2006 + +/* Formats - A.2 Format Type Codes */ +#define UAC_FORMAT_TYPE_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I 0x1 +#define UAC_FORMAT_TYPE_II 0x2 +#define UAC_FORMAT_TYPE_III 0x3 +#define UAC_EXT_FORMAT_TYPE_I 0x81 +#define UAC_EXT_FORMAT_TYPE_II 0x82 +#define UAC_EXT_FORMAT_TYPE_III 0x83 + +struct uac_iso_endpoint_descriptor { + __u8 bLength; /* in bytes: 7 */ + __u8 bDescriptorType; /* USB_DT_CS_ENDPOINT */ + __u8 bDescriptorSubtype; /* EP_GENERAL */ + __u8 bmAttributes; + __u8 bLockDelayUnits; + __le16 wLockDelay; +} __attribute__((packed)); +#define UAC_ISO_ENDPOINT_DESC_SIZE 7 + +#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01 +#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02 +#define UAC_EP_CS_ATTR_FILL_MAX 0x80 + +/* status word format (3.7.1.1) */ + +#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f +#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF 0x1 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP 0x2 + +#define UAC1_STATUS_TYPE_IRQ_PENDING (1 << 7) +#define UAC1_STATUS_TYPE_MEM_CHANGED (1 << 6) + +struct uac1_status_word { + __u8 bStatusType; + __u8 bOriginator; +} __attribute__((packed)); + + +#endif /* _UAPI__LINUX_USB_AUDIO_H */ diff --git a/components/drivers/usb/usbdevice/class/audio_mic.c b/components/drivers/usb/usbdevice/class/audio_mic.c new file mode 100644 index 0000000000..4ac85711ad --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio_mic.c @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-09-07 flybreak the first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> + +#include "drivers/usb_device.h" +#include "audio.h" + +#define DBG_TAG "usbd.audio.mic" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#define RECORD_SAMPLERATE 16000 +#define RECORD_CHANNEL 1 +#define RESOLUTION_BITS 16 + +#define RESOLUTION_BYTE (RESOLUTION_BITS / 8) +#define RECORD_PER_MS_SZ ((RECORD_SAMPLERATE * RECORD_CHANNEL * RESOLUTION_BYTE) / 1000) +#define RECORD_BUFFER_SZ (RECORD_PER_MS_SZ * 20) /* 20ms */ + +#if defined(RT_USBD_MIC_DEVICE_NAME) + #define MIC_DEVICE_NAME RT_USBD_MIC_DEVICE_NAME +#else + #define MIC_DEVICE_NAME "mic0" +#endif + +#define EVENT_RECORD_START (1 << 0) +#define EVENT_RECORD_STOP (1 << 1) +#define EVENT_RECORD_DATA (1 << 2) + +/* + * uac mic descriptor define + */ + +#define UAC_CS_INTERFACE 0x24 +#define UAC_CS_ENDPOINT 0x25 + +#define UAC_MAX_PACKET_SIZE 64 +#define UAC_EP_MAX_PACKET_SIZE 32 +#define UAC_CHANNEL_NUM RECORD_CHANNEL +#define UAC_INTR_NUM 1 +#define UAC_CH_NUM 1 +#define UAC_FORMAT_NUM 1 + +struct uac_ac_descriptor +{ +#ifdef RT_USB_DEVICE_COMPOSITE + struct uiad_descriptor iad_desc; +#endif + struct uinterface_descriptor intf_desc; + DECLARE_UAC_AC_HEADER_DESCRIPTOR(UAC_INTR_NUM) hdr_desc; + struct uac_input_terminal_descriptor it_desc; + struct uac1_output_terminal_descriptor ot_desc; +#if UAC_USE_FEATURE_UNIT + DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) feature_unit_desc; +#endif +}; + +struct uac_as_descriptor +{ + struct uinterface_descriptor intf_desc; + struct uac1_as_header_descriptor hdr_desc; + DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(UAC_FORMAT_NUM) format_type_desc; + struct uendpoint_descriptor ep_desc; + struct uac_iso_endpoint_descriptor as_ep_desc; +}; + +/* + * uac mic device type + */ + +struct uac_audio_mic +{ + rt_device_t dev; + rt_event_t event; + rt_uint8_t open_count; + + rt_uint8_t *buffer; + rt_uint32_t buffer_index; + + uep_t ep; +}; +static struct uac_audio_mic mic; + +ALIGN(4) +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_DEVICE, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + UAC_MAX_PACKET_SIZE, //bMaxPacketSize0; + _VENDOR_ID, //idVendor; + _PRODUCT_ID, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber;Unused. + USB_DYNAMIC, //bNumConfigurations; +}; + +//FS and HS needed +ALIGN(4) +static struct usb_qualifier_descriptor dev_qualifier = +{ + sizeof(dev_qualifier), //bLength + USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType + 0x0200, //bcdUSB + USB_CLASS_AUDIO, //bDeviceClass + 0x00, //bDeviceSubClass + 0x00, //bDeviceProtocol + 64, //bMaxPacketSize0 + 0x01, //bNumConfigurations + 0, +}; + +ALIGN(4) +const static char *_ustring[] = +{ + "Language", + "RT-Thread Team.", + "Microphone", + "32021919830108", + "Configuration", + "Interface", +}; + +ALIGN(4) +static struct uac_ac_descriptor ac_desc = +{ +#ifdef RT_USB_DEVICE_COMPOSITE + /* Interface Association Descriptor */ + { + USB_DESC_LENGTH_IAD, + USB_DESC_TYPE_IAD, + USB_DYNAMIC, + 0x02, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, +#endif + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOCONTROL, + 0x00, + 0x00, + }, + /* Header Descriptor */ + { + UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + UAC_CS_INTERFACE, + UAC_HEADER, + 0x0100, /* Version: 1.00 */ + 0x001E, /* Total length: 30 */ + 0x01, /* Total number of interfaces: 1 */ + {0x01}, /* Interface number: 1 */ + }, + /* Input Terminal Descriptor */ + { + UAC_DT_INPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_INPUT_TERMINAL, + 0x01, /* Terminal ID: 1 */ + 0x0201, /* Terminal Type: Microphone (0x0201) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Number Channels: 1 */ + 0x0000, /* Channel Config: 0x0000 */ + 0x00, /* Channel Names: 0 */ + 0x00, /* Terminal: 0 */ + }, + /* Output Terminal Descriptor */ + { + UAC_DT_OUTPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_OUTPUT_TERMINAL, + 0x02, /* Terminal ID: 2 */ + 0x0101, /* Terminal Type: USB Streaming (0x0101) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Source ID: 1 */ + 0x00, /* Terminal: 0 */ + }, +#if UAC_USE_FEATURE_UNIT + /* Feature unit Descriptor */ + { + UAC_DT_FEATURE_UNIT_SIZE(UAC_CH_NUM), + UAC_CS_INTERFACE, + UAC_FEATURE_UNIT, + 0x02, + 0x0101, + 0x00, + 0x01, + }, +#endif +}; + +ALIGN(4) +static struct uinterface_descriptor as_desc0 = +{ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, +}; + +ALIGN(4) +static struct uac_as_descriptor as_desc = +{ + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x01, + 0x01, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, + /* General AS Descriptor */ + { + UAC_DT_AS_HEADER_SIZE, + UAC_CS_INTERFACE, + UAC_AS_GENERAL, + 0x02, /* Terminal ID: 2 */ + 0x01, /* Interface delay in frames: 1 */ + UAC_FORMAT_TYPE_I_PCM, + }, + /* Format type i Descriptor */ + { + UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + UAC_CS_INTERFACE, + UAC_FORMAT_TYPE, + UAC_FORMAT_TYPE_I, + UAC_CHANNEL_NUM, + 2, /* Subframe Size: 2 */ + RESOLUTION_BITS, + 0x01, /* Samples Frequence Type: 1 */ + {0}, /* Samples Frequence */ + }, + /* Endpoint Descriptor */ + { + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_IN, + USB_EP_ATTR_ISOC, + UAC_EP_MAX_PACKET_SIZE, + 0x01, + }, + /* AS Endpoint Descriptor */ + { + UAC_ISO_ENDPOINT_DESC_SIZE, + UAC_CS_ENDPOINT, + UAC_MS_GENERAL, + }, +}; + +void mic_entry(void *parameter) +{ + struct rt_audio_caps caps = {0}; + rt_uint32_t e, index; + + mic.buffer = rt_malloc(RECORD_BUFFER_SZ); + if (mic.buffer == RT_NULL) + { + LOG_E("malloc failed"); + goto __exit; + } + + mic.dev = rt_device_find(MIC_DEVICE_NAME); + if (mic.dev == RT_NULL) + { + LOG_E("can't find device:%s", MIC_DEVICE_NAME); + goto __exit; + } + + while (1) + { + if (rt_event_recv(mic.event, EVENT_RECORD_START | EVENT_RECORD_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + continue; + } + if (mic.open_count == 0) + { + continue; + } + LOG_D("record start"); + + rt_device_open(mic.dev, RT_DEVICE_OFLAG_RDONLY); + + caps.main_type = AUDIO_TYPE_INPUT; + caps.sub_type = AUDIO_DSP_PARAM; + caps.udata.config.samplerate = RECORD_SAMPLERATE; + caps.udata.config.channels = RECORD_CHANNEL; + caps.udata.config.samplebits = RESOLUTION_BITS; + rt_device_control(mic.dev, AUDIO_CTL_CONFIGURE, &caps); + + while (1) + { + if (rt_event_recv(mic.event, EVENT_RECORD_DATA | EVENT_RECORD_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + if (mic.open_count > 0) + continue; + else + break; + } + if (e & EVENT_RECORD_DATA) + { + index = (mic.buffer_index >= RECORD_BUFFER_SZ / 2) ? 0 : (RECORD_BUFFER_SZ / 2); + rt_device_read(mic.dev, 0, mic.buffer + index, RECORD_BUFFER_SZ / 2); + } + else if (e & EVENT_RECORD_STOP) + { + break; + } + } + LOG_D("record stop"); + rt_device_close(mic.dev); + } + +__exit: + if (mic.buffer) + rt_free(mic.buffer); +} + +static rt_err_t _record_start(ufunction_t func) +{ + mic.ep->request.buffer = RT_NULL; + mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + mic.ep->request.req_type = UIO_REQUEST_WRITE; + rt_usbd_io_request(func->device, mic.ep, &mic.ep->request); + + mic.open_count ++; + rt_event_send(mic.event, EVENT_RECORD_START); + return 0; +} + +static rt_err_t _record_stop(ufunction_t func) +{ + mic.open_count --; + rt_event_send(mic.event, EVENT_RECORD_STOP); + return 0; +} + +static rt_err_t _ep_data_in_handler(ufunction_t func, rt_size_t size) +{ + RT_ASSERT(func != RT_NULL); + LOG_D("_ep_data_in_handler"); + + mic.ep->request.buffer = mic.buffer + mic.buffer_index; + mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + mic.ep->request.req_type = UIO_REQUEST_WRITE; + rt_usbd_io_request(func->device, mic.ep, &mic.ep->request); + + mic.buffer_index += UAC_EP_MAX_PACKET_SIZE; + if (mic.buffer_index >= RECORD_BUFFER_SZ) + { + mic.buffer_index = 0; + rt_event_send(mic.event, EVENT_RECORD_DATA); + } + else if (mic.buffer_index == RECORD_BUFFER_SZ / 2) + { + rt_event_send(mic.event, EVENT_RECORD_DATA); + } + + return RT_EOK; +} + +static rt_err_t _interface_as_handler(ufunction_t func, ureq_t setup) +{ + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + LOG_D("_interface_as_handler"); + + if ((setup->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + switch (setup->bRequest) + { + case USB_REQ_GET_INTERFACE: + break; + case USB_REQ_SET_INTERFACE: + LOG_D("set interface handler"); + if (setup->wValue == 1) + { + _record_start(func); + } + else if (setup->wValue == 0) + { + _record_stop(func); + } + break; + default: + LOG_D("unknown uac request 0x%x", setup->bRequest); + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static rt_err_t _function_enable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function enable"); + + return RT_EOK; +} + +static rt_err_t _function_disable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function disable"); + _record_stop(func); + return RT_EOK; +} + +static struct ufunction_ops ops = +{ + _function_enable, + _function_disable, + RT_NULL, +}; +/** + * This function will configure uac descriptor. + * + * @param comm the communication interface number. + * @param data the data interface number. + * + * @return RT_EOK on successful. + */ +static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, + rt_uint8_t cintf_nr, struct uac_as_descriptor *as, rt_uint8_t sintf_nr) +{ + ac->hdr_desc.baInterfaceNr[0] = sintf_nr; +#ifdef RT_USB_DEVICE_COMPOSITE + ac->iad_desc.bFirstInterface = cintf_nr; +#endif + + return RT_EOK; +} + +static rt_err_t _uac_samplerate_config(struct uac_as_descriptor *as, rt_uint32_t samplerate) +{ + as->format_type_desc.tSamFreq[0][2] = samplerate >> 16 & 0xff; + as->format_type_desc.tSamFreq[0][1] = samplerate >> 8 & 0xff; + as->format_type_desc.tSamFreq[0][0] = samplerate & 0xff; + return RT_EOK; +} + +/** + * This function will create a uac function instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +ufunction_t rt_usbd_function_uac_mic_create(udevice_t device) +{ + ufunction_t func; + uintf_t intf_ac, intf_as; + ualtsetting_t setting_as0; + ualtsetting_t setting_ac, setting_as; + struct uac_as_descriptor *as_desc_t; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* set usb device string description */ + rt_usbd_device_set_string(device, _ustring); + + /* create a uac function */ + func = rt_usbd_function_new(device, &dev_desc, &ops); + //not support HS + //rt_usbd_device_set_qualifier(device, &dev_qualifier); + + /* create interface */ + intf_ac = rt_usbd_interface_new(device, RT_NULL); + intf_as = rt_usbd_interface_new(device, _interface_as_handler); + + /* create alternate setting */ + setting_ac = rt_usbd_altsetting_new(sizeof(struct uac_ac_descriptor)); + setting_as0 = rt_usbd_altsetting_new(sizeof(struct uinterface_descriptor)); + setting_as = rt_usbd_altsetting_new(sizeof(struct uac_as_descriptor)); + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(setting_ac, &ac_desc, + (rt_off_t) & ((struct uac_ac_descriptor *)0)->intf_desc); + rt_usbd_altsetting_config_descriptor(setting_as0, &as_desc0, 0); + rt_usbd_altsetting_config_descriptor(setting_as, &as_desc, + (rt_off_t) & ((struct uac_as_descriptor *)0)->intf_desc); + /* configure the uac interface descriptor */ + _uac_descriptor_config(setting_ac->desc, intf_ac->intf_num, setting_as->desc, intf_as->intf_num); + _uac_samplerate_config(setting_as->desc, RECORD_SAMPLERATE); + + /* create endpoint */ + as_desc_t = (struct uac_as_descriptor *)setting_as->desc; + mic.ep = rt_usbd_endpoint_new(&as_desc_t->ep_desc, _ep_data_in_handler); + + /* add the endpoint to the alternate setting */ + rt_usbd_altsetting_add_endpoint(setting_as, mic.ep); + + /* add the alternate setting to the interface, then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_ac, setting_ac); + rt_usbd_set_altsetting(intf_ac, 0); + rt_usbd_interface_add_altsetting(intf_as, setting_as0); + rt_usbd_interface_add_altsetting(intf_as, setting_as); + rt_usbd_set_altsetting(intf_as, 0); + + /* add the interface to the uac function */ + rt_usbd_function_add_interface(func, intf_ac); + rt_usbd_function_add_interface(func, intf_as); + + return func; +} + +int audio_mic_init(void) +{ + rt_thread_t mic_tid; + mic.event = rt_event_create("mic_event", RT_IPC_FLAG_FIFO); + + mic_tid = rt_thread_create("mic_thread", + mic_entry, RT_NULL, + 1024, + 5, 10); + + if (mic_tid != RT_NULL) + rt_thread_startup(mic_tid); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(audio_mic_init); + +/* + * register uac class + */ +struct udclass uac_class = +{ + .rt_usbd_function_create = rt_usbd_function_uac_mic_create +}; + +int rt_usbd_uac_mic_class_register(void) +{ + rt_usbd_class_register(&uac_class); + return 0; +} +INIT_PREV_EXPORT(rt_usbd_uac_mic_class_register); diff --git a/components/drivers/usb/usbdevice/class/audio_speaker.c b/components/drivers/usb/usbdevice/class/audio_speaker.c new file mode 100644 index 0000000000..84c36d2053 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio_speaker.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-09-19 flybreak the first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> + +#include "drivers/usb_device.h" +#include "audio.h" + +#define DBG_TAG "usbd.audio.speaker" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#define AUDIO_SAMPLERATE 16000 +#define AUDIO_CHANNEL 1 +#define RESOLUTION_BITS 16 + +#define RESOLUTION_BYTE (RESOLUTION_BITS / 8) +#define AUDIO_PER_MS_SZ ((AUDIO_SAMPLERATE * AUDIO_CHANNEL * RESOLUTION_BYTE) / 1000) +#define AUDIO_BUFFER_SZ (AUDIO_PER_MS_SZ * 20) /* 20ms */ + +#if defined(RT_USBD_SPEAKER_DEVICE_NAME) + #define SPEAKER_DEVICE_NAME RT_USBD_SPEAKER_DEVICE_NAME +#else + #define SPEAKER_DEVICE_NAME "sound0" +#endif + +#define EVENT_AUDIO_START (1 << 0) +#define EVENT_AUDIO_STOP (1 << 1) +#define EVENT_AUDIO_DATA (1 << 2) + +/* + * uac speaker descriptor define + */ + +#define UAC_CS_INTERFACE 0x24 +#define UAC_CS_ENDPOINT 0x25 + +#define UAC_MAX_PACKET_SIZE 64 +#define UAC_EP_MAX_PACKET_SIZE 32 +#define UAC_CHANNEL_NUM AUDIO_CHANNEL +#define UAC_INTR_NUM 1 +#define UAC_CH_NUM 1 +#define UAC_FORMAT_NUM 1 + +struct uac_ac_descriptor +{ +#ifdef RT_USB_DEVICE_COMPOSITE + struct uiad_descriptor iad_desc; +#endif + struct uinterface_descriptor intf_desc; + DECLARE_UAC_AC_HEADER_DESCRIPTOR(UAC_INTR_NUM) hdr_desc; + struct uac_input_terminal_descriptor it_desc; + struct uac1_output_terminal_descriptor ot_desc; +#if UAC_USE_FEATURE_UNIT + DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) feature_unit_desc; +#endif +}; + +struct uac_as_descriptor +{ + struct uinterface_descriptor intf_desc; + struct uac1_as_header_descriptor hdr_desc; + DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(UAC_FORMAT_NUM) format_type_desc; + struct uendpoint_descriptor ep_desc; + struct uac_iso_endpoint_descriptor as_ep_desc; +}; + +/* + * uac speaker device type + */ + +struct uac_audio_speaker +{ + rt_device_t dev; + rt_event_t event; + rt_uint8_t open_count; + + rt_uint8_t *buffer; + rt_uint32_t buffer_index; + + uep_t ep; +}; +static struct uac_audio_speaker speaker; + +ALIGN(4) +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_DEVICE, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + UAC_MAX_PACKET_SIZE, //bMaxPacketSize0; + _VENDOR_ID, //idVendor; + _PRODUCT_ID, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber;Unused. + USB_DYNAMIC, //bNumConfigurations; +}; + +//FS and HS needed +ALIGN(4) +static struct usb_qualifier_descriptor dev_qualifier = +{ + sizeof(dev_qualifier), //bLength + USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType + 0x0200, //bcdUSB + USB_CLASS_AUDIO, //bDeviceClass + 0x00, //bDeviceSubClass + 0x00, //bDeviceProtocol + 64, //bMaxPacketSize0 + 0x01, //bNumConfigurations + 0, +}; + +ALIGN(4) +const static char *_ustring[] = +{ + "Language", + "RT-Thread Team.", + "RT-Thread Speaker", + "32021919830108", + "Configuration", + "Interface", +}; + +ALIGN(4) +static struct uac_ac_descriptor ac_desc = +{ +#ifdef RT_USB_DEVICE_COMPOSITE + /* Interface Association Descriptor */ + { + USB_DESC_LENGTH_IAD, + USB_DESC_TYPE_IAD, + USB_DYNAMIC, + 0x02, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, +#endif + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOCONTROL, + 0x00, + 0x00, + }, + /* Header Descriptor */ + { + UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + UAC_CS_INTERFACE, + UAC_HEADER, + 0x0100, /* Version: 1.00 */ + 0x0027, /* Total length: 39 */ + 0x01, /* Total number of interfaces: 1 */ + {0x01}, /* Interface number: 1 */ + }, + /* Input Terminal Descriptor */ + { + UAC_DT_INPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_INPUT_TERMINAL, + 0x01, /* Terminal ID: 1 */ + 0x0101, /* Terminal Type: USB Streaming (0x0101) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Number Channels: 1 */ + 0x0000, /* Channel Config: 0x0000 */ + 0x00, /* Channel Names: 0 */ + 0x00, /* Terminal: 0 */ + }, + /* Output Terminal Descriptor */ + { + UAC_DT_OUTPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_OUTPUT_TERMINAL, + 0x02, /* Terminal ID: 2 */ + 0x0302, /* Terminal Type: Headphones (0x0302) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Source ID: 1 */ + 0x00, /* Terminal: 0 */ + }, +#if UAC_USE_FEATURE_UNIT + /* Feature unit Descriptor */ + { + UAC_DT_FEATURE_UNIT_SIZE(UAC_CH_NUM), + UAC_CS_INTERFACE, + UAC_FEATURE_UNIT, + 0x02, + 0x0101, + 0x00, + 0x01, + }, +#endif +}; + +ALIGN(4) +static struct uinterface_descriptor as_desc0 = +{ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, +}; + +ALIGN(4) +static struct uac_as_descriptor as_desc = +{ + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x01, + 0x01, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, + /* General AS Descriptor */ + { + UAC_DT_AS_HEADER_SIZE, + UAC_CS_INTERFACE, + UAC_AS_GENERAL, + 0x01, /* Terminal ID: 1 */ + 0x01, /* Interface delay in frames: 1 */ + UAC_FORMAT_TYPE_I_PCM, + }, + /* Format type i Descriptor */ + { + UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + UAC_CS_INTERFACE, + UAC_FORMAT_TYPE, + UAC_FORMAT_TYPE_I, + UAC_CHANNEL_NUM, + 2, /* Subframe Size: 2 */ + RESOLUTION_BITS, + 0x01, /* Samples Frequence Type: 1 */ + {0}, /* Samples Frequence */ + }, + /* Endpoint Descriptor */ + { + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_OUT, + USB_EP_ATTR_ISOC, + UAC_EP_MAX_PACKET_SIZE, + 0x01, + }, + /* AS Endpoint Descriptor */ + { + UAC_ISO_ENDPOINT_DESC_SIZE, + UAC_CS_ENDPOINT, + UAC_MS_GENERAL, + }, +}; + +void speaker_entry(void *parameter) +{ + struct rt_audio_caps caps = {0}; + rt_uint32_t e, index; + + speaker.buffer = rt_malloc(AUDIO_BUFFER_SZ); + if (speaker.buffer == RT_NULL) + { + LOG_E("malloc failed"); + goto __exit; + } + + speaker.dev = rt_device_find(SPEAKER_DEVICE_NAME); + if (speaker.dev == RT_NULL) + { + LOG_E("can't find device:%s", SPEAKER_DEVICE_NAME); + goto __exit; + } + + while (1) + { + if (rt_event_recv(speaker.event, EVENT_AUDIO_START | EVENT_AUDIO_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + continue; + } + if (speaker.open_count == 0) + { + continue; + } + LOG_D("play start"); + + rt_device_open(speaker.dev, RT_DEVICE_OFLAG_WRONLY); + + caps.main_type = AUDIO_TYPE_OUTPUT; + caps.sub_type = AUDIO_DSP_PARAM; + caps.udata.config.samplerate = AUDIO_SAMPLERATE; + caps.udata.config.channels = AUDIO_CHANNEL; + caps.udata.config.samplebits = RESOLUTION_BITS; + rt_device_control(speaker.dev, AUDIO_CTL_CONFIGURE, &caps); + + while (1) + { + if (rt_event_recv(speaker.event, EVENT_AUDIO_DATA | EVENT_AUDIO_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + if (speaker.open_count > 0) + continue; + else + break; + } + if (e & EVENT_AUDIO_DATA) + { + index = (speaker.buffer_index >= AUDIO_BUFFER_SZ / 2) ? 0 : (AUDIO_BUFFER_SZ / 2); + rt_device_write(speaker.dev, 0, speaker.buffer + index, AUDIO_BUFFER_SZ / 2); + } + else if (e & EVENT_AUDIO_STOP) + { + break; + } + } + LOG_D("play stop"); + rt_device_close(speaker.dev); + } + +__exit: + if (speaker.buffer) + rt_free(speaker.buffer); +} + +static rt_err_t _audio_start(ufunction_t func) +{ + speaker.ep->request.buffer = speaker.buffer; + speaker.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + speaker.ep->request.req_type = UIO_REQUEST_READ_FULL; + rt_usbd_io_request(func->device, speaker.ep, &speaker.ep->request); + + speaker.open_count ++; + rt_event_send(speaker.event, EVENT_AUDIO_START); + + return 0; +} + +static rt_err_t _audio_stop(ufunction_t func) +{ + speaker.open_count --; + rt_event_send(speaker.event, EVENT_AUDIO_STOP); + return 0; +} + +static rt_err_t _ep_data_handler(ufunction_t func, rt_size_t size) +{ + RT_ASSERT(func != RT_NULL); + LOG_D("_ep_data_handler"); + + speaker.ep->request.buffer = speaker.buffer + speaker.buffer_index; + speaker.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + speaker.ep->request.req_type = UIO_REQUEST_READ_FULL; + rt_usbd_io_request(func->device, speaker.ep, &speaker.ep->request); + + speaker.buffer_index += UAC_EP_MAX_PACKET_SIZE; + if (speaker.buffer_index >= AUDIO_BUFFER_SZ) + { + speaker.buffer_index = 0; + rt_event_send(speaker.event, EVENT_AUDIO_DATA); + } + else if (speaker.buffer_index == AUDIO_BUFFER_SZ / 2) + { + rt_event_send(speaker.event, EVENT_AUDIO_DATA); + } + + return RT_EOK; +} + +static rt_err_t _interface_as_handler(ufunction_t func, ureq_t setup) +{ + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + LOG_D("_interface_as_handler"); + + if ((setup->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + switch (setup->bRequest) + { + case USB_REQ_GET_INTERFACE: + break; + case USB_REQ_SET_INTERFACE: + LOG_D("set interface handler"); + if (setup->wValue == 1) + { + _audio_start(func); + } + else if (setup->wValue == 0) + { + _audio_stop(func); + } + break; + default: + LOG_D("unknown uac request 0x%x", setup->bRequest); + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static rt_err_t _function_enable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function enable"); + + return RT_EOK; +} + +static rt_err_t _function_disable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function disable"); + _audio_stop(func); + return RT_EOK; +} + +static struct ufunction_ops ops = +{ + _function_enable, + _function_disable, + RT_NULL, +}; +/** + * This function will configure uac descriptor. + * + * @param comm the communication interface number. + * @param data the data interface number. + * + * @return RT_EOK on successful. + */ +static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, + rt_uint8_t cintf_nr, struct uac_as_descriptor *as, rt_uint8_t sintf_nr) +{ + ac->hdr_desc.baInterfaceNr[0] = sintf_nr; +#ifdef RT_USB_DEVICE_COMPOSITE + ac->iad_desc.bFirstInterface = cintf_nr; +#endif + + return RT_EOK; +} + +static rt_err_t _uac_samplerate_config(struct uac_as_descriptor *as, rt_uint32_t samplerate) +{ + as->format_type_desc.tSamFreq[0][2] = samplerate >> 16 & 0xff; + as->format_type_desc.tSamFreq[0][1] = samplerate >> 8 & 0xff; + as->format_type_desc.tSamFreq[0][0] = samplerate & 0xff; + return RT_EOK; +} + +/** + * This function will create a uac function instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +ufunction_t rt_usbd_function_uac_speaker_create(udevice_t device) +{ + ufunction_t func; + uintf_t intf_ac, intf_as; + ualtsetting_t setting_as0; + ualtsetting_t setting_ac, setting_as; + struct uac_as_descriptor *as_desc_t; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* set usb device string description */ + rt_usbd_device_set_string(device, _ustring); + + /* create a uac function */ + func = rt_usbd_function_new(device, &dev_desc, &ops); + //not support HS + //rt_usbd_device_set_qualifier(device, &dev_qualifier); + + /* create interface */ + intf_ac = rt_usbd_interface_new(device, RT_NULL); + intf_as = rt_usbd_interface_new(device, _interface_as_handler); + + /* create alternate setting */ + setting_ac = rt_usbd_altsetting_new(sizeof(struct uac_ac_descriptor)); + setting_as0 = rt_usbd_altsetting_new(sizeof(struct uinterface_descriptor)); + setting_as = rt_usbd_altsetting_new(sizeof(struct uac_as_descriptor)); + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(setting_ac, &ac_desc, + (rt_off_t) & ((struct uac_ac_descriptor *)0)->intf_desc); + rt_usbd_altsetting_config_descriptor(setting_as0, &as_desc0, 0); + rt_usbd_altsetting_config_descriptor(setting_as, &as_desc, + (rt_off_t) & ((struct uac_as_descriptor *)0)->intf_desc); + /* configure the uac interface descriptor */ + _uac_descriptor_config(setting_ac->desc, intf_ac->intf_num, setting_as->desc, intf_as->intf_num); + _uac_samplerate_config(setting_as->desc, AUDIO_SAMPLERATE); + + /* create endpoint */ + as_desc_t = (struct uac_as_descriptor *)setting_as->desc; + speaker.ep = rt_usbd_endpoint_new(&as_desc_t->ep_desc, _ep_data_handler); + + /* add the endpoint to the alternate setting */ + rt_usbd_altsetting_add_endpoint(setting_as, speaker.ep); + + /* add the alternate setting to the interface, then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_ac, setting_ac); + rt_usbd_set_altsetting(intf_ac, 0); + rt_usbd_interface_add_altsetting(intf_as, setting_as0); + rt_usbd_interface_add_altsetting(intf_as, setting_as); + rt_usbd_set_altsetting(intf_as, 0); + + /* add the interface to the uac function */ + rt_usbd_function_add_interface(func, intf_ac); + rt_usbd_function_add_interface(func, intf_as); + + return func; +} + +int audio_speaker_init(void) +{ + rt_thread_t speaker_tid; + speaker.event = rt_event_create("speaker_event", RT_IPC_FLAG_FIFO); + + speaker_tid = rt_thread_create("speaker_thread", + speaker_entry, RT_NULL, + 1024, + 5, 10); + + if (speaker_tid != RT_NULL) + rt_thread_startup(speaker_tid); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(audio_speaker_init); + +/* + * register uac class + */ +static struct udclass uac_speaker_class = +{ + .rt_usbd_function_create = rt_usbd_function_uac_speaker_create +}; + +int rt_usbd_uac_speaker_class_register(void) +{ + rt_usbd_class_register(&uac_speaker_class); + return 0; +} +INIT_PREV_EXPORT(rt_usbd_uac_speaker_class_register); diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index 336cfcb152..64230533ae 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -28,7 +28,11 @@ #define VCOM_TX_TIMEOUT 1000 #endif /*RT_VCOM_TX_TIMEOUT*/ +#ifdef RT_CDC_RX_BUFSIZE +#define CDC_RX_BUFSIZE RT_CDC_RX_BUFSIZE +#else #define CDC_RX_BUFSIZE 128 +#endif #define CDC_MAX_PACKET_SIZE 64 #define VCOM_DEVICE "vcom" @@ -63,6 +67,7 @@ static struct ucdc_line_coding line_coding; #define CDC_BULKIN_MAXSIZE (CDC_TX_BUFSIZE / 8) #define CDC_TX_HAS_DATE 0x01 +#define CDC_TX_HAS_SPACE 0x02 struct vcom { @@ -488,6 +493,7 @@ static rt_err_t _function_enable(ufunction_t func) data = (struct vcom*)func->user_data; data->ep_out->buffer = rt_malloc(CDC_RX_BUFSIZE); + RT_ASSERT(data->ep_out->buffer != RT_NULL); data->ep_out->request.buffer = data->ep_out->buffer; data->ep_out->request.size = EP_MAXPACKET(data->ep_out); @@ -583,11 +589,13 @@ ufunction_t rt_usbd_function_cdc_create(udevice_t device) /* create a cdc function */ func = rt_usbd_function_new(device, &dev_desc, &ops); - //not support HS - //rt_usbd_device_set_qualifier(device, &dev_qualifier); + + /* support HS */ + rt_usbd_device_set_qualifier(device, &dev_qualifier); /* allocate memory for cdc vcom data */ data = (struct vcom*)rt_malloc(sizeof(struct vcom)); + RT_ASSERT(data != RT_NULL); rt_memset(data, 0, sizeof(struct vcom)); func->user_data = (void*)data; @@ -693,23 +701,48 @@ static int _vcom_getc(struct rt_serial_device *serial) return result; } -static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size,int direction) + +static rt_size_t _vcom_rb_block_put(struct vcom *data, const rt_uint8_t *buf, rt_size_t size) { rt_uint32_t level; + rt_size_t put_len = 0; + rt_size_t w_ptr = 0; + rt_uint32_t res; + rt_size_t remain_size = size; + + while (remain_size) + { + level = rt_hw_interrupt_disable(); + put_len = rt_ringbuffer_put(&data->tx_ringbuffer, (const rt_uint8_t *)&buf[w_ptr], remain_size); + rt_hw_interrupt_enable(level); + w_ptr += put_len; + remain_size -= put_len; + if (put_len == 0) + { + rt_event_recv(&data->tx_event, CDC_TX_HAS_SPACE, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + VCOM_TX_TIMEOUT, &res); + } + else + { + rt_event_send(&data->tx_event, CDC_TX_HAS_DATE); + } + } + + return size; +} +static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size,int direction) +{ struct ufunction *func; struct vcom *data; - rt_uint32_t baksize; + rt_uint32_t send_size = 0; rt_size_t ptr = 0; - int empty = 0; rt_uint8_t crlf[2] = {'\r', '\n',}; func = (struct ufunction*)serial->parent.user_data; data = (struct vcom*)func->user_data; - size = (size >= CDC_BULKIN_MAXSIZE) ? CDC_BULKIN_MAXSIZE : size; - baksize = size; - RT_ASSERT(serial != RT_NULL); RT_ASSERT(buf != RT_NULL); @@ -717,64 +750,37 @@ static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_s if (data->connected) { - size = 0; if((serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) { - empty = 0; - while(ptr < baksize) + while(send_size < size) { - while(ptr < baksize && buf[ptr] != '\n') + while(ptr < size && buf[ptr] != '\n') { ptr++; } - if(ptr < baksize) + if(ptr < size) { - level = rt_hw_interrupt_disable(); - size += rt_ringbuffer_put_force(&data->tx_ringbuffer, (const rt_uint8_t *)&buf[size], ptr - size); - rt_hw_interrupt_enable(level); - - /* no data was be ignored */ - if(size == ptr) - { - level = rt_hw_interrupt_disable(); - if(rt_ringbuffer_space_len(&data->tx_ringbuffer) >= 2) - { - rt_ringbuffer_put_force(&data->tx_ringbuffer, crlf, 2); - size++; - } - rt_hw_interrupt_enable(level); - } - else - { - empty = 1; - break; - } - - /* ring buffer is full */ - if(size == ptr) - { - empty = 1; - break; - } + send_size += _vcom_rb_block_put(data, (const rt_uint8_t *)&buf[send_size], ptr - send_size); + _vcom_rb_block_put(data, crlf, 2); + send_size++; ptr++; } + else if (ptr == size) + { + send_size += _vcom_rb_block_put(data, (const rt_uint8_t *)&buf[send_size], ptr - send_size); + } else { break; } } } - - if(size < baksize && !empty) + else { - level = rt_hw_interrupt_disable(); - size += rt_ringbuffer_put_force(&data->tx_ringbuffer, (rt_uint8_t *)&buf[size], baksize - size); - rt_hw_interrupt_enable(level); - } - - if(size) - { - rt_event_send(&data->tx_event, CDC_TX_HAS_DATE); + while (send_size < size) + { + send_size += _vcom_rb_block_put(data, (rt_uint8_t *)&buf[send_size], size - send_size); + } } } else @@ -902,6 +908,7 @@ static void vcom_tx_thread_entry(void* parameter) #else rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE); #endif + rt_event_send(&data->tx_event, CDC_TX_HAS_SPACE); } } diff --git a/components/drivers/usb/usbdevice/class/ecm.c b/components/drivers/usb/usbdevice/class/ecm.c index cda1a8bf1b..36557dad74 100644 --- a/components/drivers/usb/usbdevice/class/ecm.c +++ b/components/drivers/usb/usbdevice/class/ecm.c @@ -6,17 +6,16 @@ * Change Logs: * Date Author Notes * 2017-11-19 ZYH first version + * 2019-06-10 ZYH fix hotplug */ #include <rtdevice.h> +#ifdef RT_USB_DEVICE_ECM #include "cdc.h" - -#ifdef ECM_DEBUG -#define ECM_PRINTF rt_kprintf("[ECM] "); rt_kprintf -#else -#define ECM_PRINTF(...) -#endif /* ECM_DEBUG */ +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "ECM" +#include <rtdbg.h> /* RT-Thread LWIP ethernet interface */ #include <netif/ethernetif.h> @@ -216,15 +215,21 @@ static rt_err_t _cdc_send_notifi(ufunction_t func,ucdc_notification_code_t notif return RT_EOK; } + static rt_err_t _ecm_set_eth_packet_filter(ufunction_t func, ureq_t setup) { rt_ecm_eth_t _ecm_eth = (rt_ecm_eth_t)func->user_data; dcd_ep0_send_status(func->device->dcd); - /* send link up. */ eth_device_linkchange(&_ecm_eth->parent, RT_TRUE); - _cdc_send_notifi(func,UCDC_NOTIFI_NETWORK_CONNECTION,1,0); + _cdc_send_notifi(func, UCDC_NOTIFI_NETWORK_CONNECTION, 1, 0); + +#ifdef LWIP_USING_DHCPD + extern void dhcpd_start(const char *netif_name); + dhcpd_start("u0"); +#endif + return RT_EOK; } /** @@ -243,10 +248,11 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) switch(setup->bRequest) { case CDC_SET_ETH_PACKET_FILTER: + LOG_D("CDC_SET_ETH_PACKET_FILTER"); _ecm_set_eth_packet_filter(func, setup); break; default: - rt_kprintf("setup->bRequest:0x%02X",setup->bRequest); + LOG_E("Unknow setup->bRequest: 0x%02X", setup->bRequest); break; } return RT_EOK; @@ -402,22 +408,26 @@ rt_err_t rt_ecm_eth_tx(rt_device_t dev, struct pbuf* p) if(!ecm_eth_dev->parent.link_status) { - ECM_PRINTF("linkdown, drop pkg\r\n"); + LOG_D("linkdown, drop pkg"); return RT_EOK; } - // RT_ASSERT(p->tot_len < USB_ETH_MTU); if(p->tot_len > USB_ETH_MTU) { - ECM_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("ECM MTU is:%d, but the send packet size is %d", USB_ETH_MTU, p->tot_len); p->tot_len = USB_ETH_MTU; } - result = rt_sem_take(&ecm_eth_dev->tx_buffer_free, RT_WAITING_FOREVER); + + result = rt_sem_take(&ecm_eth_dev->tx_buffer_free, rt_tick_from_millisecond(1000)); if(result != RT_EOK) { + LOG_W("wait for buffer free timeout"); + /* if cost 1s to wait send done it said that connection is close . drop it */ + rt_sem_release(&ecm_eth_dev->tx_buffer_free); return result; } + pbuffer = (char *)&ecm_eth_dev->tx_buffer; for (q = p; q != NULL; q = q->next) { @@ -461,8 +471,13 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data; + + LOG_D("plugged in"); + eps = (cdc_eps_t)&ecm_device->eps; eps->ep_out->buffer = ecm_device->rx_pool; + + /* reset eth rx tx */ ecm_device->rx_size = 0; ecm_device->rx_offset = 0; @@ -482,7 +497,14 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { + LOG_D("plugged out"); + eth_device_linkchange(&((rt_ecm_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_ecm_eth_t)func->user_data)->rx_size = 0; + ((rt_ecm_eth_t)func->user_data)->rx_offset = 0; + return RT_EOK; } @@ -543,7 +565,8 @@ ufunction_t rt_usbd_function_ecm_create(udevice_t device) /* create a cdc class */ cdc = rt_usbd_function_new(device, &_dev_desc, &ops); rt_usbd_device_set_qualifier(device, &dev_qualifier); - _ecm_eth= rt_malloc(sizeof(struct rt_ecm_eth)); + _ecm_eth= rt_malloc(sizeof(struct rt_ecm_eth)); + RT_ASSERT(_ecm_eth != RT_NULL); rt_memset(_ecm_eth, 0, sizeof(struct rt_ecm_eth)); cdc->user_data = _ecm_eth; @@ -643,3 +666,5 @@ int rt_usbd_ecm_class_register(void) return 0; } INIT_PREV_EXPORT(rt_usbd_ecm_class_register); + +#endif /* RT_USB_DEVICE_ECM */ diff --git a/components/drivers/usb/usbdevice/class/hid.c b/components/drivers/usb/usbdevice/class/hid.c index aea6d802d1..a4acce75ea 100644 --- a/components/drivers/usb/usbdevice/class/hid.c +++ b/components/drivers/usb/usbdevice/class/hid.c @@ -29,7 +29,7 @@ struct hid_s uep_t ep_in; uep_t ep_out; int status; - rt_uint16_t protocol; + rt_uint8_t protocol; rt_uint8_t report_buf[MAX_REPORT_SIZE]; struct rt_messagequeue hid_mq; }; @@ -246,7 +246,7 @@ static struct udevice_descriptor _dev_desc = USB_DESC_LENGTH_DEVICE, //bLength; USB_DESC_TYPE_DEVICE, //type; USB_BCD_VERSION, //bcdUSB; - USB_CLASS_HID, //bDeviceClass; + 0x0, //bDeviceClass; 0x00, //bDeviceSubClass; 0x00, //bDeviceProtocol; 64, //bMaxPacketSize0; @@ -266,8 +266,8 @@ static struct usb_qualifier_descriptor dev_qualifier = sizeof(dev_qualifier), //bLength USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType 0x0200, //bcdUSB - USB_CLASS_MASS_STORAGE, //bDeviceClass - 0x06, //bDeviceSubClass + 0x0, //bDeviceClass + 0x0, //bDeviceSubClass 0x50, //bDeviceProtocol 64, //bMaxPacketSize0 0x01, //bNumConfigurations @@ -347,7 +347,7 @@ const static struct uhid_comm_descriptor _hid_comm_desc = USB_DYNAMIC | USB_DIR_IN, USB_EP_ATTR_INT, 0x40, - 0x01, + 0x0A, }, /* Endpoint Descriptor OUT */ @@ -372,7 +372,7 @@ const static char* _ustring[] = "Interface", }; -static void dump_data(uint8_t *data, rt_size_t size) +static void dump_data(rt_uint8_t *data, rt_size_t size) { rt_size_t i; for (i = 0; i < size; i++) @@ -458,8 +458,6 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) struct hid_s *data = (struct hid_s *) func->user_data; - if(setup->wIndex != 0) - return -RT_EIO; switch (setup->bRequest) { @@ -489,7 +487,7 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) dcd_ep0_send_status(func->device->dcd); break; case USB_HID_REQ_GET_PROTOCOL: - rt_usbd_ep0_write(func->device, &data->protocol,2); + rt_usbd_ep0_write(func->device, &data->protocol,1); break; case USB_HID_REQ_SET_REPORT: @@ -695,8 +693,9 @@ ufunction_t rt_usbd_function_hid_create(udevice_t device) /* create a cdc function */ func = rt_usbd_function_new(device, &_dev_desc, &ops); - //not support hs - //rt_usbd_device_set_qualifier(device, &_dev_qualifier); + + /* For high speed mode supporting */ + rt_usbd_device_set_qualifier(device, &dev_qualifier); /* allocate memory for cdc vcom data */ data = (struct hid_s*)rt_malloc(sizeof(struct hid_s)); diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c index 6a6e92415b..d0a2b7f736 100644 --- a/components/drivers/usb/usbdevice/class/mstorage.c +++ b/components/drivers/usb/usbdevice/class/mstorage.c @@ -16,6 +16,10 @@ #include "drivers/usb_device.h" #include "mstorage.h" +#ifdef RT_USING_DFS_MNTTABLE +#include "dfs_fs.h" +#endif + #ifdef RT_USB_DEVICE_MSTORAGE enum STAT @@ -422,7 +426,7 @@ static rt_size_t _read_capacity(ufunction_t func, ustorage_cbw_t cbw) data = (struct mstorage*)func->user_data; buf = data->ep_in->buffer; - sector_count = data->geometry.sector_count; + sector_count = data->geometry.sector_count - 1; /* Last Logical Block Address */ sector_size = data->geometry.bytes_per_sector; buf[0] = sector_count >> 24; @@ -606,8 +610,11 @@ static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size) rt_usbd_ep_set_stall(func->device, data->ep_out); } else - { - rt_usbd_ep_set_stall(func->device, data->ep_in); + { + //rt_kprintf("warning:in stall path but not stall\n"); + + /* FIXME: Disable the operation or the disk cannot work. */ + //rt_usbd_ep_set_stall(func->device, data->ep_in); } data->csw_response.data_reside = 0; } @@ -715,9 +722,22 @@ static void _cb_len_calc(ufunction_t func, struct scsi_cmd* cmd, break; } } + + //workaround: for stability in full-speed mode + else if(cmd->cmd_len == 12) + { + switch(cmd->type) + { + case COUNT: + data->cb_data_size = cbw->cb[4]; + break; + default: + break; + } + } else { -// rt_kprintf("cmd_len error %d\n", cmd->cmd_len); + rt_kprintf("cmd_len error %d\n", cmd->cmd_len); } } @@ -733,7 +753,7 @@ static rt_bool_t _cbw_verify(ufunction_t func, struct scsi_cmd* cmd, data = (struct mstorage*)func->user_data; if(cmd->cmd_len != cbw->cb_len) { - // rt_kprintf("cb_len error\n"); + rt_kprintf("cb_len error\n"); cmd->cmd_len = cbw->cb_len; } @@ -764,7 +784,7 @@ static rt_bool_t _cbw_verify(ufunction_t func, struct scsi_cmd* cmd, if(cbw->xfer_len < data->cb_data_size) { - // rt_kprintf("xfer_len < data_size\n"); + rt_kprintf("xfer_len < data_size\n"); data->cb_data_size = cbw->xfer_len; data->csw_response.status = 1; } @@ -955,7 +975,7 @@ static rt_err_t _function_enable(ufunction_t func) struct mstorage *data; RT_ASSERT(func != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_USB, ("Mass storage function enabled\n")); - data = (struct mstorage*)func->user_data; + data = (struct mstorage*)func->user_data; data->disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME); if(data->disk == RT_NULL) @@ -964,6 +984,10 @@ static rt_err_t _function_enable(ufunction_t func) return -RT_ERROR; } +#ifdef RT_USING_DFS_MNTTABLE + dfs_unmount_device(data->disk); +#endif + if(rt_device_open(data->disk, RT_DEVICE_OFLAG_RDWR) != RT_EOK) { rt_kprintf("disk open error\n"); @@ -1029,6 +1053,9 @@ static rt_err_t _function_disable(ufunction_t func) if(data->disk != RT_NULL) { rt_device_close(data->disk); +#ifdef RT_USING_DFS_MNTTABLE + dfs_mount_device(data->disk); +#endif data->disk = RT_NULL; } diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c index 8996b728e6..93e0ba6ae2 100644 --- a/components/drivers/usb/usbdevice/class/rndis.c +++ b/components/drivers/usb/usbdevice/class/rndis.c @@ -13,21 +13,21 @@ * 2013-07-09 aozima support respone chain list. * 2013-07-18 aozima re-initial respone chain list when RNDIS restart. * 2017-11-25 ZYH fix it and add OS descriptor + * 2019-06-10 ZYH fix hot plug and delay linkup */ #include <rtdevice.h> +#ifdef RT_USB_DEVICE_RNDIS #include "cdc.h" #include "rndis.h" #include "ndis.h" -//#define RNDIS_DEBUG -//#define RNDIS_DELAY_LINK_UP +/* define RNDIS_DELAY_LINK_UP by menuconfig for delay linkup */ + +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "RNDIS" +#include <rtdbg.h> -#ifdef RNDIS_DEBUG -#define RNDIS_PRINTF rt_kprintf("[RNDIS] "); rt_kprintf -#else -#define RNDIS_PRINTF(...) -#endif /* RNDIS_DEBUG */ /* RT-Thread LWIP ethernet interface */ #include <netif/ethernetif.h> @@ -314,7 +314,7 @@ static rt_err_t _rndis_init_response(ufunction_t func, rndis_init_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -360,7 +360,7 @@ static rndis_query_cmplt_t _create_resp(rt_size_t size) if(resp == RT_NULL) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); return RT_NULL; } @@ -421,7 +421,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) case OID_GEN_LINK_SPEED: resp = _create_resp(4); if(resp == RT_NULL) break; - _set_resp(resp, func->device->dcd->device_is_hs ? (480UL * 1000 *1000) : (12UL * 1000 * 1000) / 100); + _set_resp(resp, (func->device->dcd->device_is_hs ? (480UL * 1000 *1000) : (12UL * 1000 * 1000)) / 100); break; case OID_GEN_MEDIA_CONNECT_STATUS: @@ -510,7 +510,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) break; default: - RNDIS_PRINTF("OID %X\n", msg->Oid); + LOG_W("Not support OID %X", msg->Oid); ret = -RT_ERROR; break; } @@ -518,7 +518,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) response = rt_malloc(sizeof(struct rt_rndis_response)); if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -557,7 +557,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -577,8 +577,10 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) case OID_GEN_CURRENT_PACKET_FILTER: oid_packet_filter = *((rt_uint32_t *)((rt_uint8_t *)&(msg->RequestId) + \ msg->InformationBufferOffset)); + /* TODO: make complier happy */ oid_packet_filter = oid_packet_filter; - RNDIS_PRINTF("OID_GEN_CURRENT_PACKET_FILTER\r\n"); + + LOG_D("OID_GEN_CURRENT_PACKET_FILTER"); #ifdef RNDIS_DELAY_LINK_UP /* link up. */ @@ -592,6 +594,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) break; default: + LOG_W("Unknow rndis set 0x%02X", msg->Oid); resp->Status = RNDIS_STATUS_FAILURE; return RT_EOK; } @@ -609,6 +612,56 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) return RT_EOK; } +static rt_err_t _rndis_reset_response(ufunction_t func,rndis_set_msg_t msg) +{ + struct rndis_reset_cmplt * resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_reset_cmplt)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + /* reset packet filter */ + + oid_packet_filter = 0x0000000; + + /* link down eth */ + + eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + + + resp->MessageType = REMOTE_NDIS_RESET_CMPLT; + resp->MessageLength = sizeof(struct rndis_reset_cmplt); + resp->Status = RNDIS_STATUS_SUCCESS; + resp->AddressingReset = 1; + + response->buffer = resp; + + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + return RT_EOK; +} + static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t msg) { rndis_keepalive_cmplt_t resp; @@ -619,7 +672,7 @@ static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -652,34 +705,42 @@ static rt_err_t _rndis_msg_parser(ufunction_t func, rt_uint8_t *msg) switch (((rndis_gen_msg_t) msg)->MessageType) { case REMOTE_NDIS_INITIALIZE_MSG: + LOG_D("REMOTE_NDIS_INITIALIZE_MSG"); ret = _rndis_init_response(func, (rndis_init_msg_t) msg); break; case REMOTE_NDIS_HALT_MSG: - RNDIS_PRINTF("halt\n"); + LOG_D("REMOTE_NDIS_HALT_MSG"); /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; break; case REMOTE_NDIS_QUERY_MSG: + LOG_D("REMOTE_NDIS_QUERY_MSG"); ret = _rndis_query_response(func,(rndis_query_msg_t) msg); break; case REMOTE_NDIS_SET_MSG: + LOG_D("REMOTE_NDIS_SET_MSG"); ret = _rndis_set_response(func,(rndis_set_msg_t) msg); - RNDIS_PRINTF("set\n"); break; case REMOTE_NDIS_RESET_MSG: - RNDIS_PRINTF("reset\n"); + LOG_D("REMOTE_NDIS_RESET_MSG"); + ret = _rndis_reset_response(func,(rndis_set_msg_t) msg); break; case REMOTE_NDIS_KEEPALIVE_MSG: + LOG_D("REMOTE_NDIS_KEEPALIVE_MSG"); ret = _rndis_keepalive_response(func,(rndis_keepalive_msg_t) msg); break; default: - RNDIS_PRINTF("msg %X\n", ((rndis_gen_msg_t) msg)->MessageType); + LOG_W("not support RNDIS msg %X", ((rndis_gen_msg_t) msg)->MessageType); ret = -RT_ERROR; break; } @@ -718,7 +779,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) if(rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { - RNDIS_PRINTF("response_list is empty!\r\n"); + LOG_D("response_list is empty!"); ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE; return RT_EOK; } @@ -741,7 +802,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) { rt_uint32_t * data; - RNDIS_PRINTF("auto append next response!\r\n"); + LOG_I("auto append next response!"); data = (rt_uint32_t *)((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer; data[0] = RESPONSE_AVAILABLE; data[1] = 0; @@ -758,55 +819,6 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) return RT_EOK; } -#ifdef RNDIS_DELAY_LINK_UP -/** - * This function will set rndis connect status. - * - * @param device the usb device object. - * @param status the connect status. - * - * @return RT_EOK on successful. - */ -static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) -{ - rndis_indicate_status_msg_t resp; - struct rt_rndis_response * response; - - response = rt_malloc(sizeof(struct rt_rndis_response)); - resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); - - if( (response == RT_NULL) || (resp == RT_NULL) ) - { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); - - if(response != RT_NULL) - rt_free(response); - - if(resp != RT_NULL) - rt_free(resp); - - return -RT_ENOMEM; - } - - resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; - resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ - resp->Status = status; - resp->StatusBufferLength = 0; - resp->StatusBufferOffset = 0; - - response->buffer = resp; - { - rt_base_t level = rt_hw_interrupt_disable(); - rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); - rt_hw_interrupt_enable(level); - } - - _rndis_response_available(func); - - return RT_EOK; -} -#endif /* RNDIS_DELAY_LINK_UP */ - /** * This function will handle rndis interface request. * @@ -831,7 +843,7 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) break; default: - RNDIS_PRINTF("unkown setup->request!\r\n"); + LOG_W("unkown setup->request 0x%02X !", setup->bRequest); break; } @@ -933,6 +945,8 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; + LOG_I("plugged in"); + eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps; eps->ep_in->buffer = ((rt_rndis_eth_t)func->user_data)->tx_pool; eps->ep_out->buffer = ((rt_rndis_eth_t)func->user_data)->rx_pool; @@ -945,6 +959,7 @@ static rt_err_t _function_enable(ufunction_t func) ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + // eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent)); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -981,7 +996,7 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { - RNDIS_PRINTF("plugged out\n"); + LOG_I("plugged out"); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -996,7 +1011,7 @@ static rt_err_t _function_disable(ufunction_t func) while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next; - RNDIS_PRINTF("remove resp chain list!\r\n"); + LOG_D("remove resp chain list!"); rt_list_remove(&response->list); rt_free((void *)response->buffer); @@ -1007,8 +1022,14 @@ static rt_err_t _function_disable(ufunction_t func) rt_hw_interrupt_enable(level); } + /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + return RT_EOK; } @@ -1141,22 +1162,25 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p) if(!device->parent.link_status) { - RNDIS_PRINTF("linkdown, drop pkg\r\n"); + LOG_I("linkdown, drop pkg"); return RT_EOK; } - RT_ASSERT(p->tot_len < sizeof(device->tx_buffer)); + //RT_ASSERT(p->tot_len < sizeof(device->tx_buffer)); if(p->tot_len > sizeof(device->tx_buffer)) { - RNDIS_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("RNDIS MTU is:%d, but the send packet size is %d", sizeof(device->tx_buffer), p->tot_len); p->tot_len = sizeof(device->tx_buffer); } /* wait for buffer free. */ - result = rt_sem_take(&device->tx_buffer_free, RT_WAITING_FOREVER); + result = rt_sem_take(&device->tx_buffer_free, rt_tick_from_millisecond(1000)); if(result != RT_EOK) { + LOG_W("wait for buffer free timeout"); + /* if cost 1s to wait send done it said that connection is close . drop it */ + rt_sem_release(&device->tx_buffer_free); return result; } @@ -1215,11 +1239,59 @@ const static struct rt_device_ops rndis_device_ops = #endif /* RT_USING_LWIP */ #ifdef RNDIS_DELAY_LINK_UP + +/** + * This function will set rndis connect status. + * + * @param device the usb device object. + * @param status the connect status. + * + * @return RT_EOK on successful. + */ +static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) +{ + rndis_indicate_status_msg_t resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; + resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ + resp->Status = status; + resp->StatusBufferLength = 0; + resp->StatusBufferOffset = 0; + + response->buffer = resp; + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + _rndis_response_available(func); + + return RT_EOK; +} + /* the delay linkup timer handler. */ static void timer_timeout(void* parameter) { - RNDIS_PRINTF("delay link up!\r\n"); - _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->parent.parent.user_data, + LOG_I("delay link up!"); + _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->func, RNDIS_STATUS_MEDIA_CONNECT); eth_device_linkchange(&((rt_rndis_eth_t)parameter)->parent, RT_TRUE); } @@ -1319,7 +1391,7 @@ ufunction_t rt_usbd_function_rndis_create(udevice_t device) timer_timeout, _rndis, RT_TICK_PER_SECOND * 2, - RT_TIMER_FLAG_ONE_SHOT); + RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); #endif /* RNDIS_DELAY_LINK_UP */ /* OUI 00-00-00, only for test. */ @@ -1372,4 +1444,6 @@ int rt_usbd_rndis_class_register(void) rt_usbd_class_register(&rndis_class); return 0; } -INIT_PREV_EXPORT(rt_usbd_rndis_class_register);
\ No newline at end of file +INIT_PREV_EXPORT(rt_usbd_rndis_class_register); + +#endif /* RT_USB_DEVICE_RNDIS */ diff --git a/components/drivers/usb/usbdevice/class/rndis.h b/components/drivers/usb/usbdevice/class/rndis.h index 000ea62baf..fcdd249984 100644 --- a/components/drivers/usb/usbdevice/class/rndis.h +++ b/components/drivers/usb/usbdevice/class/rndis.h @@ -180,6 +180,15 @@ struct rndis_reset_msg rt_uint32_t Reserved; }; +/* Remote NDIS Soft Reset Response */ +struct rndis_reset_cmplt +{ + rt_uint32_t MessageType; + rt_uint32_t MessageLength; + rt_uint32_t Status; + rt_uint32_t AddressingReset; +}; + /* Remote NDIS Indicate Status Message */ struct rndis_indicate_status_msg { diff --git a/components/drivers/usb/usbdevice/class/winusb.c b/components/drivers/usb/usbdevice/class/winusb.c index bf4b353d73..729e39f663 100644 --- a/components/drivers/usb/usbdevice/class/winusb.c +++ b/components/drivers/usb/usbdevice/class/winusb.c @@ -121,7 +121,7 @@ const static char* _ustring[] = ALIGN(4) struct usb_os_proerty winusb_proerty[] = { - USB_OS_PROERTY_DESC(USB_OS_PROERTY_TYPE_REG_SZ,"DeviceInterfaceGUID",RT_WINUSB_GUID), + USB_OS_PROPERTY_DESC(USB_OS_PROPERTY_TYPE_REG_SZ,"DeviceInterfaceGUID",RT_WINUSB_GUID), }; ALIGN(4) diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/usbdevice_core.c index fb850d6d2b..ef569d7bf2 100644 --- a/components/drivers/usb/usbdevice/core/core.c +++ b/components/drivers/usb/usbdevice/core/usbdevice_core.c @@ -194,7 +194,18 @@ static rt_err_t _get_descriptor(struct udevice* device, ureq_t setup) _get_string_descriptor(device, setup); break; case USB_DESC_TYPE_DEVICEQUALIFIER: - _get_qualifier_descriptor(device, setup); + /* If a full-speed only device (with a device descriptor version number equal to 0200H) receives a + GetDescriptor() request for a device_qualifier, it must respond with a request error. The host must not make + a request for an other_speed_configuration descriptor unless it first successfully retrieves the + device_qualifier descriptor. */ + if(device->dcd->device_is_hs) + { + _get_qualifier_descriptor(device, setup); + } + else + { + rt_usbd_ep0_set_stall(device); + } break; case USB_DESC_TYPE_OTHERSPEED: _get_config_descriptor(device, setup); @@ -226,7 +237,8 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) { rt_uint8_t value; uintf_t intf; - + ufunction_t func; + /* parameter check */ RT_ASSERT(device != RT_NULL); RT_ASSERT(setup != RT_NULL); @@ -240,12 +252,17 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) } /* find the specified interface and its alternate setting */ - intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, RT_NULL); + intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, &func); value = intf->curr_setting->intf_desc->bAlternateSetting; /* send the interface alternate setting to endpoint 0*/ rt_usbd_ep0_write(device, &value, 1); + if (intf->handler) + { + intf->handler(func, setup); + } + return RT_EOK; } @@ -259,6 +276,7 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) */ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) { + ufunction_t func; uintf_t intf; uep_t ep; struct rt_list_node* i; @@ -277,7 +295,7 @@ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) } /* find the specified interface */ - intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, RT_NULL); + intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, &func); /* set alternate setting to the interface */ rt_usbd_set_altsetting(intf, setup->wValue & 0xFF); @@ -292,6 +310,11 @@ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) } dcd_ep0_send_status(device->dcd); + if (intf->handler) + { + intf->handler(func, setup); + } + return RT_EOK; } @@ -984,10 +1007,10 @@ udevice_t rt_usbd_device_new(void) RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_new\n")); /* allocate memory for the object */ - udevice = rt_malloc(sizeof(struct udevice)); + udevice = (udevice_t)rt_malloc(sizeof(struct udevice)); if(udevice == RT_NULL) { - rt_kprintf("alloc memery failed\n"); + rt_kprintf("alloc memory failed\n"); return RT_NULL; } rt_memset(udevice, 0, sizeof(struct udevice)); @@ -1098,10 +1121,10 @@ uconfig_t rt_usbd_config_new(void) RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_new\n")); /* allocate memory for the object */ - cfg = rt_malloc(sizeof(struct uconfig)); + cfg = (uconfig_t)rt_malloc(sizeof(struct uconfig)); if(cfg == RT_NULL) { - rt_kprintf("alloc memery failed\n"); + rt_kprintf("alloc memory failed\n"); return RT_NULL; } rt_memset(cfg, 0, sizeof(struct uconfig)); @@ -1140,7 +1163,7 @@ uintf_t rt_usbd_interface_new(udevice_t device, uintf_handler_t handler) intf = (uintf_t)rt_malloc(sizeof(struct uinterface)); if(intf == RT_NULL) { - rt_kprintf("alloc memery failed\n"); + rt_kprintf("alloc memory failed\n"); return RT_NULL; } intf->intf_num = device->nr_intf; @@ -1175,14 +1198,14 @@ ualtsetting_t rt_usbd_altsetting_new(rt_size_t desc_size) setting = (ualtsetting_t)rt_malloc(sizeof(struct ualtsetting)); if(setting == RT_NULL) { - rt_kprintf("alloc memery failed\n"); + rt_kprintf("alloc memory failed\n"); return RT_NULL; } /* allocate memory for the desc */ setting->desc = rt_malloc(desc_size); if (setting->desc == RT_NULL) { - rt_kprintf("alloc desc memery failed\n"); + rt_kprintf("alloc desc memory failed\n"); rt_free(setting); return RT_NULL; } @@ -1240,7 +1263,7 @@ ufunction_t rt_usbd_function_new(udevice_t device, udev_desc_t dev_desc, func = (ufunction_t)rt_malloc(sizeof(struct ufunction)); if(func == RT_NULL) { - rt_kprintf("alloc memery failed\n"); + rt_kprintf("alloc memory failed\n"); return RT_NULL; } func->dev_desc = dev_desc; @@ -1275,7 +1298,7 @@ uep_t rt_usbd_endpoint_new(uep_desc_t ep_desc, udep_handler_t handler) ep = (uep_t)rt_malloc(sizeof(struct uendpoint)); if(ep == RT_NULL) { - rt_kprintf("alloc memery failed\n"); + rt_kprintf("alloc memory failed\n"); return RT_NULL; } ep->ep_desc = ep_desc; @@ -1477,9 +1500,10 @@ uep_t rt_usbd_find_endpoint(udevice_t device, ufunction_t* pfunc, rt_uint8_t ep_ */ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) { - struct rt_list_node *i, *j, *k; + struct rt_list_node *i, *j, *k, *m; ufunction_t func; uintf_t intf; + ualtsetting_t altsetting; uep_t ep; RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n")); @@ -1501,22 +1525,26 @@ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) intf = (uintf_t)rt_list_entry(j, struct uinterface, list); cfg->cfg_desc.bNumInterfaces++; - /* allocate address for every endpoint in the interface alternate setting */ - for(k=intf->curr_setting->ep_list.next; - k!=&intf->curr_setting->ep_list; k=k->next) + for(k=intf->setting_list.next; k!=&intf->setting_list;k=k->next) { - ep = (uep_t)rt_list_entry(k, struct uendpoint, list); - if(rt_usbd_ep_assign(device, ep) != RT_EOK) + altsetting = (ualtsetting_t)rt_list_entry(k, struct ualtsetting, list); + + /* allocate address for every endpoint in the interface alternate setting */ + for(m=altsetting->ep_list.next; m!=&altsetting->ep_list; m=m->next) { - rt_kprintf("endpoint assign error\n"); + ep = (uep_t)rt_list_entry(m, struct uendpoint, list); + if(rt_usbd_ep_assign(device, ep) != RT_EOK) + { + rt_kprintf("endpoint assign error\n"); + } } - } - /* construct complete configuration descriptor */ - rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG], - (void*)intf->curr_setting->desc, - intf->curr_setting->desc_size); - cfg->cfg_desc.wTotalLength += intf->curr_setting->desc_size; + /* construct complete configuration descriptor */ + rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG], + (void*)altsetting->desc, + altsetting->desc_size); + cfg->cfg_desc.wTotalLength += altsetting->desc_size; + } } } @@ -2042,7 +2070,7 @@ rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size) ep0 = &device->dcd->ep0; ep0->request.size = size; - ep0->request.buffer = buffer; + ep0->request.buffer = (rt_uint8_t *)buffer; ep0->request.remain_size = size; if(size >= ep0->id->maxpacket) { @@ -2068,7 +2096,7 @@ rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size, RT_ASSERT(buffer != RT_NULL); ep0 = &device->dcd->ep0; - ep0->request.buffer = buffer; + ep0->request.buffer = (rt_uint8_t *)buffer; ep0->request.remain_size = size; ep0->rx_indicate = rx_ind; if(size >= ep0->id->maxpacket) @@ -2176,7 +2204,7 @@ static struct rt_thread usb_thread; #define USBD_MQ_MAX_MSG 16 /* internal of the message queue: every message is associated with a pointer, * so in order to recveive USBD_MQ_MAX_MSG messages, we have to allocate more - * than USBD_MQ_MSG_SZ*USBD_MQ_MAX_MSG memery. */ + * than USBD_MQ_MSG_SZ*USBD_MQ_MAX_MSG memory. */ static rt_uint8_t usb_mq_pool[(USBD_MQ_MSG_SZ+sizeof(void*))*USBD_MQ_MAX_MSG]; /** diff --git a/components/drivers/usb/usbhost/SConscript b/components/drivers/usb/usbhost/SConscript index b12adfc5ad..081c732819 100644 --- a/components/drivers/usb/usbhost/SConscript +++ b/components/drivers/usb/usbhost/SConscript @@ -3,7 +3,7 @@ from building import * cwd = GetCurrentDir() src = Split(""" -core/core.c +core/usbhost_core.c core/driver.c core/usbhost.c core/hub.c diff --git a/components/drivers/usb/usbhost/class/adk.h b/components/drivers/usb/usbhost/class/adk.h index 041d47c674..c582ad7f17 100644 --- a/components/drivers/usb/usbhost/class/adk.h +++ b/components/drivers/usb/usbhost/class/adk.h @@ -8,8 +8,8 @@ * 2011-12-12 Yi Qiu first version */ -#ifndef __HID_H__ -#define __HID_H__ +#ifndef __ADK_H__ +#define __ADK_H__ #include <rtthread.h> diff --git a/components/drivers/usb/usbhost/class/udisk.c b/components/drivers/usb/usbhost/class/udisk.c index 1509a26105..6c8030b29a 100644 --- a/components/drivers/usb/usbhost/class/udisk.c +++ b/components/drivers/usb/usbhost/class/udisk.c @@ -186,7 +186,7 @@ rt_err_t rt_udisk_run(struct uhintf* intf) { int i = 0; rt_err_t ret; - char dname[4]; + char dname[8]; char sname[8]; rt_uint8_t max_lun, *sector, sense[18], inquiry[36]; struct dfs_partition part[MAX_PARTITION_COUNT]; diff --git a/components/drivers/usb/usbhost/core/hub.c b/components/drivers/usb/usbhost/core/hub.c index 80ed9b4e3f..eefa571472 100644 --- a/components/drivers/usb/usbhost/core/hub.c +++ b/components/drivers/usb/usbhost/core/hub.c @@ -417,8 +417,13 @@ static rt_err_t rt_usbh_hub_port_change(uhub_t hub) if(reconnect) { - if(hub->child[i] != RT_NULL && hub->child[i]->status != DEV_STATUS_IDLE) + if(hub->child[i] != RT_NULL && hub->child[i]->status != DEV_STATUS_IDLE) + { rt_usbh_detach_instance(hub->child[i]); + + /* Child device have been detach. Set hub->child[i] to NULL. */ + hub->child[i] = RT_NULL; + } ret = rt_usbh_hub_port_debounce(hub, i + 1); if(ret != RT_EOK) continue; @@ -508,6 +513,7 @@ static rt_err_t rt_usbh_hub_enable(void *arg) /* create a hub instance */ hub = rt_malloc(sizeof(struct uhub)); + RT_ASSERT(hub != RT_NULL); rt_memset(hub, 0, sizeof(struct uhub)); /* make interface instance's user data point to hub instance */ @@ -531,7 +537,12 @@ static rt_err_t rt_usbh_hub_enable(void *arg) } /* get hub ports number */ - hub->num_ports = hub->hub_desc.num_ports; + /* If hub device supported ports over USB_HUB_PORT_NUM(Ex: 8 port hub). Set hub->num_ports to USB_HUB_PORT_NUM */ + if(hub->hub_desc.num_ports > USB_HUB_PORT_NUM) + hub->num_ports = USB_HUB_PORT_NUM; + else + hub->num_ports = hub->hub_desc.num_ports; + hub->hcd = device->hcd; hub->self = device; @@ -606,7 +617,6 @@ static rt_err_t rt_usbh_hub_disable(void* arg) } if(hub != RT_NULL) rt_free(hub); - if(intf != RT_NULL) rt_free(intf); return RT_EOK; } diff --git a/components/drivers/usb/usbhost/core/core.c b/components/drivers/usb/usbhost/core/usbhost_core.c index 71341a33c3..d72dca82f2 100644 --- a/components/drivers/usb/usbhost/core/core.c +++ b/components/drivers/usb/usbhost/core/usbhost_core.c @@ -162,6 +162,10 @@ rt_err_t rt_usbh_attatch_instance(uinst_t device) /* alloc memory for configuration descriptor */ device->cfg_desc = (ucfg_desc_t)rt_malloc(cfg_desc.wTotalLength); + if(device->cfg_desc == RT_NULL) + { + return RT_ENOMEM; + } rt_memset(device->cfg_desc, 0, cfg_desc.wTotalLength); /* get full configuration descriptor */ @@ -219,6 +223,10 @@ rt_err_t rt_usbh_attatch_instance(uinst_t device) { /* allocate memory for interface device */ device->intf[i] = (struct uhintf*)rt_malloc(sizeof(struct uhintf)); + if(device->intf[i] == RT_NULL) + { + return RT_ENOMEM; + } device->intf[i]->drv = drv; device->intf[i]->device = device; device->intf[i]->intf_desc = intf_desc; diff --git a/components/drivers/watchdog/watchdog.c b/components/drivers/watchdog/watchdog.c index 196f02039d..09a6bf4fad 100644 --- a/components/drivers/watchdog/watchdog.c +++ b/components/drivers/watchdog/watchdog.c @@ -14,7 +14,7 @@ /* RT-Thread Device Interface */ /* - * This function initializes serial + * This function initializes watchdog */ static rt_err_t rt_watchdog_init(struct rt_device *dev) { diff --git a/components/drivers/wlan/SConscript b/components/drivers/wlan/SConscript index 271ca66a80..f2a6bbdc82 100644 --- a/components/drivers/wlan/SConscript +++ b/components/drivers/wlan/SConscript @@ -1,8 +1,30 @@ from building import * cwd = GetCurrentDir() -src = Glob('*.c') CPPPATH = [cwd] + +src = Split(''' + wlan_dev.c + ''') + +if GetDepend(['RT_WLAN_MANAGE_ENABLE']): + src += ['wlan_mgnt.c'] + +if GetDepend(['RT_WLAN_MSH_CMD_ENABLE']): + src += ['wlan_cmd.c'] + +if GetDepend(['RT_WLAN_PROT_ENABLE']): + src += ['wlan_prot.c'] + +if GetDepend(['RT_WLAN_PROT_LWIP_ENABLE']): + src += ['wlan_lwip.c'] + +if GetDepend(['RT_WLAN_CFG_ENABLE']): + src += ['wlan_cfg.c'] + +if GetDepend(['RT_WLAN_WORK_THREAD_ENABLE']): + src += ['wlan_workqueue.c'] + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_WIFI'], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/wlan/wlan_cfg.c b/components/drivers/wlan/wlan_cfg.c index 27da9bc24e..7fa9ecb2da 100644 --- a/components/drivers/wlan/wlan_cfg.c +++ b/components/drivers/wlan/wlan_cfg.c @@ -11,16 +11,16 @@ #include <rtthread.h> #include <wlan_cfg.h> -#define DBG_ENABLE +#define DBG_TAG "WLAN.cfg" #ifdef RT_WLAN_CFG_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_SECTION_NAME "WLAN.cfg" -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_WLAN_CFG_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_CFG_ENABLE + #define WLAN_CFG_LOCK() (rt_mutex_take(&cfg_mutex, RT_WAITING_FOREVER)) #define WLAN_CFG_UNLOCK() (rt_mutex_release(&cfg_mutex)) @@ -57,9 +57,12 @@ static rt_uint16_t rt_wlan_cal_crc(rt_uint8_t *buff, int len) while (len--) { + int i; + wChar = *(buff++); wCRCin ^= (wChar << 8); - for (int i = 0; i < 8; i++) + + for (i = 0; i < 8; i++) { if (wCRCin & 0x8000) wCRCin = (wCRCin << 1) ^ wCPoly; @@ -461,3 +464,5 @@ void rt_wlan_cfg_dump(void) rt_kprintf("%3d \n", info->channel); } } + +#endif diff --git a/components/drivers/wlan/wlan_cmd.c b/components/drivers/wlan/wlan_cmd.c index b962b63947..fead6a8bf2 100644 --- a/components/drivers/wlan/wlan_cmd.c +++ b/components/drivers/wlan/wlan_cmd.c @@ -13,6 +13,8 @@ #include <wlan_cfg.h> #include <wlan_prot.h> +#if defined(RT_WLAN_MANAGE_ENABLE) && defined(RT_WLAN_MSH_CMD_ENABLE) + struct wifi_cmd_des { const char *cmd; @@ -75,7 +77,7 @@ static int wifi_help(int argc, char *argv[]) { rt_kprintf("wifi\n"); rt_kprintf("wifi help\n"); - rt_kprintf("wifi scan\n"); + rt_kprintf("wifi scan [SSID]\n"); rt_kprintf("wifi join [SSID] [PASSWORD]\n"); rt_kprintf("wifi ap SSID [PASSWORD]\n"); rt_kprintf("wifi disc\n"); @@ -143,12 +145,23 @@ static int wifi_status(int argc, char *argv[]) static int wifi_scan(int argc, char *argv[]) { struct rt_wlan_scan_result *scan_result = RT_NULL; + struct rt_wlan_info *info = RT_NULL; + struct rt_wlan_info filter; - if (argc > 2) + if (argc > 3) return -1; + if (argc == 3) + { + INVALID_INFO(&filter); + SSID_SET(&filter, argv[2]); + info = &filter; + } + + /* clean scan result */ + rt_wlan_scan_result_clean(); /* scan ap info */ - scan_result = rt_wlan_scan_sync(); + scan_result = rt_wlan_scan_with_info(info); if (scan_result) { int index, num; @@ -224,8 +237,10 @@ static int wifi_join(int argc, char *argv[]) const char *key = RT_NULL; struct rt_wlan_cfg_info cfg_info; + rt_memset(&cfg_info, 0, sizeof(cfg_info)); if (argc == 2) { +#ifdef RT_WLAN_CFG_ENABLE /* get info to connect */ if (rt_wlan_cfg_read_index(&cfg_info, 0) == 1) { @@ -234,8 +249,9 @@ static int wifi_join(int argc, char *argv[]) key = (char *)(&cfg_info.key.val[0]); } else +#endif { - rt_kprintf("not find info\n"); + rt_kprintf("not find connect info\n"); } } else if (argc == 3) @@ -387,8 +403,9 @@ static int wifi_debug_save_cfg(int argc, char *argv[]) rt_memcpy(&cfg_info.key.val[0], password, len); cfg_info.key.len = len; } - +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_save(&cfg_info); +#endif return 0; } @@ -396,7 +413,9 @@ static int wifi_debug_dump_cfg(int argc, char *argv[]) { if (argc == 1) { +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_dump(); +#endif } else { @@ -409,8 +428,10 @@ static int wifi_debug_clear_cfg(int argc, char *argv[]) { if (argc == 1) { +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_delete_all(); rt_wlan_cfg_cache_save(); +#endif } else { @@ -447,6 +468,10 @@ static int wifi_debug_set_mode(int argc, char *argv[]) { mode = RT_WLAN_AP; } + else if (rt_strcmp("none", argv[1]) == 0) + { + mode = RT_WLAN_NONE; + } else return -1; @@ -564,3 +589,5 @@ static int wifi_msh(int argc, char *argv[]) #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) FINSH_FUNCTION_EXPORT_ALIAS(wifi_msh, __cmd_wifi, wifi command.); #endif + +#endif diff --git a/components/drivers/wlan/wlan_dev.c b/components/drivers/wlan/wlan_dev.c index 387f65fde2..53b6138e99 100644 --- a/components/drivers/wlan/wlan_dev.c +++ b/components/drivers/wlan/wlan_dev.c @@ -13,16 +13,16 @@ #include <wlan_dev.h> #include <wlan_prot.h> -#define DBG_ENABLE +#define DBG_TAG "WLAN.dev" #ifdef RT_WLAN_DEV_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_SECTION_NAME "WLAN.dev" -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_WLAN_DEV_DEBUG */ #include <rtdbg.h> +#if defined(RT_USING_WIFI) || defined(RT_USING_WLAN) + #ifndef RT_DEVICE #define RT_DEVICE(__device) ((rt_device_t)__device) #endif @@ -58,6 +58,17 @@ rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode) return -RT_ERROR; } + if (mode == RT_WLAN_AP && device->flags & RT_WLAN_FLAG_STA_ONLY) + { + LOG_E("F:%s L:%d This wlan device can only be set to sta mode!", __FUNCTION__, __LINE__); + return -RT_ERROR; + } + else if (mode == RT_WLAN_STATION && device->flags & RT_WLAN_FLAG_AP_ONLY) + { + LOG_E("F:%s L:%d This wlan device can only be set to ap mode!", __FUNCTION__, __LINE__); + return -RT_ERROR; + } + result = rt_device_init(RT_DEVICE(device)); if (result != RT_EOK) { @@ -91,7 +102,7 @@ rt_err_t rt_wlan_dev_connect(struct rt_wlan_device *device, struct rt_wlan_info if ((password_len > RT_WLAN_PASSWORD_MAX_LENGTH) || (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH)) { - LOG_E("L:%d password or ssid is to long", __LINE__); + LOG_E("L:%d password or ssid is too long", __LINE__); return -RT_ERROR; } rt_memset(&sta_info, 0, sizeof(struct rt_sta_info)); @@ -136,16 +147,19 @@ rt_err_t rt_wlan_dev_ap_start(struct rt_wlan_device *device, struct rt_wlan_info return -RT_ERROR; } - if ((password_len >= RT_WLAN_PASSWORD_MAX_LENGTH) || - (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH)) + if ((password_len > RT_WLAN_PASSWORD_MAX_LENGTH) || + (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH)) { - LOG_E("L:%d password or ssid is to long", __LINE__); + LOG_E("L:%d password or ssid is too long", __LINE__); return -RT_ERROR; } rt_memset(&ap_info, 0, sizeof(struct rt_ap_info)); rt_memcpy(&ap_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t)); - rt_memcpy(ap_info.key.val, password, password_len); + if (password != RT_NULL) + { + rt_memcpy(ap_info.key.val, password, password_len); + } ap_info.key.len = password_len; ap_info.hidden = info->hidden; ap_info.channel = info->channel; @@ -184,13 +198,21 @@ rt_err_t rt_wlan_dev_ap_deauth(struct rt_wlan_device *device, rt_uint8_t mac[6]) int rt_wlan_dev_get_rssi(struct rt_wlan_device *device) { int rssi = 0; + rt_err_t result = RT_EOK; if (device == RT_NULL) { - return -RT_EIO; + rt_set_errno(-RT_EIO); + return 0; + } + + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_RSSI, &rssi); + if (result != RT_EOK) + { + rt_set_errno(result); + return 0; } - rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_RSSI, &rssi); return rssi; } @@ -235,14 +257,20 @@ rt_err_t rt_wlan_dev_set_powersave(struct rt_wlan_device *device, int level) int rt_wlan_dev_get_powersave(struct rt_wlan_device *device) { - int level = 0; + int level = -1; + rt_err_t result = RT_EOK; if (device == RT_NULL) { + rt_set_errno(-RT_EIO); return -1; } - rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_POWERSAVE, &level); + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_POWERSAVE, &level); + if (result != RT_EOK) + { + rt_set_errno(result); + } return level; } @@ -432,19 +460,21 @@ rt_err_t rt_wlan_dev_set_channel(struct rt_wlan_device *device, int channel) return result; } -rt_err_t rt_wlan_dev_get_channel(struct rt_wlan_device *device) +int rt_wlan_dev_get_channel(struct rt_wlan_device *device) { rt_err_t result = RT_EOK; - int channel; + int channel = -1; if (device == RT_NULL) { - return -RT_EIO; + rt_set_errno(-RT_EIO); + return -1; } result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_CHANNEL, &channel); if (result != RT_EOK) { + rt_set_errno(result); return -1; } @@ -466,17 +496,19 @@ rt_err_t rt_wlan_dev_set_country(struct rt_wlan_device *device, rt_country_code_ rt_country_code_t rt_wlan_dev_get_country(struct rt_wlan_device *device) { - int result = 0; + int result = RT_EOK; rt_country_code_t country_code = RT_COUNTRY_UNKNOWN; if (device == RT_NULL) { - return country_code; + rt_set_errno(-RT_EIO); + return RT_COUNTRY_UNKNOWN; } result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_GET_COUNTRY, &country_code); if (result != RT_EOK) { + rt_set_errno(result); return RT_COUNTRY_UNKNOWN; } @@ -496,15 +528,24 @@ rt_err_t rt_wlan_dev_scan(struct rt_wlan_device *device, struct rt_wlan_info *in if (info != RT_NULL) { - if (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH) + if (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH) { - LOG_E("L:%d ssid is to long", __LINE__); + LOG_E("L:%d ssid is too long", __LINE__); return -RT_EINVAL; } rt_memcpy(&scan_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t)); rt_memcpy(scan_info.bssid, info->bssid, RT_WLAN_BSSID_MAX_LENGTH); - scan_info.channel_min = -1; - scan_info.channel_max = -1; + if (info->channel > 0) + { + scan_info.channel_min = info->channel; + scan_info.channel_max = info->channel; + } + else + { + scan_info.channel_min = -1; + scan_info.channel_max = -1; + } + scan_info.passive = info->hidden ? RT_TRUE : RT_FALSE; p_scan_info = &scan_info; } result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SCAN, p_scan_info); @@ -526,7 +567,82 @@ rt_err_t rt_wlan_dev_scan_stop(struct rt_wlan_device *device) rt_err_t rt_wlan_dev_report_data(struct rt_wlan_device *device, void *buff, int len) { +#ifdef RT_WLAN_PROT_ENABLE return rt_wlan_dev_transfer_prot(device, buff, len); +#else + return -RT_ERROR; +#endif +} + +rt_err_t rt_wlan_dev_enter_mgnt_filter(struct rt_wlan_device *device) +{ + rt_err_t result = RT_EOK; + int enable = 1; + + if (device == RT_NULL) + { + return -RT_EIO; + } + + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_CFG_MGNT_FILTER, &enable); + return result; +} + +rt_err_t rt_wlan_dev_exit_mgnt_filter(struct rt_wlan_device *device) +{ + rt_err_t result = RT_EOK; + int enable = 0; + + if (device == RT_NULL) + { + return -RT_EIO; + } + + result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_CFG_MGNT_FILTER, &enable); + return result; +} + +rt_err_t rt_wlan_dev_set_mgnt_filter_callback(struct rt_wlan_device *device, rt_wlan_mgnt_filter_callback_t callback) +{ + if (device == RT_NULL) + { + return -RT_EIO; + } + device->mgnt_filter_callback = callback; + + return RT_EOK; +} + +void rt_wlan_dev_mgnt_filter_handler(struct rt_wlan_device *device, void *data, int len) +{ + rt_wlan_mgnt_filter_callback_t callback; + + if (device == RT_NULL) + { + return; + } + + callback = device->mgnt_filter_callback; + + if (callback != RT_NULL) + { + callback(device, data, len); + } +} + +int rt_wlan_dev_send_raw_frame(struct rt_wlan_device *device, void *buff, int len) +{ + if (device == RT_NULL) + { + return -RT_EIO; + } + + if (device->ops->wlan_send_raw_frame) + { + return device->ops->wlan_send_raw_frame(device, buff, len); + } + + return -RT_ERROR; } static rt_err_t _rt_wlan_dev_init(rt_device_t dev) @@ -641,7 +757,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) 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); + err = wlan->ops->wlan_set_powersave(wlan, level); break; } case RT_WLAN_CMD_GET_POWERSAVE: @@ -659,7 +775,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_CFG_PROMISC, "RT_WLAN_CMD_CFG_PROMISC"); if (wlan->ops->wlan_cfg_promisc) - wlan->ops->wlan_cfg_promisc(wlan, start); + err = wlan->ops->wlan_cfg_promisc(wlan, start); break; } case RT_WLAN_CMD_CFG_FILTER: @@ -668,7 +784,16 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_CFG_FILTER, "RT_WLAN_CMD_CFG_FILTER"); if (wlan->ops->wlan_cfg_filter) - wlan->ops->wlan_cfg_filter(wlan, filter); + err = wlan->ops->wlan_cfg_filter(wlan, filter); + break; + } + case RT_WLAN_CMD_CFG_MGNT_FILTER: + { + rt_bool_t start = *((rt_bool_t *)args); + + LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_CFG_MGNT_FILTER, "RT_WLAN_CMD_CFG_MGNT_FILTER"); + if (wlan->ops->wlan_cfg_mgnt_filter) + err = wlan->ops->wlan_cfg_mgnt_filter(wlan, start); break; } case RT_WLAN_CMD_SET_CHANNEL: @@ -676,7 +801,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) int channel = *(int *)args; LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SET_CHANNEL, "RT_WLAN_CMD_SET_CHANNEL"); if (wlan->ops->wlan_set_channel) - wlan->ops->wlan_set_channel(wlan, channel); + err = wlan->ops->wlan_set_channel(wlan, channel); break; } case RT_WLAN_CMD_GET_CHANNEL: @@ -694,7 +819,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SET_COUNTRY, "RT_WLAN_CMD_SET_COUNTRY"); if (wlan->ops->wlan_set_country) - wlan->ops->wlan_set_country(wlan, country); + err = wlan->ops->wlan_set_country(wlan, country); break; } case RT_WLAN_CMD_GET_COUNTRY: @@ -711,7 +836,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_SET_MAC, "RT_WLAN_CMD_SET_MAC"); if (wlan->ops->wlan_set_mac) - wlan->ops->wlan_set_mac(wlan, mac); + err = wlan->ops->wlan_set_mac(wlan, mac); break; } case RT_WLAN_CMD_GET_MAC: @@ -720,7 +845,7 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) LOG_D("%s %d cmd[%d]:%s run......", __FUNCTION__, __LINE__, RT_WLAN_CMD_GET_MAC, "RT_WLAN_CMD_GET_MAC"); if (wlan->ops->wlan_get_mac) - wlan->ops->wlan_get_mac(wlan, mac); + err = wlan->ops->wlan_get_mac(wlan, mac); break; } default: @@ -733,11 +858,24 @@ static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args) return err; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops wlan_ops = +{ + _rt_wlan_dev_init, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + _rt_wlan_dev_control +}; +#endif + rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, const struct rt_wlan_dev_ops *ops, rt_uint32_t flag, void *user_data) { rt_err_t err = RT_EOK; - if ((wlan == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL)) + if ((wlan == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL) || + (flag & RT_WLAN_FLAG_STA_ONLY && flag & RT_WLAN_FLAG_AP_ONLY)) { LOG_E("F:%s L:%d parameter Wrongful", __FUNCTION__, __LINE__); return RT_NULL; @@ -745,12 +883,17 @@ rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, con rt_memset(wlan, 0, sizeof(struct rt_wlan_device)); +#ifdef RT_USING_DEVICE_OPS + wlan->device.ops = &wlan_ops; +#else wlan->device.init = _rt_wlan_dev_init; wlan->device.open = RT_NULL; wlan->device.close = RT_NULL; wlan->device.read = RT_NULL; wlan->device.write = RT_NULL; wlan->device.control = _rt_wlan_dev_control; +#endif + wlan->device.user_data = RT_NULL; wlan->device.type = RT_Device_Class_NetIf; @@ -765,3 +908,5 @@ rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, con return err; } + +#endif diff --git a/components/drivers/wlan/wlan_dev.h b/components/drivers/wlan/wlan_dev.h index e3f0d3dc61..3019afb19d 100644 --- a/components/drivers/wlan/wlan_dev.h +++ b/components/drivers/wlan/wlan_dev.h @@ -37,7 +37,8 @@ typedef enum RT_WLAN_CMD_SET_POWERSAVE, RT_WLAN_CMD_GET_POWERSAVE, RT_WLAN_CMD_CFG_PROMISC, /* start/stop minitor */ - RT_WLAN_CMD_CFG_FILTER, + RT_WLAN_CMD_CFG_FILTER, /* start/stop frame filter */ + RT_WLAN_CMD_CFG_MGNT_FILTER, /* start/stop management frame filter */ RT_WLAN_CMD_SET_CHANNEL, RT_WLAN_CMD_GET_CHANNEL, RT_WLAN_CMD_SET_COUNTRY, @@ -360,6 +361,8 @@ typedef void (*rt_wlan_dev_event_handler)(struct rt_wlan_device *device, rt_wlan typedef void (*rt_wlan_pormisc_callback_t)(struct rt_wlan_device *device, void *data, int len); +typedef void (*rt_wlan_mgnt_filter_callback_t)(struct rt_wlan_device *device, void *data, int len); + struct rt_wlan_ssid { rt_uint8_t len; @@ -381,6 +384,11 @@ typedef struct rt_wlan_key rt_wlan_key_t; (_info)->channel = -1; \ } while(0) +#define SSID_SET(_info, _ssid) do { \ + rt_strncpy((char *)(_info)->ssid.val, (_ssid), RT_WLAN_SSID_MAX_LENGTH); \ + (_info)->ssid.len = rt_strlen((char *)(_info)->ssid.val); \ + } while(0) + struct rt_wlan_info { /* security type */ @@ -440,8 +448,10 @@ struct rt_wlan_device struct rt_mutex lock; struct rt_wlan_dev_event_desc handler_table[RT_WLAN_DEV_EVT_MAX][RT_WLAN_DEV_EVENT_NUM]; rt_wlan_pormisc_callback_t pormisc_callback; + rt_wlan_mgnt_filter_callback_t mgnt_filter_callback; const struct rt_wlan_dev_ops *ops; rt_uint32_t flags; + struct netdev *netdev; void *prot; void *user_data; }; @@ -470,6 +480,7 @@ struct rt_scan_info rt_uint8_t bssid[6]; rt_int16_t channel_min; rt_int16_t channel_max; + rt_bool_t passive; }; struct rt_wlan_dev_ops @@ -488,6 +499,7 @@ struct rt_wlan_dev_ops int (*wlan_get_powersave)(struct rt_wlan_device *wlan); rt_err_t (*wlan_cfg_promisc)(struct rt_wlan_device *wlan, rt_bool_t start); rt_err_t (*wlan_cfg_filter)(struct rt_wlan_device *wlan, struct rt_wlan_filter *filter); + rt_err_t (*wlan_cfg_mgnt_filter)(struct rt_wlan_device *wlan, rt_bool_t start); rt_err_t (*wlan_set_channel)(struct rt_wlan_device *wlan, int channel); int (*wlan_get_channel)(struct rt_wlan_device *wlan); rt_err_t (*wlan_set_country)(struct rt_wlan_device *wlan, rt_country_code_t country_code); @@ -496,6 +508,7 @@ struct rt_wlan_dev_ops rt_err_t (*wlan_get_mac)(struct rt_wlan_device *wlan, rt_uint8_t mac[]); int (*wlan_recv)(struct rt_wlan_device *wlan, void *buff, int len); int (*wlan_send)(struct rt_wlan_device *wlan, void *buff, int len); + int (*wlan_send_raw_frame)(struct rt_wlan_device *wlan, void *buff, int len); }; /* @@ -559,7 +572,7 @@ rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_fi * wlan device channel interface */ rt_err_t rt_wlan_dev_set_channel(struct rt_wlan_device *device, int channel); -rt_err_t rt_wlan_dev_get_channel(struct rt_wlan_device *device); +int rt_wlan_dev_get_channel(struct rt_wlan_device *device); /* * wlan device country interface diff --git a/components/drivers/wlan/wlan_lwip.c b/components/drivers/wlan/wlan_lwip.c index ec6ca23845..3c4e4dd598 100644 --- a/components/drivers/wlan/wlan_lwip.c +++ b/components/drivers/wlan/wlan_lwip.c @@ -14,27 +14,34 @@ #include <wlan_prot.h> #include <wlan_workqueue.h> +#if defined(RT_WLAN_PROT_ENABLE) && defined(RT_WLAN_PROT_LWIP_ENABLE) + #ifdef RT_USING_LWIP #include <netif/ethernetif.h> #include <lwip/netifapi.h> #ifdef LWIP_USING_DHCPD #include <dhcp_server.h> #endif +#ifdef RT_USING_NETDEV +#include <netdev.h> +#endif -#define DBG_ENABLE +#define DBG_TAG "WLAN.lwip" #ifdef RT_WLAN_LWIP_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_SECTION_NAME "WLAN.lwip" -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_WLAN_LWIP_DEBUG */ #include <rtdbg.h> #ifndef IPADDR_STRLEN_MAX #define IPADDR_STRLEN_MAX (32) #endif +#ifndef RT_WLAN_PROT_LWIP_NAME +#define RT_WLAN_PROT_LWIP_NAME ("lwip") +#endif + struct lwip_prot_des { struct rt_wlan_prot prot; @@ -49,12 +56,16 @@ static void netif_is_ready(struct rt_work *work, void *parameter) ip_addr_t ip_addr_zero = { 0 }; struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; - struct eth_device *eth_dev = &lwip_prot->eth; + struct eth_device *eth_dev; rt_base_t level; struct rt_wlan_buff buff; rt_uint32_t ip_addr[4]; char str[IPADDR_STRLEN_MAX]; + if (lwip_prot == RT_NULL) + return; + + eth_dev = &lwip_prot->eth; rt_timer_stop(&lwip_prot->timer); if (ip_addr_cmp(&(eth_dev->netif->ip_addr), &ip_addr_zero) != 0) { @@ -102,18 +113,26 @@ static void netif_is_ready(struct rt_work *work, void *parameter) LOG_I("Got IP address : %s", str); exit: level = rt_hw_interrupt_disable(); - rt_memset(work, 0, sizeof(struct rt_work)); + if (work) + { + rt_memset(work, 0, sizeof(struct rt_work)); + } rt_hw_interrupt_enable(level); } static void timer_callback(void *parameter) { +#ifdef RT_WLAN_WORK_THREAD_ENABLE struct rt_workqueue *workqueue; struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; - struct rt_work *work = &lwip_prot->work; + struct rt_work *work; rt_base_t level; + if (lwip_prot == RT_NULL) + return; + + work = &lwip_prot->work; workqueue = rt_wlan_get_workqueue(); if (workqueue != RT_NULL) { @@ -127,13 +146,22 @@ static void timer_callback(void *parameter) rt_hw_interrupt_enable(level); } } +#else + netif_is_ready(RT_NULL, parameter); +#endif + } static void netif_set_connected(void *parameter) { struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = wlan->prot; - struct eth_device *eth_dev = &lwip_prot->eth; + struct eth_device *eth_dev; + + if (lwip_prot == RT_NULL) + return; + + eth_dev = &lwip_prot->eth; if (lwip_prot->connected_flag) { @@ -153,14 +181,10 @@ static void netif_set_connected(void *parameter) netifapi_netif_common(eth_dev->netif, netif_set_link_up, NULL); #ifdef LWIP_USING_DHCPD { - char netif_name[8]; - int i; + char netif_name[RT_NAME_MAX]; rt_memset(netif_name, 0, sizeof(netif_name)); - for (i = 0; i < sizeof(eth_dev->netif->name); i++) - { - netif_name[i] = eth_dev->netif->name[i]; - } + rt_memcpy(netif_name, eth_dev->netif->name, sizeof(eth_dev->netif->name)); dhcpd_start(netif_name); } #endif @@ -168,24 +192,24 @@ static void netif_set_connected(void *parameter) } else { - if (wlan->mode == RT_WLAN_STATION) - { - LOG_D("F:%s L:%d dhcp stop run", __FUNCTION__, __LINE__); - netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + LOG_D("F:%s L:%d set linkdown", __FUNCTION__, __LINE__); + netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + rt_timer_stop(&lwip_prot->timer); #ifdef RT_LWIP_DHCP - { - ip_addr_t ip_addr = { 0 }; - dhcp_stop(eth_dev->netif); - netif_set_addr(eth_dev->netif, &ip_addr, &ip_addr, &ip_addr); - } -#endif - rt_timer_stop(&lwip_prot->timer); + { + ip_addr_t ip_addr = { 0 }; + dhcp_stop(eth_dev->netif); + netif_set_addr(eth_dev->netif, &ip_addr, &ip_addr, &ip_addr); } - else if (wlan->mode == RT_WLAN_AP) +#endif +#ifdef LWIP_USING_DHCPD { - LOG_D("F:%s L:%d dhcpd stop run", __FUNCTION__, __LINE__); - netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + char netif_name[RT_NAME_MAX]; + rt_memset(netif_name, 0, sizeof(netif_name)); + rt_memcpy(netif_name, lwip_prot->eth.netif->name, sizeof(lwip_prot->eth.netif->name)); + dhcpd_stop(netif_name); } +#endif } } @@ -194,6 +218,9 @@ static void rt_wlan_lwip_event_handle(struct rt_wlan_prot *port, struct rt_wlan_ struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; rt_bool_t flag_old; + if (lwip_prot == RT_NULL) + return; + flag_old = lwip_prot->connected_flag; switch (event) @@ -240,8 +267,11 @@ static void rt_wlan_lwip_event_handle(struct rt_wlan_prot *port, struct rt_wlan_ } if (flag_old != lwip_prot->connected_flag) { +#ifdef RT_WLAN_WORK_THREAD_ENABLE rt_wlan_workqueue_dowork(netif_set_connected, wlan); - // netif_set_connected(wlan); +#else + netif_set_connected(wlan); +#endif } } @@ -372,10 +402,22 @@ static rt_err_t rt_wlan_lwip_protocol_send(rt_device_t device, struct pbuf *p) #endif } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops wlan_lwip_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + rt_wlan_lwip_protocol_control +}; +#endif + static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan) { struct eth_device *eth = RT_NULL; - static rt_uint8_t id = 0; + rt_uint8_t id = 0; char eth_name[4], timer_name[16]; rt_device_t device = RT_NULL; struct lwip_prot_des *lwip_prot; @@ -417,12 +459,18 @@ static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot * rt_memset(lwip_prot, 0, sizeof(struct lwip_prot_des)); eth = &lwip_prot->eth; + +#ifdef RT_USING_DEVICE_OPS + eth->parent.ops = &wlan_lwip_ops; +#else eth->parent.init = RT_NULL; eth->parent.open = RT_NULL; eth->parent.close = RT_NULL; eth->parent.read = RT_NULL; eth->parent.write = RT_NULL; eth->parent.control = rt_wlan_lwip_protocol_control; +#endif + eth->parent.user_data = wlan; eth->eth_rx = RT_NULL; eth->eth_tx = rt_wlan_lwip_protocol_send; @@ -436,22 +484,43 @@ static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot * return RT_NULL; } rt_memcpy(&lwip_prot->prot, prot, sizeof(struct rt_wlan_prot)); - if (wlan->mode == RT_WLAN_STATION) - { - rt_sprintf(timer_name, "timer_%s", eth_name); - rt_timer_init(&lwip_prot->timer, timer_name, timer_callback, wlan, rt_tick_from_millisecond(1000), - RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT); - } + rt_sprintf(timer_name, "timer_%s", eth_name); + rt_timer_init(&lwip_prot->timer, timer_name, timer_callback, wlan, rt_tick_from_millisecond(1000), + RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT); netif_set_up(eth->netif); LOG_I("eth device init ok name:%s", eth_name); - +#ifdef RT_USING_NETDEV + wlan->netdev = netdev_get_by_name(eth_name); +#endif return &lwip_prot->prot; } static void rt_wlan_lwip_protocol_unregister(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan) { - /*TODO*/ + struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)prot; + LOG_D("F:%s L:%d is run wlan:0x%08x", __FUNCTION__, __LINE__, wlan); +#if !defined(RT_USING_LWIP141) + wlan->prot = RT_NULL; + if (lwip_prot == RT_NULL) + { + return; + } + +#ifdef LWIP_USING_DHCPD + { + char netif_name[RT_NAME_MAX]; + rt_memset(netif_name, 0, sizeof(netif_name)); + rt_memcpy(netif_name, lwip_prot->eth.netif->name, sizeof(lwip_prot->eth.netif->name)); + dhcpd_stop(netif_name); + } +#endif + eth_device_deinit(&lwip_prot->eth); + rt_device_close((rt_device_t)wlan); + rt_timer_detach(&lwip_prot->timer); + wlan->netdev = RT_NULL; + rt_free(lwip_prot); +#endif } static struct rt_wlan_prot_ops ops = @@ -467,7 +536,7 @@ int rt_wlan_lwip_init(void) rt_wlan_prot_event_t event; rt_memset(&prot, 0, sizeof(prot)); - rt_strncpy(&prot.name[0], RT_WLAN_PROT_LWIP, RT_WLAN_PROT_NAME_LEN); + rt_strncpy(&prot.name[0], RT_WLAN_PROT_LWIP_NAME, RT_WLAN_PROT_NAME_LEN); prot.ops = &ops; if (rt_wlan_prot_regisetr(&prot) != RT_EOK) @@ -486,3 +555,4 @@ int rt_wlan_lwip_init(void) INIT_PREV_EXPORT(rt_wlan_lwip_init); #endif +#endif diff --git a/components/drivers/wlan/wlan_mgnt.c b/components/drivers/wlan/wlan_mgnt.c index 1d0b0c4aa7..fefe700acc 100644 --- a/components/drivers/wlan/wlan_mgnt.c +++ b/components/drivers/wlan/wlan_mgnt.c @@ -16,16 +16,16 @@ #include <wlan_prot.h> #include <wlan_workqueue.h> -#define DBG_ENABLE +#define DBG_TAG "WLAN.mgnt" #ifdef RT_WLAN_MGNT_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_SECTION_NAME "WLAN.mgnt" -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_WLAN_MGNT_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_MANAGE_ENABLE + #ifndef RT_WLAN_DEVICE #define RT_WLAN_DEVICE(__device) ((struct rt_wlan_device *)__device) #endif @@ -50,13 +50,16 @@ #define COMPLETE_LOCK() (rt_mutex_take(&complete_mutex, RT_WAITING_FOREVER)) #define COMPLETE_UNLOCK() (rt_mutex_release(&complete_mutex)) +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE #define TIME_STOP() (rt_timer_stop(&reconnect_time)) #define TIME_START() (rt_timer_start(&reconnect_time)) - -#define DISCONNECT_RESPONSE_TICK (2000) +#else +#define TIME_STOP() +#define TIME_START() +#endif #if RT_WLAN_EBOX_NUM < 1 -#error "event box num Too little" +#error "event box num Too few" #endif struct rt_wlan_mgnt_des @@ -115,8 +118,11 @@ static struct rt_wlan_event_desc event_tab[RT_WLAN_EVT_MAX]; static struct rt_wlan_complete_des *complete_tab[5]; static struct rt_mutex complete_mutex; +static struct rt_wlan_info *scan_filter; +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE static struct rt_timer reconnect_time; +#endif rt_inline int _sta_is_null(void) { @@ -147,9 +153,97 @@ rt_inline rt_bool_t _is_do_connect(void) return RT_TRUE; } -static void rt_wlan_mgnt_work(void *parameter); +#ifdef RT_WLAN_WORK_THREAD_ENABLE + +static rt_bool_t rt_wlan_info_isequ(struct rt_wlan_info *info1, struct rt_wlan_info *info2) +{ + rt_bool_t is_equ = 1; + rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 }; + + if (is_equ && (info1->security != SECURITY_UNKNOWN) && (info2->security != SECURITY_UNKNOWN)) + { + is_equ &= info2->security == info1->security; + } + if (is_equ && ((info1->ssid.len > 0) && (info2->ssid.len > 0))) + { + is_equ &= info1->ssid.len == info2->ssid.len; + is_equ &= rt_memcmp(&info2->ssid.val[0], &info1->ssid.val[0], info1->ssid.len) == 0; + } + if (is_equ && (rt_memcmp(&info1->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH)) && + (rt_memcmp(&info2->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH))) + { + is_equ &= rt_memcmp(&info1->bssid[0], &info2->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0; + } + if (is_equ && info1->datarate && info2->datarate) + { + is_equ &= info1->datarate == info2->datarate; + } + if (is_equ && (info1->channel >= 0) && (info2->channel >= 0)) + { + is_equ &= info1->channel == info2->channel; + } + if (is_equ && (info1->rssi < 0) && (info2->rssi < 0)) + { + is_equ &= info1->rssi == info2->rssi; + } + return is_equ; +} + +static void rt_wlan_mgnt_work(void *parameter) +{ + struct rt_wlan_msg *msg = parameter; + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + struct rt_wlan_buff user_buff = { 0 }; + rt_base_t level; + + /* Get user callback */ + if (msg->event < RT_WLAN_EVT_MAX) + { + level = rt_hw_interrupt_disable(); + handler = event_tab[msg->event].handler; + user_parameter = event_tab[msg->event].parameter; + rt_hw_interrupt_enable(level); + } + + /* run user callback fun */ + if (handler) + { + user_buff.data = msg->buff; + user_buff.len = msg->len; + RT_WLAN_LOG_D("wlan work thread run user callback, event:%d", msg->event); + handler(msg->event, &user_buff, user_parameter); + } + + switch (msg->event) + { + case RT_WLAN_EVT_STA_CONNECTED: + { + struct rt_wlan_cfg_info cfg_info; + + rt_memset(&cfg_info, 0, sizeof(cfg_info)); + /* save config */ + if (rt_wlan_is_connected() == RT_TRUE) + { + rt_enter_critical(); + cfg_info.info = _sta_mgnt.info; + cfg_info.key = _sta_mgnt.key; + rt_exit_critical(); + RT_WLAN_LOG_D("run save config! ssid:%s len%d", _sta_mgnt.info.ssid.val, _sta_mgnt.info.ssid.len); +#ifdef RT_WLAN_CFG_ENABLE + rt_wlan_cfg_save(&cfg_info); +#endif + } + break; + } + default : + break; + } + + rt_free(msg); +} -static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) +static rt_err_t rt_wlan_send_to_thread(rt_wlan_event_t event, void *buff, int len) { struct rt_wlan_msg *msg; @@ -166,7 +260,8 @@ static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) msg->event = event; if (len != 0) { - msg->buff = ((char *)msg) + sizeof(struct rt_wlan_msg); + msg->buff = (void *)&msg[1]; + rt_memcpy(msg->buff, buff, len); msg->len = len; } @@ -179,14 +274,16 @@ static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) } return RT_EOK; } +#endif static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout) { struct rt_wlan_info *ptable; rt_err_t err = RT_EOK; int i, insert = -1; + rt_base_t level; - if (_sta_is_null() || (info == RT_NULL)) return RT_EOK; + if (_sta_is_null() || (info == RT_NULL) || (info->ssid.len == 0)) return RT_EOK; RT_WLAN_LOG_D("ssid:%s len:%d mac:%02x:%02x:%02x:%02x:%02x:%02x", info->ssid.val, info->ssid.len, info->bssid[0], info->bssid[1], info->bssid[2], info->bssid[3], info->bssid[4], info->bssid[5]); @@ -195,6 +292,23 @@ static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout if (err != RT_EOK) return err; + /* scanning result filtering */ + level = rt_hw_interrupt_disable(); + if (scan_filter) + { + struct rt_wlan_info _tmp_info = *scan_filter; + rt_hw_interrupt_enable(level); + if (rt_wlan_info_isequ(&_tmp_info, info) != RT_TRUE) + { + rt_mutex_release(&scan_result_mutex); + return RT_EOK; + } + } + else + { + rt_hw_interrupt_enable(level); + } + /* de-duplicatio */ for (i = 0; i < scan_result.num; i++) { @@ -383,7 +497,7 @@ static rt_err_t rt_wlan_sta_info_del_all(int timeout) sta_info.node = RT_NULL; return err; } - +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter) { static rt_uint32_t id = 0; @@ -415,12 +529,12 @@ static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter) if (id >= rt_wlan_cfg_get_num()) id = 0; - if ((cfg_info.key.len > 0) && (cfg_info.key.len < RT_WLAN_PASSWORD_MAX_LENGTH)) + if ((cfg_info.key.len > 0) && (cfg_info.key.len <= RT_WLAN_PASSWORD_MAX_LENGTH)) { cfg_info.key.val[cfg_info.key.len] = '\0'; password = (char *)(&cfg_info.key.val[0]); } - rt_wlan_connect_adv(&cfg_info.info, password); + rt_wlan_connect((char *)cfg_info.info.ssid.val, password); exit: rt_mutex_release(&mgnt_mutex); level = rt_hw_interrupt_disable(); @@ -451,41 +565,10 @@ static void rt_wlan_cyclic_check(void *parameter) } } } - -static void rt_wlan_mgnt_work(void *parameter) -{ - struct rt_wlan_msg *msg = parameter; - - switch (msg->event) - { - case RT_WLAN_DEV_EVT_CONNECT: - { - struct rt_wlan_cfg_info cfg_info; - - /* save config */ - if (rt_wlan_is_connected() == RT_TRUE) - { - rt_enter_critical(); - cfg_info.info = _sta_mgnt.info; - cfg_info.key = _sta_mgnt.key; - rt_exit_critical(); - RT_WLAN_LOG_D("run save config! ssid:%s len%d", _sta_mgnt.info.ssid.val, _sta_mgnt.info.ssid.len); - rt_wlan_cfg_save(&cfg_info); - } - break; - } - default : - break; - } - - rt_free(msg); -} +#endif static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter) { - rt_base_t level; - void *user_parameter; - rt_wlan_event_handler handler = RT_NULL; rt_err_t err = RT_NULL; rt_wlan_event_t user_event = RT_WLAN_EVT_MAX; int i; @@ -505,7 +588,6 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECTING; user_event = RT_WLAN_EVT_STA_CONNECTED; TIME_STOP(); - rt_wlan_send_msg(event, RT_NULL, 0); user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); RT_WLAN_LOG_I("wifi connect success ssid:%s", &_sta_mgnt.info.ssid.val[0]); @@ -520,7 +602,10 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev user_event = RT_WLAN_EVT_STA_CONNECTED_FAIL; user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); - TIME_START(); + if (rt_wlan_get_autoreconnect_mode()) + { + TIME_START(); + } break; } case RT_WLAN_DEV_EVT_DISCONNECT: @@ -531,7 +616,10 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev user_event = RT_WLAN_EVT_STA_DISCONNECTED; user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); - TIME_START(); + if (rt_wlan_get_autoreconnect_mode()) + { + TIME_START(); + } break; } case RT_WLAN_DEV_EVT_AP_START: @@ -624,20 +712,30 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev } } COMPLETE_UNLOCK(); - /* Get user callback */ - if (user_event < RT_WLAN_EVT_MAX) +#ifdef RT_WLAN_WORK_THREAD_ENABLE + rt_wlan_send_to_thread(user_event, user_buff.data, user_buff.len); +#else { - level = rt_hw_interrupt_disable(); - handler = event_tab[user_event].handler; - user_parameter = event_tab[user_event].parameter; - rt_hw_interrupt_enable(level); - } + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + rt_base_t level; + /* Get user callback */ + if (user_event < RT_WLAN_EVT_MAX) + { + level = rt_hw_interrupt_disable(); + handler = event_tab[user_event].handler; + user_parameter = event_tab[user_event].parameter; + rt_hw_interrupt_enable(level); + } - /* run user callback fun */ - if (handler) - { - handler(user_event, &user_buff, user_parameter); + /* run user callback fun */ + if (handler) + { + RT_WLAN_LOG_D("unknown thread run user callback, event:%d", user_event); + handler(user_event, &user_buff, user_parameter); + } } +#endif } static struct rt_wlan_complete_des *rt_wlan_complete_create(const char *name) @@ -822,14 +920,30 @@ rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode) /* update dev event handle */ if (up_event_flag == 1) { - rt_wlan_dev_event_t event; - for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event++) + if (handler) { - if (handler) + if (mode == RT_WLAN_STATION) { - rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), event, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_CONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_CONNECT_FAIL, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_DISCONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_SCAN_REPORT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_SCAN_DONE, handler, RT_NULL); } - else + else if (mode == RT_WLAN_AP) + { + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_START, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_STOP, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_ASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_DISASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_ASSOCIATE_FAILED, handler, RT_NULL); + } + } + else + { + rt_wlan_dev_event_t event; + handler = rt_wlan_event_dispatch; + for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event++) { rt_wlan_dev_unregister_event_handler(RT_WLAN_DEVICE(device), event, handler); } @@ -838,8 +952,11 @@ rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode) MGNT_UNLOCK(); /* Mount protocol */ -#ifdef RT_WLAN_DEFAULT_PROT - rt_wlan_prot_attach(dev_name, RT_WLAN_DEFAULT_PROT); +#if defined(RT_WLAN_PROT_ENABLE) && defined(RT_WLAN_DEFAULT_PROT) + if (err == RT_EOK) + { + rt_wlan_prot_attach(dev_name, RT_WLAN_DEFAULT_PROT); + } #endif return err; } @@ -934,6 +1051,7 @@ rt_err_t rt_wlan_connect(const char *ssid, const char *password) struct rt_wlan_info info; struct rt_wlan_complete_des *complete; rt_uint32_t set = 0, recved = 0; + rt_uint32_t scan_retry = RT_WLAN_SCAN_RETRY_CNT; /* sta dev Can't be NULL */ if (_sta_is_null()) @@ -962,12 +1080,11 @@ rt_err_t rt_wlan_connect(const char *ssid, const char *password) /* get info from cache */ INVALID_INFO(&info); MGNT_LOCK(); - if (rt_wlan_find_best_by_cache(ssid, &info) != RT_TRUE) + while (scan_retry-- && rt_wlan_find_best_by_cache(ssid, &info) != RT_TRUE) { rt_wlan_scan_sync(); - rt_wlan_find_best_by_cache(ssid, &info); - rt_wlan_scan_result_clean(); } + rt_wlan_scan_result_clean(); if (info.ssid.len <= 0) { @@ -1218,10 +1335,13 @@ rt_err_t rt_wlan_get_info(struct rt_wlan_info *info) } RT_WLAN_LOG_D("%s is run", __FUNCTION__); - rt_enter_critical(); - *info = _sta_mgnt.info; - rt_exit_critical(); - return RT_EOK; + if (rt_wlan_is_connected() == RT_TRUE) + { + *info = _sta_mgnt.info; + info->rssi = rt_wlan_get_rssi(); + return RT_EOK; + } + return -RT_ERROR; } int rt_wlan_get_rssi(void) @@ -1270,6 +1390,7 @@ rt_err_t rt_wlan_start_ap(const char *ssid, const char *password) rt_memcpy(&info.ssid.val, ssid, ssid_len); info.ssid.len = ssid_len; info.channel = 6; + info.band = RT_802_11_BAND_2_4GHZ; /* Initializing events that need to wait */ MGNT_LOCK(); @@ -1320,7 +1441,10 @@ rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password) return -RT_EIO; } RT_WLAN_LOG_D("%s is run", __FUNCTION__); - password_len = rt_strlen(password); + if (password != RT_NULL) + { + password_len = rt_strlen(password); + } if (password_len > RT_WLAN_PASSWORD_MAX_LENGTH) { RT_WLAN_LOG_E("key is to long! len:%d", password_len); @@ -1358,16 +1482,16 @@ rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password) return err; } -int rt_wlan_ap_is_active(void) +rt_bool_t rt_wlan_ap_is_active(void) { - int _active = 0; + rt_bool_t _active = RT_FALSE; if (_ap_is_null()) { - return 0; + return RT_FALSE; } - _active = _ap_mgnt.state & RT_WLAN_STATE_ACTIVE ? 1 : 0; + _active = _ap_mgnt.state & RT_WLAN_STATE_ACTIVE ? RT_TRUE : RT_FALSE; RT_WLAN_LOG_D("%s is run active:%s", __FUNCTION__, _active ? "Active" : "Inactive"); return _active; } @@ -1426,8 +1550,12 @@ rt_err_t rt_wlan_ap_get_info(struct rt_wlan_info *info) } RT_WLAN_LOG_D("%s is run", __FUNCTION__); - *info = _ap_mgnt.info; - return RT_EOK; + if (rt_wlan_ap_is_active() == RT_TRUE) + { + *info = _ap_mgnt.info; + return RT_EOK; + } + return -RT_ERROR; } /* get sta number */ @@ -1554,27 +1682,35 @@ rt_country_code_t rt_wlan_ap_get_country(void) void rt_wlan_config_autoreconnect(rt_bool_t enable) { +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable); MGNT_LOCK(); if (enable) { + TIME_START(); _sta_mgnt.flags |= RT_WLAN_STATE_AUTOEN; } else { + TIME_STOP(); _sta_mgnt.flags &= ~RT_WLAN_STATE_AUTOEN; } MGNT_UNLOCK(); +#endif } rt_bool_t rt_wlan_get_autoreconnect_mode(void) { +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE rt_bool_t enable = 0; enable = _sta_mgnt.flags & RT_WLAN_STATE_AUTOEN ? 1 : 0; RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable); return enable; +#else + return RT_FALSE; +#endif } /* Call the underlying scan function, which is asynchronous. @@ -1611,6 +1747,9 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) rt_err_t err = RT_EOK; struct rt_wlan_complete_des *complete; rt_uint32_t set = 0, recved = 0; + static struct rt_wlan_info scan_filter_info; + rt_base_t level; + struct rt_wlan_scan_result *result; if (_sta_is_null()) { @@ -1632,14 +1771,23 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) return &scan_result; } + /* add scan info filter */ + if (info) + { + scan_filter_info = *info; + level = rt_hw_interrupt_disable(); + scan_filter = &scan_filter_info; + rt_hw_interrupt_enable(level); + } + /* run scan */ err = rt_wlan_dev_scan(STA_DEVICE(), info); if (err != RT_EOK) { rt_wlan_complete_delete(complete); RT_WLAN_LOG_E("scan sync fail"); - MGNT_UNLOCK(); - return RT_NULL; + result = RT_NULL; + goto scan_exit; } /* Initializing events that need to wait */ @@ -1652,12 +1800,17 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) if (!(recved & set)) { RT_WLAN_LOG_E("scan wait timeout!"); - MGNT_UNLOCK(); - return &scan_result; + result = &scan_result; + goto scan_exit; } +scan_exit: MGNT_UNLOCK(); - return &scan_result; + level = rt_hw_interrupt_disable(); + scan_filter = RT_NULL; + rt_hw_interrupt_enable(level); + result = &scan_result; + return result; } int rt_wlan_scan_get_info_num(void) @@ -1708,8 +1861,7 @@ int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_ { int i = 0, count = 0; struct rt_wlan_info *scan_info; - rt_bool_t is_equ = 1; - rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 }; + rt_bool_t is_equ; if ((out_info == RT_NULL) || (info == RT_NULL) || (num <= 0)) { @@ -1720,31 +1872,7 @@ int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_ for (i = 0; (i < scan_result.num) && (count < num); i++) { scan_info = &scan_result.info[i]; - - if (is_equ && (info->security != SECURITY_UNKNOWN)) - { - is_equ &= info->security == scan_info->security; - } - if (is_equ && ((info->ssid.len > 0) && (info->ssid.len == scan_info->ssid.len))) - { - is_equ &= rt_memcmp(&info->ssid.val[0], &scan_info->ssid.val[0], scan_info->ssid.len) == 0; - } - if (is_equ && (rt_memcmp(&info->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH))) - { - is_equ &= rt_memcmp(&info->bssid[0], &scan_info->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0; - } - if (is_equ && info->datarate) - { - is_equ &= info->datarate == scan_info->datarate; - } - if (is_equ && (info->channel >= 0)) - { - is_equ &= info->channel == scan_info->channel; - } - if (is_equ && (info->rssi < 0)) - { - is_equ &= info->rssi == scan_info->rssi; - } + is_equ = rt_wlan_info_isequ(scan_info, info); /* Determine whether to find */ if (is_equ) { @@ -1797,7 +1925,7 @@ rt_err_t rt_wlan_register_event_handler(rt_wlan_event_t event, rt_wlan_event_han } RT_WLAN_LOG_D("%s is run event:%d", __FUNCTION__, event); - MGNT_UNLOCK(); + MGNT_LOCK(); /* Registering Callbacks */ level = rt_hw_interrupt_disable(); event_tab[event].handler = handler; @@ -1839,8 +1967,6 @@ void rt_wlan_mgnt_unlock(void) int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff) { rt_base_t level; - void *user_parameter; - rt_wlan_event_handler handler = RT_NULL; if ((wlan == RT_NULL) || (_sta_mgnt.device != wlan) || (!(_sta_mgnt.state & RT_WLAN_STATE_CONNECT))) @@ -1853,13 +1979,24 @@ int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *b } level = rt_hw_interrupt_disable(); _sta_mgnt.state |= RT_WLAN_STATE_READY; - handler = event_tab[RT_WLAN_EVT_READY].handler; - user_parameter = event_tab[RT_WLAN_EVT_READY].parameter; rt_hw_interrupt_enable(level); - if (handler) +#ifdef RT_WLAN_WORK_THREAD_ENABLE + rt_wlan_send_to_thread(RT_WLAN_EVT_READY, buff->data, buff->len); +#else { - handler(RT_WLAN_EVT_READY, buff, user_parameter); + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + + level = rt_hw_interrupt_disable(); + handler = event_tab[RT_WLAN_EVT_READY].handler; + user_parameter = event_tab[RT_WLAN_EVT_READY].parameter; + rt_hw_interrupt_enable(level); + if (handler) + { + handler(RT_WLAN_EVT_READY, buff, user_parameter); + } } +#endif return 0; } @@ -1878,10 +2015,15 @@ int rt_wlan_init(void) rt_mutex_init(&scan_result_mutex, "scan", RT_IPC_FLAG_FIFO); rt_mutex_init(&sta_info_mutex, "sta", RT_IPC_FLAG_FIFO); rt_mutex_init(&complete_mutex, "complete", RT_IPC_FLAG_FIFO); - rt_timer_init(&reconnect_time, "wifi_tim", rt_wlan_cyclic_check, RT_NULL, DISCONNECT_RESPONSE_TICK, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); - rt_timer_start(&reconnect_time); +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE + rt_timer_init(&reconnect_time, "wifi_tim", rt_wlan_cyclic_check, RT_NULL, + rt_tick_from_millisecond(AUTO_CONNECTION_PERIOD_MS), + RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); +#endif _init_flag = 1; } return 0; } INIT_PREV_EXPORT(rt_wlan_init); + +#endif diff --git a/components/drivers/wlan/wlan_mgnt.h b/components/drivers/wlan/wlan_mgnt.h index d11d9ee347..df0827bb7b 100644 --- a/components/drivers/wlan/wlan_mgnt.h +++ b/components/drivers/wlan/wlan_mgnt.h @@ -37,6 +37,14 @@ extern "C" { #define RT_WLAN_EBOX_NUM (10) #endif +#ifndef RT_WLAN_SCAN_RETRY_CNT +#define RT_WLAN_SCAN_RETRY_CNT (3) +#endif + +#ifndef AUTO_CONNECTION_PERIOD_MS +#define AUTO_CONNECTION_PERIOD_MS (2000) +#endif + /*state fot station*/ #define RT_WLAN_STATE_CONNECT (1UL << 0) #define RT_WLAN_STATE_CONNECTING (1UL << 1) @@ -97,7 +105,7 @@ int rt_wlan_get_rssi(void); */ rt_err_t rt_wlan_start_ap(const char *ssid, const char *password); rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password); -int rt_wlan_ap_is_active(void); +rt_bool_t rt_wlan_ap_is_active(void); rt_err_t rt_wlan_ap_stop(void); rt_err_t rt_wlan_ap_get_info(struct rt_wlan_info *info); int rt_wlan_ap_get_sta_num(void); diff --git a/components/drivers/wlan/wlan_prot.c b/components/drivers/wlan/wlan_prot.c index ec5e419bc4..b1a1b5de99 100644 --- a/components/drivers/wlan/wlan_prot.c +++ b/components/drivers/wlan/wlan_prot.c @@ -13,16 +13,16 @@ #include <wlan_dev.h> #include <wlan_prot.h> -#define DBG_ENABLE +#define DBG_TAG "WLAN.prot" #ifdef RT_WLAN_PROT_DEBUG -#define DBG_LEVEL DBG_LOG +#define DBG_LVL DBG_LOG #else -#define DBG_LEVEL DBG_INFO -#endif -#define DBG_SECTION_NAME "WLAN.prot" -#define DBG_COLOR +#define DBG_LVL DBG_INFO +#endif /* RT_WLAN_PROT_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_PROT_ENABLE + #if RT_WLAN_PROT_NAME_LEN < 4 #error "The name is too short" #endif @@ -162,7 +162,7 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n { int i = 0; struct rt_wlan_prot *prot = wlan->prot; - rt_wlan_dev_event_t event; + rt_wlan_dev_event_handler handler = rt_wlan_prot_event_handle; if (wlan == RT_NULL) { @@ -182,7 +182,7 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n rt_wlan_prot_detach_dev(wlan); #ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE - if (rt_strcmp(RT_WLAN_PROT_LWIP, prot_name) != 0) + if (rt_strcmp(RT_WLAN_PROT_LWIP_NAME, prot_name) != 0) { return -RT_ERROR; } @@ -204,13 +204,12 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n return -RT_ERROR; } - for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event ++) - { - if (rt_wlan_dev_register_event_handler(wlan, event, rt_wlan_prot_event_handle, RT_NULL) != RT_EOK) - { - LOG_E("prot register event filed:%d", event); - } - } + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_CONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_DISCONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_START, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_STOP, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_ASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_DISASSOCIATED, handler, RT_NULL); return RT_EOK; } @@ -362,3 +361,4 @@ void rt_wlan_prot_dump(void) } } } +#endif diff --git a/components/drivers/wlan/wlan_prot.h b/components/drivers/wlan/wlan_prot.h index 34c5bae7fd..2df979270f 100644 --- a/components/drivers/wlan/wlan_prot.h +++ b/components/drivers/wlan/wlan_prot.h @@ -25,8 +25,6 @@ extern "C" { #define RT_LWAN_ID_PREFIX (0x5054) -#define RT_WLAN_PROT_LWIP ("lwip") - typedef enum { RT_WLAN_PROT_EVT_INIT_DONE = 0, diff --git a/components/drivers/wlan/wlan_workqueue.c b/components/drivers/wlan/wlan_workqueue.c index f65ac95d08..4cd98346d2 100644 --- a/components/drivers/wlan/wlan_workqueue.c +++ b/components/drivers/wlan/wlan_workqueue.c @@ -13,12 +13,12 @@ #include <wlan_workqueue.h> #include <ipc/workqueue.h> -#define DBG_ENABLE -#define DBG_LEVEL DBG_INFO -#define DBG_SECTION_NAME "WLAN.work" -#define DBG_COLOR +#define DBG_TAG "WLAN.work" +#define DBG_LVL DBG_INFO #include <rtdbg.h> +#ifdef RT_WLAN_WORK_THREAD_ENABLE + struct rt_wlan_work { struct rt_work work; @@ -97,3 +97,5 @@ int rt_wlan_workqueue_init(void) return 0; } INIT_PREV_EXPORT(rt_wlan_workqueue_init); + +#endif |
