diff options
| author | bernard <[email protected]> | 2017-09-29 10:23:56 +0800 |
|---|---|---|
| committer | bernard <[email protected]> | 2017-09-29 10:23:56 +0800 |
| commit | cccff34fcac04f34233a33e453f2d0ec255bf231 (patch) | |
| tree | d406036f73296b27f3cb96e77ede98dd7803c61d /components | |
| parent | e9a77b513f0a4b37d539a030592a61b08d03602d (diff) | |
| parent | 3691b67e83ab57196dfc62606b1be18db76994a7 (diff) | |
Merge branch 'master' of https://github.com/RT-Thread/rt-thread
Diffstat (limited to 'components')
42 files changed, 1726 insertions, 989 deletions
diff --git a/components/cplusplus/crt_init.c b/components/cplusplus/crt_init.c index ebcc4af37d..12c92dc6fb 100755 --- a/components/cplusplus/crt_init.c +++ b/components/cplusplus/crt_init.c @@ -44,11 +44,11 @@ void _fini() { } -WEAK void *__dso_handle = 0; +RT_WEAK void *__dso_handle = 0; #endif -WEAK +RT_WEAK int cplusplus_system_init(void) { #if defined(__GNUC__) && !defined(__CC_ARM) diff --git a/components/dfs/filesystems/romfs/romfs.c b/components/dfs/filesystems/romfs/romfs.c index ff4b353059..a571c36ec6 100644 --- a/components/dfs/filesystems/romfs/romfs.c +++ b/components/dfs/filesystems/romfs/romfs.c @@ -39,13 +39,13 @@ const static unsigned char _dummy_txt[] = 0x74,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x61,0x20,0x66,0x69,0x6c,0x65,0x21,0x0d,0x0a, }; -const struct romfs_dirent WEAK _root_dirent[] = +const struct romfs_dirent RT_WEAK _root_dirent[] = { {ROMFS_DIRENT_DIR, "dummy", (rt_uint8_t *)_dummy, sizeof(_dummy)/sizeof(_dummy[0])}, {ROMFS_DIRENT_FILE, "dummy.txt", _dummy_txt, sizeof(_dummy_txt)}, }; -const struct romfs_dirent WEAK romfs_root = +const struct romfs_dirent RT_WEAK romfs_root = { ROMFS_DIRENT_DIR, "/", (rt_uint8_t *)_root_dirent, sizeof(_root_dirent)/sizeof(_root_dirent[0]) }; diff --git a/components/drivers/audio/audio.c b/components/drivers/audio/audio.c index 3476d06412..0b2f9a0cdd 100644 --- a/components/drivers/audio/audio.c +++ b/components/drivers/audio/audio.c @@ -1,8 +1,25 @@ /* - * audio.c + * File : audio.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team * - * Created on: 2016��10��19�� - * Author: Urey + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017-05-09 Urey first version */ #include <stdio.h> @@ -19,383 +36,70 @@ #define AUDIO_DBG(...) #endif - -rt_err_t _audio_queue_init(struct rt_audio_queue *queue, rt_uint16_t size, rt_uint16_t lwm) +static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio) { - RT_ASSERT(queue != RT_NULL); - - queue->count = 0; - queue->size = size; - queue->lwm = lwm; - queue->waiting_lwm = RT_FALSE; - - queue->get_index = 0; - queue->put_index = 0; + rt_err_t result = RT_EOK; + rt_base_t level; + struct rt_audio_frame frame; - rt_list_init(&(queue->suspended_push_list)); - rt_list_init(&(queue->suspended_pop_list)); + RT_ASSERT(audio != RT_NULL); - queue->queue = (struct rt_audio_frame *)rt_malloc(sizeof(struct rt_audio_frame) * size); - if (queue->queue == RT_NULL) + //check repaly queue is empty + if (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) != RT_EOK) { - return -RT_ENOMEM; - } - - return RT_EOK; -} - -rt_err_t _audio_queue_push(struct rt_audio_queue *queue, struct rt_audio_frame *frame, rt_int32_t timeout) -{ - rt_ubase_t level; - rt_thread_t thread; - rt_err_t result; - - RT_ASSERT(queue != RT_NULL); - - result = RT_EOK; - thread = rt_thread_self(); - - AUDIO_DBG("%s count = %d\n",__func__,queue->count); - - level = rt_hw_interrupt_disable(); - while(queue->count == queue->size) - {// audio queue is full - queue->waiting_lwm = RT_TRUE; - - /* queue is full */ - if (timeout == 0) - { - result = -RT_ETIMEOUT; - goto __exit; - } + AUDIO_DBG("TX queue is empty\n"); + result = -RT_EEMPTY; - /* current context checking */ - RT_DEBUG_NOT_IN_INTERRUPT; - - /* reset thread error number */ - thread->error = RT_EOK; - - /* suspend thread on the push list */ - rt_thread_suspend(thread); - rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist)); - /* start timer */ - if (timeout > 0) - { - /* reset the timeout of thread timer and start it */ - rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout); - rt_timer_start(&(thread->thread_timer)); - } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - - /* do schedule */ - rt_schedule(); - - /* thread is waked up */ - result = thread->error; level = rt_hw_interrupt_disable(); - if (result != RT_EOK) goto __exit; - } - - queue->queue[queue->put_index].data_ptr = frame->data_ptr; - queue->queue[queue->put_index].data_size = frame->data_size; - queue->queue[queue->put_index].data_ofs = frame->data_ofs; - queue->put_index = (queue->put_index + 1) % queue->size; - queue->count ++; - - if (!rt_list_isempty(&(queue->suspended_pop_list))) - { - /* there is at least one thread in suspended list */ - - /* get thread entry */ - thread = rt_list_entry(queue->suspended_pop_list.next, - struct rt_thread, - tlist); - - /* resume it */ - rt_thread_resume(thread); + audio->replay->activated = RT_FALSE; rt_hw_interrupt_enable(level); - /* perform a schedule */ - rt_schedule(); - - return result; + goto _exit; } -__exit: - rt_hw_interrupt_enable(level); - - return result; -} - -rt_err_t _audio_queue_pop(struct rt_audio_queue *queue, struct rt_audio_frame *frame, rt_int32_t timeout) -{ - rt_ubase_t level; - rt_thread_t thread; - rt_err_t result; - - RT_ASSERT(queue != RT_NULL); - RT_ASSERT(frame != RT_NULL); - - result = RT_EOK; - thread = rt_thread_self(); - - AUDIO_DBG("%s count = %d\n",__func__,queue->count); - level = rt_hw_interrupt_disable(); - while (queue->count == 0) - { - /* queue is empty */ - if (timeout == 0) - { - result = -RT_ETIMEOUT; - goto __exit; - } - - /* current context checking */ - RT_DEBUG_NOT_IN_INTERRUPT; - - /* reset thread error number */ - thread->error = RT_EOK; - - /* suspend thread on the pop list */ - rt_thread_suspend(thread); - rt_list_insert_before(&(queue->suspended_pop_list), &(thread->tlist)); - /* start timer */ - if (timeout > 0) - { - /* reset the timeout of thread timer and start it */ - rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout); - rt_timer_start(&(thread->thread_timer)); - } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - - /* do schedule */ - rt_schedule(); - - /* thread is waked up */ - result = thread->error; - level = rt_hw_interrupt_disable(); - if (result != RT_EOK) - goto __exit; - } - - frame->data_ptr = queue->queue[queue->get_index].data_ptr; - frame->data_size = queue->queue[queue->get_index].data_size; - frame->data_ofs = queue->queue[queue->get_index].data_ofs; - - queue->get_index = (queue->get_index + 1) % queue->size; - queue->count --; - - if ((queue->waiting_lwm == RT_TRUE) && - (queue->put_index - queue->get_index) <= queue->lwm) + if (audio->ops->transmit != RT_NULL) { - queue->waiting_lwm = RT_FALSE; - - /* - * there is at least one thread in suspended list - * and less than low water mark - */ - if (!rt_list_isempty(&(queue->suspended_push_list))) + AUDIO_DBG("audio transmit...\n"); + if (audio->ops->transmit(audio, frame.data_ptr, RT_NULL, frame.data_size) != frame.data_size) { - /* get thread entry */ - thread = rt_list_entry(queue->suspended_push_list.next, - struct rt_thread, - tlist); - - /* resume it */ - rt_thread_resume(thread); - rt_hw_interrupt_enable(level); + result = -RT_EBUSY; - /* perform a schedule */ - rt_schedule(); + goto _exit; } - - return result; - } -__exit: - rt_hw_interrupt_enable(level); - return result; -} - -rt_err_t _audio_queue_peak(struct rt_audio_queue *queue, struct rt_audio_frame *frame) -{ - rt_ubase_t level; - - RT_ASSERT(queue != RT_NULL); - - AUDIO_DBG("%s count = %d\n",__func__,queue->count); - - level = rt_hw_interrupt_disable(); - if (queue->count == 0) - { - rt_hw_interrupt_enable(level); - - return -RT_EEMPTY; } - frame->data_ptr = queue->queue[queue->get_index].data_ptr; - frame->data_size = queue->queue[queue->get_index].data_size; - frame->data_ofs = queue->queue[queue->get_index].data_ofs; - - rt_hw_interrupt_enable(level); + //pop the head frame... + rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); - return RT_EOK; + _exit: return result; } -rt_err_t _audio_queue_unpeak(struct rt_audio_queue *queue, struct rt_audio_frame *frame) +static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio) { - rt_ubase_t level; - - RT_ASSERT(queue != RT_NULL); + struct rt_audio_frame frame; - level = rt_hw_interrupt_disable(); - - if (queue->count == 0) + if (audio->replay == RT_NULL) + return -RT_EIO; + while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK) { - rt_hw_interrupt_enable(level); + //pop the head frame... + rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); - return -RT_EEMPTY; + /* notify transmitted complete. */ + if (audio->parent.tx_complete != RT_NULL) + audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); } - queue->queue[queue->get_index].data_ptr = frame->data_ptr; - queue->queue[queue->get_index].data_size = frame->data_size; - queue->queue[queue->get_index].data_ofs = frame->data_ofs; - - rt_hw_interrupt_enable(level); - return RT_EOK; } -rt_err_t _audio_queue_reset(struct rt_audio_queue *queue) -{ - struct rt_thread *thread; - register rt_ubase_t temp; - - rt_enter_critical(); - - /* wakeup all suspend threads */ - /* resume on pop list */ - while (!rt_list_isempty(&(queue->suspended_pop_list))) - { - /* disable interrupt */ - temp = rt_hw_interrupt_disable(); - - /* get next suspend thread */ - thread = rt_list_entry(queue->suspended_pop_list.next, - struct rt_thread, - tlist); - /* set error code to RT_ERROR */ - thread->error = -RT_ERROR; - - /* - * resume thread - * In rt_thread_resume function, it will remove current thread from - * suspend list - */ - rt_thread_resume(thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(temp); - } - - /* resume on push list */ - while (!rt_list_isempty(&(queue->suspended_push_list))) - { - /* disable interrupt */ - temp = rt_hw_interrupt_disable(); - - /* get next suspend thread */ - thread = rt_list_entry(queue->suspended_push_list.next, - struct rt_thread, - tlist); - /* set error code to RT_ERROR */ - thread->error = -RT_ERROR; - - /* - * resume thread - * In rt_thread_resume function, it will remove current thread from - * suspend list - */ - rt_thread_resume(thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(temp); - } - rt_exit_critical(); - - rt_schedule(); -} - - -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_ASSERT(audio != RT_NULL); - - //check repaly queue is empty - if(_audio_queue_peak(&audio->replay->queue,&frame) != RT_EOK) - { - AUDIO_DBG("TX queue is empty\n"); - result = -RT_EEMPTY; - - level = rt_hw_interrupt_disable(); - audio->replay->activated = RT_FALSE; - rt_hw_interrupt_enable(level); - - goto _exit; - } - - if(audio->ops->transmit != RT_NULL) - { - AUDIO_DBG("audio transmit...\n"); - if(audio->ops->transmit(audio,frame.data_ptr,RT_NULL, frame.data_size) != frame.data_size) - { - result = -RT_EBUSY; - - goto _exit; - } - } - - //pop the head frame... - _audio_queue_pop(&audio->replay->queue,&frame,RT_WAITING_NO); - -_exit: - return result; -} - -static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio) -{ - struct rt_audio_frame frame; - - if(audio->replay == RT_NULL) - return -RT_EIO; - - while(_audio_queue_peak(&audio->replay->queue,&frame) == RT_EOK) - { - //pop the head frame... - _audio_queue_pop(&audio->replay->queue,&frame,RT_WAITING_NO); - - /* notify transmitted complete. */ - if(audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent,(void *)frame.data_ptr); - } - - return RT_EOK; -} - static rt_err_t _audio_dev_init(struct rt_device *dev) { rt_err_t result = RT_EOK; struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); - audio = (struct rt_audio_device *)dev; + audio = (struct rt_audio_device *) dev; /* initialize replay & record */ audio->replay = RT_NULL; @@ -410,12 +114,12 @@ static rt_err_t _audio_dev_init(struct rt_device *dev) static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag) { - rt_err_t result = RT_EOK; - rt_base_t level; - struct rt_audio_device *audio; + rt_err_t result = RT_EOK; + rt_base_t level; + struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); - audio = (struct rt_audio_device *)dev; + audio = (struct rt_audio_device *) dev; /* check device flag with the open flag */ if ((oflag & RT_DEVICE_OFLAG_RDONLY) && !(dev->flag & RT_DEVICE_FLAG_RDONLY)) @@ -429,64 +133,65 @@ 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) - { - struct rt_audio_replay *replay = (struct rt_audio_replay *)rt_malloc(sizeof(struct rt_audio_replay)); + AUDIO_DBG("open audio device ,oflag = %x\n",oflag); + if (audio->replay == RT_NULL) + { + 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; - } + if (replay == RT_NULL) + { + AUDIO_DBG("request memory for replay error\n"); + return -RT_ENOMEM; + } - //init queue for audio replay - _audio_queue_init(&replay->queue,CFG_AUDIO_REPLAY_QUEUE_COUNT,CFG_AUDIO_REPLAY_QUEUE_COUNT / 2); + //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; - } + replay->activated = RT_FALSE; + audio->replay = replay; + } dev->open_flag |= RT_DEVICE_OFLAG_WRONLY; } - if(oflag & RT_DEVICE_OFLAG_RDONLY) + if (oflag & RT_DEVICE_OFLAG_RDONLY) { - if(audio->record == RT_NULL) - { - struct rt_audio_record *record = (struct rt_audio_record *)rt_malloc(sizeof(struct rt_audio_record)); + if (audio->record == RT_NULL) + { + 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; - } + if (record == RT_NULL) + { + AUDIO_DBG("request memory for record error\n"); + return -RT_ENOMEM; + } - //init pipe for record - { - rt_size_t size = CFG_AUDIO_RECORD_PIPE_SIZE; - rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE); + //init pipe for record + { + rt_size_t size = CFG_AUDIO_RECORD_PIPE_SIZE; + 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"); + if (buf == RT_NULL) + { + rt_free(record); + AUDIO_DBG("request pipe memory error\n"); - return -RT_ENOMEM; - } + return -RT_ENOMEM; + } - rt_pipe_init(&record->pipe,"recpipe",RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD,buf,CFG_AUDIO_RECORD_PIPE_SIZE); - } + rt_pipe_init(&record->pipe, "recpipe", RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD, buf, + CFG_AUDIO_RECORD_PIPE_SIZE); + } - record->activated = RT_FALSE; - audio->record = record; - } + record->activated = RT_FALSE; + audio->record = record; + } - //open record pipe - if(audio->record != RT_NULL) - { - rt_device_open(RT_DEVICE(&audio->record->pipe),RT_DEVICE_OFLAG_RDONLY); - } + //open record pipe + if (audio->record != RT_NULL) + { + rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY); + } dev->open_flag |= RT_DEVICE_OFLAG_RDONLY; } @@ -496,96 +201,93 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag) static rt_err_t _audio_dev_close(struct rt_device *dev) { - struct rt_audio_device *audio; + struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); - audio = (struct rt_audio_device *)dev; + audio = (struct rt_audio_device *) dev; - //shutdown the lower device - if(audio->ops->shutdown != RT_NULL) - audio->ops->shutdown(audio); + //shutdown the lower device + if (audio->ops->shutdown != RT_NULL) + audio->ops->shutdown(audio); - if(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) + if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY) { - struct rt_audio_frame frame; - //stop replay stream - audio->ops->stop(audio,AUDIO_STREAM_REPLAY); + struct rt_audio_frame frame; + //stop replay stream + audio->ops->stop(audio, AUDIO_STREAM_REPLAY); - //flush all frame - while(_audio_queue_peak(&audio->replay->queue,&frame) == RT_EOK) - { - _audio_queue_pop(&audio->replay->queue,&frame,RT_WAITING_NO); + //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); - //indicate this frame complete(maybe upper device need free data) - if(dev->tx_complete != RT_NULL) - dev->tx_complete(dev,(void *)frame.data_ptr); - } + /* notify transmitted complete. */ + if (audio->parent.tx_complete != RT_NULL) + audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); + } - dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY; + dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY; } - if(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) + if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY) { - //stop record stream - audio->ops->stop(audio,AUDIO_STREAM_RECORD); + //stop record stream + audio->ops->stop(audio, AUDIO_STREAM_RECORD); - //close record pipe - if(audio->record != RT_NULL) - rt_device_close(RT_DEVICE(&audio->record->pipe)); + //close record pipe + if (audio->record != RT_NULL) + rt_device_close(RT_DEVICE(&audio->record->pipe)); - dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY; + dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY; } - return RT_EOK; + return RT_EOK; } static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) { - struct rt_audio_device *audio; + 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; + 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->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_err_t result = RT_EOK; + rt_base_t level; + struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); - audio = (struct rt_audio_device *)dev; + audio = (struct rt_audio_device *) dev; - if(!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL)) - return 0; + 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 { - struct rt_audio_frame frame; - frame.data_ptr = buffer; - frame.data_size = size; - frame.data_ofs = 0; - - result = _audio_queue_push(&audio->replay->queue,&frame,RT_WAITING_FOREVER); - if(result != RT_EOK) + result = rt_data_queue_push(&audio->replay->queue, buffer, size, + RT_WAITING_FOREVER); + if (result != RT_EOK) { - AUDIO_DBG("TX frame queue push error\n"); - rt_set_errno(-RT_EFULL); + AUDIO_DBG("TX frame queue push error\n"); + rt_set_errno(-RT_EFULL); return 0; } } //check tx state... level = rt_hw_interrupt_disable(); - if(audio->replay->activated != RT_TRUE) + if (audio->replay->activated != RT_TRUE) { - audio->replay->activated = RT_TRUE; - rt_hw_interrupt_enable(level); + audio->replay->activated = RT_TRUE; + rt_hw_interrupt_enable(level); - _audio_send_replay_frame(audio); + _audio_send_replay_frame(audio); } return size; @@ -593,251 +295,243 @@ static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const voi static rt_err_t _audio_dev_control(struct rt_device *dev, rt_uint8_t cmd, void *args) { - rt_err_t result = RT_EOK; - struct rt_audio_device *audio; + rt_err_t result = RT_EOK; + struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); - audio = (struct rt_audio_device *)dev; + audio = (struct rt_audio_device *) dev; //dev stat... - switch (cmd) - { - case AUDIO_CTL_GETCAPS: - { - struct rt_audio_caps *caps = (struct rt_audio_caps *) args; + switch (cmd) + { + 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: - { - 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: + { + 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); - } - } + 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); + } + } - break; - case AUDIO_CTL_SHUTDOWN: - { - AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n"); + break; + case AUDIO_CTL_SHUTDOWN: + { + AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n"); - if (audio->ops->shutdown != RT_NULL) - result = audio->ops->shutdown(audio); + if (audio->ops->shutdown != RT_NULL) + result = audio->ops->shutdown(audio); - //flush replay frame... - _audio_flush_replay_frame(audio); - } - break; + //flush replay frame... + _audio_flush_replay_frame(audio); + } + break; - case AUDIO_CTL_START: - { - int stream = *(int *) args; + case AUDIO_CTL_START: + { + 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); - } - break; - case AUDIO_CTL_STOP: - { - 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); + } + 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); + AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream); + if (audio->ops->start != RT_NULL) + result = audio->ops->stop(audio, stream); - if(stream == AUDIO_STREAM_REPLAY) - { - _audio_flush_replay_frame(audio); - } - } - break; - case AUDIO_CTL_PAUSE: - { - int stream = *(int *) args; + if (stream == AUDIO_STREAM_REPLAY) + { + _audio_flush_replay_frame(audio); + } + } + break; + case AUDIO_CTL_PAUSE: + { + 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); - } - break; - case AUDIO_CTL_RESUME: - { - 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); + } + break; + case AUDIO_CTL_RESUME: + { + 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); + 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); - } - break; -#ifdef AUDIO_DEVICE_USE_PRIVATE_BUFFER - case AUDIO_CTL_ALLOCBUFFER: - { - struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *)args; + //resume tx frame... + if (stream == AUDIO_STREAM_REPLAY) + _audio_send_replay_frame(audio); + } + break; + case AUDIO_CTL_ALLOCBUFFER: + { + struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *) args; - if((audio->ops->buffer_alloc != RT_NULL) && (desc != RT_NULL)) - { - result = audio->ops->buffer_alloc(audio,&desc->data_ptr,&desc->data_size); - break; - } + if (desc) + { + desc->data_size = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2; + desc->data_ptr = rt_mp_alloc(&audio->mp, RT_WAITING_FOREVER); - result = -RT_EIO; - } - break; - case AUDIO_CTL_FREEBUFFER: - { - rt_uint8_t *data_ptr = (rt_uint8_t *)args; - if((audio->ops->buffer_free != RT_NULL) && (data_ptr != RT_NULL)) - { - audio->ops->buffer_free(audio,data_ptr); - break; - } - } - break; -#endif - default: - result = audio->ops->control(audio, cmd, args); - break; - } + result = RT_EOK; + } + else result = -RT_EIO; + } + break; + case AUDIO_CTL_FREEBUFFER: + { + rt_uint8_t *data_ptr = (rt_uint8_t *) args; + if (data_ptr) + rt_mp_free(data_ptr); + } + break; + default: + result = audio->ops->control(audio, cmd, args); + break; + } return result; } - rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data) { struct rt_device *device; RT_ASSERT(audio != RT_NULL); device = &(audio->parent); - device->type = RT_Device_Class_Sound; + device->type = RT_Device_Class_Sound; device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; - device->init = _audio_dev_init; - device->open = _audio_dev_open; - device->close = _audio_dev_close; - device->read = _audio_dev_read; - device->write = _audio_dev_write; - device->control = _audio_dev_control; - device->user_data = data; + device->init = _audio_dev_init; + device->open = _audio_dev_open; + device->close = _audio_dev_close; + device->read = _audio_dev_read; + device->write = _audio_dev_write; + device->control = _audio_dev_control; + 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); } - - -rt_size_t rt_audio_get_buffer_size(struct rt_audio_device *audio) -{ -// return (audio->config.period_count * audio->config.period_size); - return 0; -} - int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) { - int speed = 0; - switch (bitValue) - { - case AUDIO_SAMP_RATE_8K: - speed = 8000; - break; - case AUDIO_SAMP_RATE_11K: - speed = 11052; - break; - case AUDIO_SAMP_RATE_16K: - speed = 16000; - break; - case AUDIO_SAMP_RATE_22K: - speed = 22050; - break; - case AUDIO_SAMP_RATE_32K: - speed = 32000; - break; - case AUDIO_SAMP_RATE_44K: - speed = 44100; - break; - case AUDIO_SAMP_RATE_48K: - speed = 48000; - break; - case AUDIO_SAMP_RATE_96K: - speed = 96000; - break; - case AUDIO_SAMP_RATE_128K: - speed = 128000; - break; - case AUDIO_SAMP_RATE_160K: - speed = 160000; - break; - case AUDIO_SAMP_RATE_172K: - speed = 176400; - break; - case AUDIO_SAMP_RATE_192K: - speed = 192000; - break; - default: + int speed = 0; + switch (bitValue) + { + case AUDIO_SAMP_RATE_8K: + speed = 8000; + break; + case AUDIO_SAMP_RATE_11K: + speed = 11052; + break; + case AUDIO_SAMP_RATE_16K: + speed = 16000; + break; + case AUDIO_SAMP_RATE_22K: + speed = 22050; + break; + case AUDIO_SAMP_RATE_32K: + speed = 32000; + break; + case AUDIO_SAMP_RATE_44K: + speed = 44100; + break; + case AUDIO_SAMP_RATE_48K: + speed = 48000; + break; + case AUDIO_SAMP_RATE_96K: + speed = 96000; + break; + case AUDIO_SAMP_RATE_128K: + speed = 128000; + break; + case AUDIO_SAMP_RATE_160K: + speed = 160000; + break; + case AUDIO_SAMP_RATE_172K: + speed = 176400; + break; + case AUDIO_SAMP_RATE_192K: + speed = 192000; + break; + default: - break; - } + break; + } - return speed; + return speed; } - - rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format) { 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; + 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) +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); + 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); + //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); + /* notify transmitted complete. */ + if (audio->parent.tx_complete != RT_NULL) + audio->parent.tx_complete(&audio->parent, (void *) pbuf); } -void rt_audio_rx_done(struct rt_audio_device *audio,rt_uint8_t *pbuf,rt_size_t len) +void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len) { - rt_err_t result = RT_EOK; + rt_err_t result = RT_EOK; //save data to record pipe - rt_device_write(RT_DEVICE(RT_DEVICE(&audio->record->pipe)),0,pbuf,len); + rt_device_write(RT_DEVICE(RT_DEVICE(&audio->record->pipe)), 0, pbuf, len); /* invoke callback */ - if(audio->parent.rx_indicate != RT_NULL) - audio->parent.rx_indicate(&audio->parent,len); + if (audio->parent.rx_indicate != RT_NULL) + audio->parent.rx_indicate(&audio->parent, len); } diff --git a/components/drivers/can/can.c b/components/drivers/can/can.c index d1cc21dd3f..bbd1e2dcf6 100644 --- a/components/drivers/can/can.c +++ b/components/drivers/can/can.c @@ -154,20 +154,11 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da rt_uint32_t result; struct rt_can_sndbxinx_list *tx_tosnd = RT_NULL; + rt_sem_take(&(tx_fifo->sem), RT_WAITING_FOREVER); level = rt_hw_interrupt_disable(); - if (!rt_list_isempty(&tx_fifo->freelist)) - { - tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list); - RT_ASSERT(tx_tosnd != RT_NULL); - rt_list_remove(&tx_tosnd->list); - } - else - { - rt_hw_interrupt_enable(level); - - rt_completion_wait(&(tx_fifo->completion), RT_WAITING_FOREVER); - continue; - } + tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list); + RT_ASSERT(tx_tosnd != RT_NULL); + rt_list_remove(&tx_tosnd->list); rt_hw_interrupt_enable(level); no = ((rt_uint32_t)tx_tosnd - (rt_uint32_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list); @@ -178,6 +169,7 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da level = rt_hw_interrupt_disable(); rt_list_insert_after(&tx_fifo->freelist, &tx_tosnd->list); rt_hw_interrupt_enable(level); + rt_sem_release(&(tx_fifo->sem)); continue; } @@ -191,8 +183,8 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da rt_list_remove(&tx_tosnd->list); } rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list); - rt_completion_done(&(tx_fifo->completion)); rt_hw_interrupt_enable(level); + rt_sem_release(&(tx_fifo->sem)); if (result == RT_CAN_SND_RESULT_OK) { @@ -280,7 +272,7 @@ rt_inline int _can_int_tx_priv(struct rt_can_device *can, const struct rt_can_ms static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) { struct rt_can_device *can; - + char tmpname[16]; RT_ASSERT(dev != RT_NULL); can = (struct rt_can_device *)dev; @@ -341,7 +333,9 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) rt_completion_init(&(tx_fifo->buffer[i].completion)); tx_fifo->buffer[i].result = RT_CAN_SND_RESULT_OK; } - rt_completion_init(&(tx_fifo->completion)); + + rt_sprintf(tmpname, "%stl", dev->parent.name); + rt_sem_init(&(tx_fifo->sem), tmpname, can->config.sndboxnumber, RT_IPC_FLAG_FIFO); can->can_tx = tx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_TX; @@ -535,14 +529,20 @@ static rt_err_t rt_can_control(struct rt_device *dev, tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; if (can->config.privmode) { - rt_completion_done(&(tx_fifo->completion)); - for (i = 0; i < can->config.sndboxnumber; i++) { - level = rt_hw_interrupt_disable(); - rt_list_remove(&tx_fifo->buffer[i].list); + level = rt_hw_interrupt_disable(); + if(rt_list_isempty(&tx_fifo->buffer[i].list)) + { + rt_sem_release(&(tx_fifo->sem)); + } + else + { + rt_list_remove(&tx_fifo->buffer[i].list); + } rt_hw_interrupt_enable(level); } + } else { diff --git a/components/drivers/i2c/fm24clxx.c b/components/drivers/i2c/fm24clxx.c new file mode 100644 index 0000000000..4856a945da --- /dev/null +++ b/components/drivers/i2c/fm24clxx.c @@ -0,0 +1,157 @@ +/* + * File : fm24clxx.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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, rt_uint8_t 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; +} + +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; + 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; + 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 new file mode 100644 index 0000000000..fa84dd5e29 --- /dev/null +++ b/components/drivers/i2c/fm24clxx.h @@ -0,0 +1,40 @@ +/* + * File : fm24clxx.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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_core.c b/components/drivers/i2c/i2c_core.c index 739ae7ad43..67778ce0d3 100644 --- a/components/drivers/i2c/i2c_core.c +++ b/components/drivers/i2c/i2c_core.c @@ -67,7 +67,7 @@ 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%s\n", 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); } diff --git a/components/drivers/include/drivers/audio.h b/components/drivers/include/drivers/audio.h index e94c677368..70e837421b 100644 --- a/components/drivers/include/drivers/audio.h +++ b/components/drivers/include/drivers/audio.h @@ -1,98 +1,123 @@ +/* + * File : audio.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017-05-09 Urey first version + */ + #ifndef __AUDIO_H__ #define __AUDIO_H__ -//#define AUDIO_DEVICE_USE_PRIVATE_BUFFER - - /* AUDIO command */ -#define _AUDIO_CTL(a) (0x10 + a) +#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_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) /* 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 +#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_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 +#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 -#define AUDIO_SAMP_RATE_11K 0x0002 -#define AUDIO_SAMP_RATE_16K 0x0004 -#define AUDIO_SAMP_RATE_22K 0x0008 -#define AUDIO_SAMP_RATE_32K 0x0010 -#define AUDIO_SAMP_RATE_44K 0x0020 -#define AUDIO_SAMP_RATE_48K 0x0040 -#define AUDIO_SAMP_RATE_96K 0x0080 -#define AUDIO_SAMP_RATE_128K 0x0100 -#define AUDIO_SAMP_RATE_160K 0x0200 -#define AUDIO_SAMP_RATE_172K 0x0400 -#define AUDIO_SAMP_RATE_192K 0x0800 +#define AUDIO_SAMP_RATE_8K 0x0001 +#define AUDIO_SAMP_RATE_11K 0x0002 +#define AUDIO_SAMP_RATE_16K 0x0004 +#define AUDIO_SAMP_RATE_22K 0x0008 +#define AUDIO_SAMP_RATE_32K 0x0010 +#define AUDIO_SAMP_RATE_44K 0x0020 +#define AUDIO_SAMP_RATE_48K 0x0040 +#define AUDIO_SAMP_RATE_96K 0x0080 +#define AUDIO_SAMP_RATE_128K 0x0100 +#define AUDIO_SAMP_RATE_160K 0x0200 +#define AUDIO_SAMP_RATE_172K 0x0400 +#define AUDIO_SAMP_RATE_192K 0x0800 /* Supported Bit Rates */ -#define AUDIO_BIT_RATE_22K 0x01 -#define AUDIO_BIT_RATE_44K 0x02 -#define AUDIO_BIT_RATE_48K 0x04 -#define AUDIO_BIT_RATE_96K 0x08 -#define AUDIO_BIT_RATE_128K 0x10 -#define AUDIO_BIT_RATE_160K 0x20 -#define AUDIO_BIT_RATE_172K 0x40 -#define AUDIO_BIT_RATE_192K 0x80 +#define AUDIO_BIT_RATE_22K 0x01 +#define AUDIO_BIT_RATE_44K 0x02 +#define AUDIO_BIT_RATE_48K 0x04 +#define AUDIO_BIT_RATE_96K 0x08 +#define AUDIO_BIT_RATE_128K 0x10 +#define AUDIO_BIT_RATE_160K 0x20 +#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_PARAM 0 /* get/set all params */ +#define AUDIO_DSP_SAMPLERATE 1 /* ����Ƶ�� */ +#define AUDIO_DSP_FMT 2 +#define AUDIO_DSP_CHANNELS 3 /* Supported Mixer Units controls */ -#define AUDIO_MIXER_QUERY 0x0000 -#define AUDIO_MIXER_MUTE 0x0001 -#define AUDIO_MIXER_VOLUME 0x0002 -#define AUDIO_MIXER_BASS 0x0004 -#define AUDIO_MIXER_MID 0x0008 -#define AUDIO_MIXER_TREBLE 0x0010 -#define AUDIO_MIXER_EQUALIZER 0x0020 -#define AUDIO_MIXER_LINE 0x0040 -#define AUDIO_MIXER_DIGITAL 0x0080 -#define AUDIO_MIXER_MIC 0x0100 +#define AUDIO_MIXER_QUERY 0x0000 +#define AUDIO_MIXER_MUTE 0x0001 +#define AUDIO_MIXER_VOLUME 0x0002 +#define AUDIO_MIXER_BASS 0x0004 +#define AUDIO_MIXER_MID 0x0008 +#define AUDIO_MIXER_TREBLE 0x0010 +#define AUDIO_MIXER_EQUALIZER 0x0020 +#define AUDIO_MIXER_LINE 0x0040 +#define AUDIO_MIXER_DIGITAL 0x0080 +#define AUDIO_MIXER_MIC 0x0100 -#define AUDIO_MIXER_EXTEND 0x8000 //extend mixer command +#define AUDIO_MIXER_EXTEND 0x8000 //extend mixer command + +#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) -#define CFG_AUDIO_REPLAY_QUEUE_COUNT 4 -#define CFG_AUDIO_RECORD_PIPE_SIZE (8 * 1024) enum { @@ -104,36 +129,19 @@ 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 */ + 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; + rt_uint8_t *data_ptr; + rt_size_t data_size; }; struct rt_audio_frame { const void *data_ptr; rt_size_t data_size; - rt_size_t data_ofs; -}; - -struct rt_audio_queue -{ - rt_uint16_t count; - rt_uint16_t size; - rt_uint16_t lwm; - rt_bool_t waiting_lwm; - - rt_uint16_t get_index; - rt_uint16_t put_index; - - struct rt_audio_frame *queue; - - rt_list_t suspended_push_list; - rt_list_t suspended_pop_list; }; struct rt_audio_device; @@ -141,25 +149,21 @@ 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 (*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 (*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, rt_uint8_t cmd, void *arg); - rt_size_t (*transmit) (struct rt_audio_device *audio, const void *writeBuf,void *readBuf, rt_size_t size); + rt_err_t (*control) (struct rt_audio_device *audio, rt_uint8_t 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 ); -#ifdef AUDIO_DEVICE_USE_PRIVATE_BUFFER - rt_err_t (*buffer_alloc) (struct rt_audio_device *audio,rt_uint8_t **data_ptr,rt_size_t *size); - void (*buffer_free) (struct rt_audio_device *audio,rt_uint8_t *data_ptr); -#endif + void (*buffer_info) (struct rt_audio_device *audio,struct rt_audio_buf_info *info ); }; @@ -174,42 +178,44 @@ struct rt_audio_configure 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_audio_queue queue; + struct rt_data_queue queue; }; struct rt_audio_record { rt_bool_t activated; - struct rt_pipe_device pipe; + struct rt_pipe_device pipe; }; struct rt_audio_device { struct rt_device parent; - struct rt_audio_ops *ops; + struct rt_audio_ops *ops; + + struct rt_mempool mp; - struct rt_audio_replay *replay; - struct rt_audio_record *record; + 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,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); /* Device Control Commands */ @@ -219,7 +225,6 @@ rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format); #define CODEC_CMD_SAMPLERATE 3 #define CODEC_CMD_EQ 4 #define CODEC_CMD_3D 5 -#define CODEC_CMD_SWITCH 6 #define CODEC_VOLUME_MAX (63) diff --git a/components/drivers/include/drivers/can.h b/components/drivers/include/drivers/can.h index 71b577eba0..ecf3b5f51e 100644 --- a/components/drivers/include/drivers/can.h +++ b/components/drivers/include/drivers/can.h @@ -280,7 +280,7 @@ struct rt_can_sndbxinx_list struct rt_can_tx_fifo { struct rt_can_sndbxinx_list *buffer; - struct rt_completion completion; + struct rt_semaphore sem; struct rt_list_node freelist; }; diff --git a/components/drivers/include/drivers/mmcsd_card.h b/components/drivers/include/drivers/mmcsd_card.h index 4a82bc58f5..18470a5ea9 100644 --- a/components/drivers/include/drivers/mmcsd_card.h +++ b/components/drivers/include/drivers/mmcsd_card.h @@ -135,6 +135,8 @@ struct rt_sdio_function { rt_uint32_t enable_timeout_val; /* max enable timeout in msec */ struct rt_sdio_function_tuple *tuples; + + void *priv; }; #define SDIO_MAX_FUNCTIONS 7 diff --git a/components/drivers/include/drivers/mmcsd_host.h b/components/drivers/include/drivers/mmcsd_host.h index 3b68058ba4..877a04d8e0 100644 --- a/components/drivers/include/drivers/mmcsd_host.h +++ b/components/drivers/include/drivers/mmcsd_host.h @@ -111,7 +111,7 @@ struct rt_mmcsd_host { rt_uint32_t max_blk_count; /* maximum block count */ rt_uint32_t spi_use_crc; - struct rt_semaphore bus_lock; + struct rt_mutex bus_lock; struct rt_semaphore sem_ack; rt_uint32_t sdio_irq_num; diff --git a/components/drivers/include/drivers/sdio.h b/components/drivers/include/drivers/sdio.h index 5f65882952..2cd1c7dfd1 100644 --- a/components/drivers/include/drivers/sdio.h +++ b/components/drivers/include/drivers/sdio.h @@ -229,6 +229,8 @@ rt_int32_t sdio_detach_irq(struct rt_sdio_function *func); void sdio_irq_wakeup(struct rt_mmcsd_host *host); rt_int32_t sdio_enable_func(struct rt_sdio_function *func); rt_int32_t sdio_disable_func(struct rt_sdio_function *func); +void sdio_set_drvdata(struct rt_sdio_function *func, void *data); +void* sdio_get_drvdata(struct rt_sdio_function *func); rt_int32_t sdio_set_block_size(struct rt_sdio_function *func, rt_uint32_t blksize); rt_int32_t sdio_register_driver(struct rt_sdio_driver *driver); diff --git a/components/drivers/include/drivers/watchdog.h b/components/drivers/include/drivers/watchdog.h index 15ae5a1f44..5c74dc82be 100644 --- a/components/drivers/include/drivers/watchdog.h +++ b/components/drivers/include/drivers/watchdog.h @@ -38,7 +38,7 @@ struct rt_watchdog_ops; struct rt_watchdog_device { struct rt_device parent; - struct rt_watchdog_ops *ops; + const struct rt_watchdog_ops *ops; }; typedef struct rt_watchdog_device rt_watchdog_t; diff --git a/components/drivers/sdio/mmcsd_core.c b/components/drivers/sdio/mmcsd_core.c index adda6a4910..02063efdd2 100644 --- a/components/drivers/sdio/mmcsd_core.c +++ b/components/drivers/sdio/mmcsd_core.c @@ -49,12 +49,12 @@ static rt_uint32_t mmcsd_hotpluge_mb_pool[4]; void mmcsd_host_lock(struct rt_mmcsd_host *host) { - rt_sem_take(&host->bus_lock, RT_WAITING_FOREVER); + rt_mutex_take(&host->bus_lock, RT_WAITING_FOREVER); } void mmcsd_host_unlock(struct rt_mmcsd_host *host) { - rt_sem_release(&host->bus_lock); + rt_mutex_release(&host->bus_lock); } void mmcsd_req_complete(struct rt_mmcsd_host *host) @@ -713,7 +713,7 @@ struct rt_mmcsd_host *mmcsd_alloc_host(void) host->max_blk_size = 512; host->max_blk_count = 4096; - rt_sem_init(&host->bus_lock, "sd_bus_lock", 1, RT_IPC_FLAG_FIFO); + rt_mutex_init(&host->bus_lock, "sd_bus_lock", RT_IPC_FLAG_FIFO); rt_sem_init(&host->sem_ack, "sd_ack", 0, RT_IPC_FLAG_FIFO); return host; @@ -721,7 +721,7 @@ struct rt_mmcsd_host *mmcsd_alloc_host(void) void mmcsd_free_host(struct rt_mmcsd_host *host) { - rt_sem_detach(&host->bus_lock); + rt_mutex_detach(&host->bus_lock); rt_sem_detach(&host->sem_ack); rt_free(host); } diff --git a/components/drivers/sdio/sdio.c b/components/drivers/sdio/sdio.c index 59f1456e6f..496765854e 100644 --- a/components/drivers/sdio/sdio.c +++ b/components/drivers/sdio/sdio.c @@ -29,8 +29,8 @@ #ifndef RT_SDIO_STACK_SIZE #define RT_SDIO_STACK_SIZE 512 #endif -#ifndef RT_SDIO_THREAD_PREORITY -#define RT_SDIO_THREAD_PREORITY 0x40 +#ifndef RT_SDIO_THREAD_PRIORITY +#define RT_SDIO_THREAD_PRIORITY 0x40 #endif static rt_list_t sdio_cards; @@ -1059,7 +1059,7 @@ static rt_int32_t sdio_irq_thread_create(struct rt_mmcsd_card *card) RT_ASSERT(host->sdio_irq_sem != RT_NULL); host->sdio_irq_thread = rt_thread_create("sdio_irq", sdio_irq_thread, host, - RT_SDIO_STACK_SIZE, RT_SDIO_THREAD_PREORITY, 20); + RT_SDIO_STACK_SIZE, RT_SDIO_THREAD_PRIORITY, 20); if (host->sdio_irq_thread != RT_NULL) { rt_thread_startup(host->sdio_irq_thread); @@ -1079,7 +1079,7 @@ static rt_int32_t sdio_irq_thread_delete(struct rt_mmcsd_card *card) if (!host->sdio_irq_num) { if (host->flags & MMCSD_SUP_SDIO_IRQ) - host->ops->enable_sdio_irq(host, 0); + host->ops->enable_sdio_irq(host, 0); rt_sem_delete(host->sdio_irq_sem); host->sdio_irq_sem = RT_NULL; rt_thread_delete(host->sdio_irq_thread); @@ -1253,6 +1253,16 @@ err: return -RT_EIO; } +void sdio_set_drvdata(struct rt_sdio_function *func, void *data) +{ + func->priv = data; +} + +void* sdio_get_drvdata(struct rt_sdio_function *func) +{ + return func->priv; +} + rt_int32_t sdio_set_block_size(struct rt_sdio_function *func, rt_uint32_t blksize) { @@ -1284,16 +1294,24 @@ rt_int32_t sdio_set_block_size(struct rt_sdio_function *func, rt_inline rt_int32_t sdio_match_card(struct rt_mmcsd_card *card, const struct rt_sdio_device_id *id) { + rt_uint8_t num = 1; + if ((id->manufacturer != SDIO_ANY_MAN_ID) && (id->manufacturer != card->cis.manufacturer)) return 0; - if ((id->product != SDIO_ANY_PROD_ID) && - (id->product != (card->cis.product | 1))) - return 0; + + while (num <= card->sdio_function_num) + { + if ((id->product != SDIO_ANY_PROD_ID) && + (id->product == card->sdio_function[num]->product)) + return 1; + num++; + } - return 1; + return 0; } + static struct rt_mmcsd_card *sdio_match_driver(struct rt_sdio_device_id *id) { rt_list_t *l; diff --git a/components/drivers/spi/sfud/LICENSE b/components/drivers/spi/sfud/LICENSE index 6b761d3f4a..f956e1683d 100644 --- a/components/drivers/spi/sfud/LICENSE +++ b/components/drivers/spi/sfud/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Armink ([email protected]) +Copyright (c) 2016-2017 Armink ([email protected]) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/components/drivers/spi/sfud/README.md b/components/drivers/spi/sfud/README.md index 69ea4a67f6..13ef219154 100644 --- a/components/drivers/spi/sfud/README.md +++ b/components/drivers/spi/sfud/README.md @@ -10,7 +10,7 @@ - 资源占用 - 标准占用:RAM:0.2KB ROM:5.5KB - 最小占用:RAM:0.1KB ROM:3.6KB -- 设计思路:这里要首先跟大家介绍一个标准: **SFDP** ,它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B ([点击这里查看](https://www.jedec.org/standards-documents/docs/jesd216b))。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粗粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数,如果该 Flash 不支持 SFDP,则查询配置文件 ( `/sfud/inc/sfud_flash_def.h` ) 中提供的 **Flash 参数信息表** 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 [2.5 添加库目前不支持的 Flash](#25-添加库目前不支持的-flash))。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。 +- 设计思路:这里要首先跟大家介绍一个标准: **SFDP** ,它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B ([点击这里查看](https://www.jedec.org/standards-documents/docs/jesd216b))。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数,如果该 Flash 不支持 SFDP,则查询配置文件 ( [`/sfud/inc/sfud_flash_def.h`](https://github.com/armink/SFUD/blob/master/sfud/inc/sfud_flash_def.h#L110-L122) ) 中提供的 **Flash 参数信息表** 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 [2.5 添加库目前不支持的 Flash](#25-添加库目前不支持的-flash))。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。 ## 1、为什么选择 SFUD @@ -25,7 +25,7 @@ 下表为所有在 Demo 平台上进行过真机测试的 Flash。目前 SFUD 提供的 **Flash 参数信息表** 只包括下表中 **不支持** SFDP 标准的 Flash,其他不支持 SFDP 标准的 Flash 需要大家以后 **共同来完善和维护** **([Github](https://github.com/armink/SFUD)|[OSChina](http://git.oschina.net/armink/SFUD)|[Coding](https://coding.net/u/armink/p/SFUD/git))** 。如果觉得这个开源项目很赞,可以点击 [项目主页](https://github.com/armink/SFUD) 右上角的 **Star** ,同时把它推荐给更多有需要的朋友。 -|型号|制造商|容量|最高速度|SFDP|备注| +|型号|制造商|容量|最高速度|SFDP 标准|备注| |:--:|:----:|:--:|:--:|:--:|:--:| |[W25Q40BV](http://microchip.ua/esp8266/W25Q40BV(EOL).pdf)|Winbond|4Mb|50Mhz|不支持|已停产| |[W25Q80DV](http://www.winbond.com/resource-files/w25q80dv_revg_07212015.pdf)|Winbond|8Mb|104Mhz|支持|| @@ -39,7 +39,8 @@ |[SST25VF016B](http://ww1.microchip.com/downloads/en/DeviceDoc/20005044C.pdf)|Microchip|16Mb|50MHz|不支持| SST 已被 Microchip 收购| |[M25P32](https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p32.pdf)|Micron|32Mb|75Mhz|不支持|| |[EN25Q32B](http://www.kean.com.au/oshw/WR703N/teardown/EN25Q32B%2032Mbit%20SPI%20Flash.pdf)|EON|32Mb|104MHz|不支持|| -|[GD25Q64B](http://www.gigadevice.com/product/download/24.html)|GigaDevice|64Mb|120Mhz|不支持|| +|[GD25Q64B](http://www.gigadevice.com/product/detail/5/364.html)|GigaDevice|64Mb|120Mhz|不支持|| +|[GD25Q16B](http://www.gigadevice.com/product/detail/5/410.html)|GigaDevice|16Mb|120Mhz|不支持| by [TanekLiang](https://github.com/TanekLiang) | |[S25FL216K](http://www.cypress.com/file/197346/download)|Cypress|16Mb|65Mhz|不支持|| |[S25FL164K](http://www.cypress.com/file/196886/download)|Cypress|64Mb|108Mhz|支持|| |[A25LQ64](http://www.amictechnology.com/datasheets/A25LQ64.pdf)|AMIC|64Mb|104Mhz|支持|| @@ -50,8 +51,12 @@ ### 2.2 API 说明 +先说明下本库主要使用的一个结构体 `sfud_flash` 。其定义位于 `/sfud/inc/sfud_def.h`。每个 SPI Flash 会对应一个该结构体,该结构体指针下面统称为 Flash 设备对象。初始化成功后在 `sfud_flash->chip` 结构体中会存放 SPI Flash 的常见参数。如果 SPI Flash 还支持 SFDP ,还可以通过 `sfud_flash->sfdp` 看到更加全面的参数信息。以下很多函数都将使用 Flash 设备对象作为第一个入参,实现对指定 SPI Flash 的操作。 + #### 2.2.1 初始化 SFUD 库 +> 注意:初始化完的 SPI Flash 默认都 **已取消写保护** 状态,如需开启写保护,请使用 sfud_write_status 函数修改 SPI Flash 状态。 + ```C sfud_err sfud_init(void) ``` @@ -92,11 +97,13 @@ sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t |:----- |:----| |flash |Flash 设备对象| |addr |起始地址| -|size |读取数据的大小| +|size |从起始地址开始读取数据的总大小| |data |读取到的数据| #### 2.2.6 擦除 Flash 数据 +> 注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过 `sfud_flash->chip.erase_gran` 查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。 + ```C sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size) ``` @@ -105,7 +112,7 @@ sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size) |:----- |:----| |flash |Flash 设备对象| |addr |起始地址| -|size |擦除数据的大小| +|size |从起始地址开始擦除数据的总大小| #### 2.2.7 擦除 Flash 全部数据 @@ -127,11 +134,13 @@ sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const u |:----- |:----| |flash |Flash 设备对象| |addr |起始地址| -|size |写数据的大小| +|size |从起始地址开始写入数据的总大小| |data |待写入的数据| #### 2.2.9 先擦除再往 Flash 写数据 +> 注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过 `sfud_flash->chip.erase_gran` 查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。 + ```C sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) ``` @@ -140,7 +149,7 @@ sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, c |:----- |:----| |flash |Flash 设备对象| |addr |起始地址| -|size |写数据的大小| +|size |从起始地址开始写入数据的总大小| |data |待写入的数据| #### 2.2.10 读取 Flash 状态 @@ -211,7 +220,7 @@ enum { ### 2.5 添加库目前不支持的 Flash -这里需要修改 `/sfud/inc/sfdu_flash_def.h` ,所有已经支持的 Flash 见 `SFUD_FLASH_CHIP_TABLE` 宏定义,需要提前准备的 Flash 参数内容分别为:| 名称 | 制造商 ID | 类型 ID | 容量 ID | 容量 | 写模式 | 擦除粗粒度(擦除的最小单位) | 擦除粗粒度对应的命令 | 。这里以添加 兆易创新 ( GigaDevice ) 的 `GD25Q64B` Flash 来举例。 +这里需要修改 `/sfud/inc/sfdu_flash_def.h` ,所有已经支持的 Flash 见 `SFUD_FLASH_CHIP_TABLE` 宏定义,需要提前准备的 Flash 参数内容分别为:| 名称 | 制造商 ID | 类型 ID | 容量 ID | 容量 | 写模式 | 擦除粒度(擦除的最小单位) | 擦除粒度对应的命令 | 。这里以添加 兆易创新 ( GigaDevice ) 的 `GD25Q64B` Flash 来举例。 此款 Flash 为兆易创新的早期生产的型号,所以不支持 SFDP 标准。首先需要下载其数据手册,找到 0x9F 命令返回的 3 种 ID, 这里需要最后面两字节 ID ,即 `type id` 及 `capacity id` 。 `GD25Q64B` 对应这两个 ID 分别为 `0x40` 及 `0x17` 。上面要求的其他 Flash 参数都可以在数据手册中找到,这里要重点说明下 **写模式** 这个参数,库本身提供的写模式共计有 4 种,详见文件顶部的 `sfud_write_mode` 枚举类型,同一款 Flash 可以同时支持多种写模式,视情况而定。对于 `GD25Q64B` 而言,其支持的写模式应该为 `SFUD_WM_PAGE_256B` ,即写 1-256 字节每页。结合上述 `GD25Q64B` 的 Flash 参数应如下: @@ -232,4 +241,4 @@ enum { ### 2.7 许可 -采用 MIT 开源协议,细节请阅读项目中的 LICENSE 文件内容。
\ No newline at end of file +采用 MIT 开源协议,细节请阅读项目中的 LICENSE 文件内容。 diff --git a/components/drivers/spi/sfud/inc/sfud_def.h b/components/drivers/spi/sfud/inc/sfud_def.h index 44dd03c745..cc38c3fa1a 100644 --- a/components/drivers/spi/sfud/inc/sfud_def.h +++ b/components/drivers/spi/sfud/inc/sfud_def.h @@ -41,12 +41,16 @@ extern "C" { /* debug print function. Must be implement by user. */ #ifdef SFUD_DEBUG_MODE +#ifndef SFUD_DEBUG #define SFUD_DEBUG(...) sfud_log_debug(__FILE__, __LINE__, __VA_ARGS__) +#endif /* SFUD_DEBUG */ #else #define SFUD_DEBUG(...) -#endif +#endif /* SFUD_DEBUG_MODE */ +#ifndef SFUD_INFO #define SFUD_INFO(...) sfud_log_info(__VA_ARGS__) +#endif /* assert for developer. */ #ifdef SFUD_DEBUG_MODE @@ -73,7 +77,7 @@ if (!(EXPR)) \ else {if (__delay_temp) {__delay_temp();} retry --;} /* software version number */ -#define SFUD_SW_VERSION "0.10.14" +#define SFUD_SW_VERSION "1.0.1" /* * all defined supported command */ diff --git a/components/drivers/spi/sfud/inc/sfud_flash_def.h b/components/drivers/spi/sfud/inc/sfud_flash_def.h index b593297df6..06c95b775a 100644 --- a/components/drivers/spi/sfud/inc/sfud_flash_def.h +++ b/components/drivers/spi/sfud/inc/sfud_flash_def.h @@ -1,7 +1,7 @@ /* * This file is part of the Serial Flash Universal Driver Library. * - * Copyright (c) 2016, Armink, <[email protected]> + * Copyright (c) 2016-2017, Armink, <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -103,8 +103,8 @@ typedef struct { #ifdef SFUD_USING_FLASH_INFO_TABLE /* SFUD supported flash chip information table. If the flash not support JEDEC JESD216 standard, - * then the SFUD will find the flash chip information by this table. Developer can add other flash to here. - * The configuration information name and index reference the sfud_flash_chip structure. + * then the SFUD will find the flash chip information by this table. You can add other flash to here then + * notice me for update it. The configuration information name and index reference the sfud_flash_chip structure. * | name | mf_id | type_id | capacity_id | capacity | write_mode | erase_gran | erase_gran_cmd | */ #define SFUD_FLASH_CHIP_TABLE \ @@ -115,6 +115,7 @@ typedef struct { {"M25P32", SFUD_MF_ID_MICRON, 0x20, 0x16, 4*1024*1024, SFUD_WM_PAGE_256B, 64*1024, 0xD8}, \ {"EN25Q32B", SFUD_MF_ID_EON, 0x30, 0x16, 4*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20}, \ + {"GD25Q16B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x15, 2*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"S25FL216K", SFUD_MF_ID_CYPRESS, 0x40, 0x15, 2*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"A25L080", SFUD_MF_ID_AMIC, 0x30, 0x14, 1*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"F25L004", SFUD_MF_ID_ESMT, 0x20, 0x13, 512*1024, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20}, \ diff --git a/components/drivers/spi/sfud/src/sfud.c b/components/drivers/spi/sfud/src/sfud.c index b616e3fad8..475cbd5d9e 100644 --- a/components/drivers/spi/sfud/src/sfud.c +++ b/components/drivers/spi/sfud/src/sfud.c @@ -110,7 +110,7 @@ sfud_err sfud_init(void) { cur_flash_result = sfud_device_init(&flash_table[i]); if (cur_flash_result != SFUD_SUCCESS) { - cur_flash_result = cur_flash_result; + all_flash_result = cur_flash_result; } } @@ -587,12 +587,9 @@ static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, c sfud_err result = SFUD_SUCCESS; const sfud_spi *spi = &flash->spi; uint8_t cmd_data[6], cmd_size; - const size_t data_size = 2; bool first_write = true; SFUD_ASSERT(flash); - SFUD_ASSERT(size >= 2); - /* must be call this function after initialize OK */ SFUD_ASSERT(flash->init_ok); /* check the flash address bound */ if (addr + size > flash->chip.capacity) { @@ -603,41 +600,35 @@ static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, c if (spi->lock) { spi->lock(spi); } - + /* The address must be even for AAI write mode. So it must write one byte first when address is odd. */ + if (addr % 2 != 0) { + result = page256_or_1_byte_write(flash, addr++, 1, 1, data++); + if (result != SFUD_SUCCESS) { + goto __exit; + } + size--; + } /* set the flash write enable */ result = set_write_enabled(flash, true); if (result != SFUD_SUCCESS) { goto __exit; } - /* loop write operate. write unit is write granularity */ + /* loop write operate. */ cmd_data[0] = SFUD_CMD_AAI_WORD_PROGRAM; - while (size) { + while (size >= 2) { if (first_write) { make_adress_byte_array(flash, addr, &cmd_data[1]); cmd_size = flash->addr_in_4_byte ? 5 : 4; - if (addr % 2 == 0) { - cmd_data[cmd_size] = *data; - cmd_data[cmd_size + 1] = *(data + 1); - } else { - cmd_data[cmd_size] = 0xFF; - cmd_data[cmd_size + 1] = *data; - size++; - data--; - } + cmd_data[cmd_size] = *data; + cmd_data[cmd_size + 1] = *(data + 1); first_write = false; } else { cmd_size = 1; - if (size != 1) { - cmd_data[1] = *data; - cmd_data[2] = *(data + 1); - } else { - cmd_data[1] = *data; - cmd_data[2] = 0xFF; - size++; - } + cmd_data[1] = *data; + cmd_data[2] = *(data + 1); } - result = spi->wr(spi, cmd_data, cmd_size + data_size, NULL, 0); + result = spi->wr(spi, cmd_data, cmd_size + 2, NULL, 0); if (result != SFUD_SUCCESS) { SFUD_INFO("Error: Flash write SPI communicate error."); goto __exit; @@ -649,12 +640,20 @@ static sfud_err aai_write(const sfud_flash *flash, uint32_t addr, size_t size, c } size -= 2; - data += data_size; + addr += 2; + data += 2; + } + /* set the flash write disable for exit AAI mode */ + result = set_write_enabled(flash, false); + /* write last one byte data when origin write size is odd */ + if (result == SFUD_SUCCESS && size == 1) { + result = page256_or_1_byte_write(flash, addr, 1, 1, data); } __exit: - /* set the flash write disable for exist AAI mode */ - set_write_enabled(flash, false); + if (result != SFUD_SUCCESS) { + set_write_enabled(flash, false); + } /* unlock SPI */ if (spi->unlock) { spi->unlock(spi); diff --git a/components/drivers/spi/sfud/src/sfud_sfdp.c b/components/drivers/spi/sfud/src/sfud_sfdp.c index 95157e613f..32873ab8cb 100644 --- a/components/drivers/spi/sfud/src/sfud_sfdp.c +++ b/components/drivers/spi/sfud/src/sfud_sfdp.c @@ -119,7 +119,7 @@ static bool read_sfdp_header(sfud_flash *flash) { header[1] == 'F' && header[2] == 'D' && header[3] == 'P')) { - SFUD_INFO("Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P')."); + SFUD_DEBUG("Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P')."); return false; } sfdp->minor_rev = header[4]; diff --git a/components/drivers/spi/spi_flash_at45dbxx.c b/components/drivers/spi/spi_flash_at45dbxx.c index 0585e395ca..f9a15b27dd 100644 --- a/components/drivers/spi/spi_flash_at45dbxx.c +++ b/components/drivers/spi/spi_flash_at45dbxx.c @@ -140,12 +140,12 @@ static rt_size_t AT45DB_flash_read_page_256(rt_device_t dev, rt_off_t pos, void* { uint32_t index, nr; uint8_t * read_buffer = buffer; + uint32_t page = pos; nr = size; for (index = 0; index < nr; index++) { - uint32_t page = pos; uint8_t send_buffer[8]; uint32_t i; @@ -170,12 +170,12 @@ static rt_size_t AT45DB_flash_read_page_512(rt_device_t dev, rt_off_t pos, void* { uint32_t index, nr; uint8_t * read_buffer = buffer; + uint32_t page = pos; nr = size; for (index = 0; index < nr; index++) { - uint32_t page = pos; uint8_t send_buffer[8]; uint32_t i; @@ -200,12 +200,12 @@ static rt_size_t AT45DB_flash_read_page_1024(rt_device_t dev, rt_off_t pos, void { uint32_t index, nr; uint8_t * read_buffer = buffer; + uint32_t page = pos; nr = size; for (index = 0; index < nr; index++) { - uint32_t page = pos; uint8_t send_buffer[8]; uint32_t i; @@ -230,12 +230,12 @@ static rt_size_t AT45DB_flash_write_page_256(rt_device_t dev, rt_off_t pos, cons { rt_uint32_t index, nr; const uint8_t * write_buffer = buffer; + uint32_t page = pos; nr = size; for (index = 0; index < nr; index++) { - uint32_t page = pos; uint8_t send_buffer[4]; send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; @@ -258,12 +258,12 @@ static rt_size_t AT45DB_flash_write_page_512(rt_device_t dev, rt_off_t pos, cons { rt_uint32_t index, nr; const uint8_t * write_buffer = buffer; + uint32_t page = pos; nr = size; for (index = 0; index < nr; index++) { - uint32_t page = pos; uint8_t send_buffer[4]; send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; @@ -286,12 +286,12 @@ static rt_size_t AT45DB_flash_write_page_1024(rt_device_t dev, rt_off_t pos, con { rt_uint32_t index, nr; const uint8_t * write_buffer = buffer; + uint32_t page = pos; nr = size; for (index = 0; index < nr; index++) { - uint32_t page = pos; uint8_t send_buffer[4]; send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; diff --git a/components/drivers/spi/spi_wifi_rw009.c b/components/drivers/spi/spi_wifi_rw009.c index 9f5601bf26..5faf63642a 100644 --- a/components/drivers/spi/spi_wifi_rw009.c +++ b/components/drivers/spi/spi_wifi_rw009.c @@ -21,6 +21,7 @@ * Date Author Notes * 2014-07-31 aozima the first version * 2014-09-18 aozima update command & response. + * 2017-07-28 armink fix auto reconnect feature */ #include <rtthread.h> @@ -165,6 +166,8 @@ static void resp_handler(struct rw009_wifi *wifi_device, struct rw009_resp *resp } else { + wifi_device->active = 1; + eth_device_linkchange(&wifi_device->parent, RT_FALSE); WIFI_DEBUG("RW009_CMD_EASY_JOIN result: %d\n", resp->result ); } diff --git a/components/finsh/msh.c b/components/finsh/msh.c index bd4b12d9d5..f7e40c8841 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -26,6 +26,7 @@ * Date Author Notes * 2013-03-30 Bernard the first verion for finsh * 2014-01-03 Bernard msh can execute module. + * 2017-07-19 Aubr.Cool limit argc to RT_FINSH_ARG_MAX */ #include "msh.h" @@ -103,6 +104,7 @@ static int msh_split(char *cmd, rt_size_t length, char *argv[RT_FINSH_ARG_MAX]) char *ptr; rt_size_t position; rt_size_t argc; + rt_size_t i; ptr = cmd; position = 0; argc = 0; @@ -115,6 +117,18 @@ static int msh_split(char *cmd, rt_size_t length, char *argv[RT_FINSH_ARG_MAX]) *ptr = '\0'; ptr ++; position ++; } + + if(argc >= RT_FINSH_ARG_MAX) + { + rt_kprintf("Too many args ! We only Use:\n"); + for(i = 0; i < argc; i++) + { + rt_kprintf("%s ", argv[i]); + } + rt_kprintf("\n"); + break; + } + if (position >= length) break; /* handle string */ diff --git a/components/finsh/shell.c b/components/finsh/shell.c index 7e8a84ab27..2d157be3bd 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -214,6 +214,9 @@ static void finsh_wait_auth(void) rt_bool_t input_finish = RT_FALSE; char password[FINSH_PASSWORD_MAX] = { 0 }; rt_size_t cur_pos = 0; + /* password not set */ + if (rt_strlen(finsh_get_password()) == 0) return; + while (1) { rt_kprintf("Password for finsh: "); @@ -410,7 +413,12 @@ void finsh_thread_entry(void *parameter) #ifdef FINSH_USING_AUTH /* set the default password when the password isn't setting */ if (rt_strlen(finsh_get_password()) == 0) - RT_ASSERT(finsh_set_password(FINSH_DEFAULT_PASSWORD) == RT_EOK); + { + if (finsh_set_password(FINSH_DEFAULT_PASSWORD) != RT_EOK) + { + rt_kprintf("Finsh password set failed.\n"); + } + } /* waiting authenticate success */ finsh_wait_auth(); #endif diff --git a/components/libc/armlibc/sys/errno.h b/components/libc/armlibc/sys/errno.h index e4371d749a..0aba5f5e19 100644 --- a/components/libc/armlibc/sys/errno.h +++ b/components/libc/armlibc/sys/errno.h @@ -6,73 +6,75 @@ #include <dfs_def.h> /* using device error codes */ -#define ENOENT DFS_STATUS_ENOENT -#define EIO DFS_STATUS_EIO -#define ENXIO DFS_STATUS_ENXIO -#define EBADF DFS_STATUS_EBADF -#define EAGAIN DFS_STATUS_EAGAIN -#define ENOMEM DFS_STATUS_ENOMEM -#define EBUSY DFS_STATUS_EBUSY -#define EEXIST DFS_STATUS_EEXIST -#define EXDEV DFS_STATUS_EXDEV -#define ENODEV DFS_STATUS_ENODEV -#define ENOTDIR DFS_STATUS_ENOTDIR -#define EISDIR DFS_STATUS_EISDIR -#define EINVAL DFS_STATUS_EINVAL -#define ENOSPC DFS_STATUS_ENOSPC -#define EROFS DFS_STATUS_EROFS -#define ENOSYS DFS_STATUS_ENOSYS -#define ENOTEMPTY DFS_STATUS_ENOTEMPTY +#define ENOENT DFS_STATUS_ENOENT +#define EIO DFS_STATUS_EIO +#define ENXIO DFS_STATUS_ENXIO +#define EBADF DFS_STATUS_EBADF +#define EAGAIN DFS_STATUS_EAGAIN +#define ENOMEM DFS_STATUS_ENOMEM +#define EBUSY DFS_STATUS_EBUSY +#define EEXIST DFS_STATUS_EEXIST +#define EXDEV DFS_STATUS_EXDEV +#define ENODEV DFS_STATUS_ENODEV +#define ENOTDIR DFS_STATUS_ENOTDIR +#define EISDIR DFS_STATUS_EISDIR +#define EINVAL DFS_STATUS_EINVAL +#define ENOSPC DFS_STATUS_ENOSPC +#define EROFS DFS_STATUS_EROFS +#define ENOSYS DFS_STATUS_ENOSYS +#define ENOTEMPTY DFS_STATUS_ENOTEMPTY #else /* error codes */ -#define ENOENT 2 /* No such file or directory */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define EBADF 9 /* Bad file number */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* no memory */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENOSPC 28 /* No space left on device */ -#define EROFS 30 /* Read-only file system */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ +#define ENOENT 2 /* No such file or directory */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define EBADF 9 /* Bad file number */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* no memory */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENOSPC 28 /* No space left on device */ +#define EROFS 30 /* Read-only file system */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ #endif -#define EPERM 1 /* Not super-user */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EFAULT 14 /* Bad address */ -#define ENFILE 23 /* Too many open files in system */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 45 /* Deadlock condition */ -#define EBADMSG 77 /* Trying to read unreadable message */ -#define EMSGSIZE 90 /* Message too long */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ETIMEDOUT 116 /* Connection timed out */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define ENOTSUP 134 /* Not supported */ -#define ENSRNOTFOUND 163 /* Domain name not found */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EPERM 1 /* Not super-user */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENFILE 23 /* Too many open files in system */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 45 /* Deadlock condition */ +#define EBADMSG 77 /* Trying to read unreadable message */ +#define EMSGSIZE 90 /* Message too long */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ETIMEDOUT 116 /* Connection timed out */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define ENOTSUP 134 /* Not supported */ +#define ENSRNOTFOUND 163 /* Domain name not found */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ #endif diff --git a/components/libc/dlib/sys/errno.h b/components/libc/dlib/sys/errno.h index ee877c9006..a8e09ffd24 100644 --- a/components/libc/dlib/sys/errno.h +++ b/components/libc/dlib/sys/errno.h @@ -6,72 +6,75 @@ #include <dfs_def.h> /* using device error codes */ -#define ENOENT DFS_STATUS_ENOENT -#define EIO DFS_STATUS_EIO -#define ENXIO DFS_STATUS_ENXIO -#define EBADF DFS_STATUS_EBADF -#define EAGAIN DFS_STATUS_EAGAIN -#define ENOMEM DFS_STATUS_ENOMEM -#define EBUSY DFS_STATUS_EBUSY -#define EEXIST DFS_STATUS_EEXIST -#define EXDEV DFS_STATUS_EXDEV -#define ENODEV DFS_STATUS_ENODEV -#define ENOTDIR DFS_STATUS_ENOTDIR -#define EISDIR DFS_STATUS_EISDIR -#define EINVAL DFS_STATUS_EINVAL -#define ENOSPC DFS_STATUS_ENOSPC -#define EROFS DFS_STATUS_EROFS -#define ENOSYS DFS_STATUS_ENOSYS -#define ENOTEMPTY DFS_STATUS_ENOTEMPTY +#define ENOENT DFS_STATUS_ENOENT +#define EIO DFS_STATUS_EIO +#define ENXIO DFS_STATUS_ENXIO +#define EBADF DFS_STATUS_EBADF +#define EAGAIN DFS_STATUS_EAGAIN +#define ENOMEM DFS_STATUS_ENOMEM +#define EBUSY DFS_STATUS_EBUSY +#define EEXIST DFS_STATUS_EEXIST +#define EXDEV DFS_STATUS_EXDEV +#define ENODEV DFS_STATUS_ENODEV +#define ENOTDIR DFS_STATUS_ENOTDIR +#define EISDIR DFS_STATUS_EISDIR +#define EINVAL DFS_STATUS_EINVAL +#define ENOSPC DFS_STATUS_ENOSPC +#define EROFS DFS_STATUS_EROFS +#define ENOSYS DFS_STATUS_ENOSYS +#define ENOTEMPTY DFS_STATUS_ENOTEMPTY #else /* error codes */ -#define ENOENT 2 /* No such file or directory */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define EBADF 9 /* Bad file number */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* no memory */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENOSPC 28 /* No space left on device */ -#define EROFS 30 /* Read-only file system */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ +#define ENOENT 2 /* No such file or directory */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define EBADF 9 /* Bad file number */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* no memory */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENOSPC 28 /* No space left on device */ +#define EROFS 30 /* Read-only file system */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ #endif -#define EPERM 1 /* Not super-user */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EFAULT 14 /* Bad address */ -#define ENFILE 23 /* Too many open files in system */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 45 /* Deadlock condition */ -#define EBADMSG 77 /* Trying to read unreadable message */ -#define EMSGSIZE 90 /* Message too long */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ETIMEDOUT 116 /* Connection timed out */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define ENOTSUP 134 /* Not supported */ -#define ENSRNOTFOUND 163 /* Domain name not found */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EPERM 1 /* Not super-user */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENFILE 23 /* Too many open files in system */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 45 /* Deadlock condition */ +#define EBADMSG 77 /* Trying to read unreadable message */ +#define EMSGSIZE 90 /* Message too long */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ETIMEDOUT 116 /* Connection timed out */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define ENOTSUP 134 /* Not supported */ +#define ENSRNOTFOUND 163 /* Domain name not found */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ #endif diff --git a/components/libc/libdl/dlopen.c b/components/libc/libdl/dlopen.c index 5e063eed96..2c091079b2 100644 --- a/components/libc/libdl/dlopen.c +++ b/components/libc/libdl/dlopen.c @@ -27,7 +27,7 @@ void* dlopen(const char *filename, int flags) /* check parameters */ RT_ASSERT(filename != RT_NULL); - if (filename[0] != '/') /* it's a absolute path, use it directly */ + if (filename[0] != '/') /* it's a relative path, prefix with MODULE_ROOT_DIR */ { fullpath = rt_malloc(strlen(def_path) + strlen(filename) + 2); @@ -37,8 +37,7 @@ void* dlopen(const char *filename, int flags) } else { - rt_kprintf("use absolute path\n"); - return RT_NULL; + fullpath = (char*)filename; /* absolute path, use it directly */ } /* find in module list */ @@ -47,7 +46,11 @@ void* dlopen(const char *filename, int flags) if(module != RT_NULL) module->nref++; else module = rt_module_open(fullpath); - rt_free(fullpath); + if(fullpath != filename) + { + rt_free(fullpath); + } + return (void*)module; } diff --git a/components/net/lwip-2.0.0/src/arch/sys_arch.c b/components/net/lwip-2.0.0/src/arch/sys_arch.c index 7db873f130..c5b4dbbf47 100644 --- a/components/net/lwip-2.0.0/src/arch/sys_arch.c +++ b/components/net/lwip-2.0.0/src/arch/sys_arch.c @@ -600,7 +600,7 @@ u32_t sys_now(void) return rt_tick_get() * (1000 / RT_TICK_PER_SECOND); } -WEAK +RT_WEAK void mem_init(void) { } diff --git a/components/net/lwip-2.0.2/SConscript b/components/net/lwip-2.0.2/SConscript index 631e4c1e6b..fa8a087c8d 100644 --- a/components/net/lwip-2.0.2/SConscript +++ b/components/net/lwip-2.0.2/SConscript @@ -29,7 +29,6 @@ src/core/udp.c src/netif/ethernet.c src/netif/ethernetif.c src/netif/lowpan6.c -src/netif/slipif.c """) ipv4_src = Split(""" @@ -75,7 +74,7 @@ if GetDepend(['RT_LWIP_SNMP']): if GetDepend(['RT_LWIP_PPP']): src += ppp_src path += [GetCurrentDir() + '/src/netif/ppp'] - + group = DefineGroup('lwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP202'], CPPPATH = path) Return('group') diff --git a/components/net/lwip-2.0.2/src/apps/README.md b/components/net/lwip-2.0.2/src/apps/README.md new file mode 100644 index 0000000000..26670858c5 --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/README.md @@ -0,0 +1,6 @@ +Some net apps for current version LwIP. + +The RT-Thread develop team ported apps. It's easy to use it on finsh/msh. + +- ping +- tftp diff --git a/components/net/lwip-2.0.2/src/apps/SConscript b/components/net/lwip-2.0.2/src/apps/SConscript new file mode 100644 index 0000000000..2bc01cc16e --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/SConscript @@ -0,0 +1,13 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('tftp/*.c') + +if GetDepend(['RT_LWIP_ICMP', 'RT_LWIP_RAW']): + src += Glob('ping/*.c') + +CPPPATH = [cwd] + +group = DefineGroup('LwIP', src, depend = ['RT_USING_NETUTILS', 'RT_USING_LWIP202'], CPPPATH = CPPPATH) + +Return('group')
\ No newline at end of file diff --git a/components/net/lwip-2.0.2/src/apps/ping/ping.c b/components/net/lwip-2.0.2/src/apps/ping/ping.c new file mode 100644 index 0000000000..4b934f0cac --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/ping/ping.c @@ -0,0 +1,201 @@ +/* + * netutils: ping implementation + */ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/icmp.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/sockets.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" + +/** + * PING_DEBUG: Enable debugging for PING. + */ +#ifndef PING_DEBUG +#define PING_DEBUG LWIP_DBG_ON +#endif + +/** ping receive timeout - in milliseconds */ +#define PING_RCV_TIMEO rt_tick_from_millisecond(2000) +/** ping delay - in milliseconds */ +#define PING_DELAY rt_tick_from_millisecond(1000) + +/** ping identifier - must fit on a u16_t */ +#ifndef PING_ID +#define PING_ID 0xAFAF +#endif + +/** ping additional data size to include in the packet */ +#ifndef PING_DATA_SIZE +#define PING_DATA_SIZE 32 +#endif + +/* ping variables */ +static u16_t ping_seq_num; +struct _ip_addr +{ + rt_uint8_t addr0, addr1, addr2, addr3; +}; + +/** Prepare a echo ICMP request */ +static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) +{ + size_t i; + size_t data_len = len - sizeof(struct icmp_echo_hdr); + + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = PING_ID; + iecho->seqno = htons(++ping_seq_num); + + /* fill the additional data buffer with some data */ + for(i = 0; i < data_len; i++) + { + ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; + } + + iecho->chksum = inet_chksum(iecho, len); +} + +/* Ping using the socket ip */ +static err_t ping_send(int s, ip_addr_t *addr, int size) +{ + int err; + struct icmp_echo_hdr *iecho; + struct sockaddr_in to; + size_t ping_size = sizeof(struct icmp_echo_hdr) + size; + LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); + + iecho = rt_malloc(ping_size); + if (iecho == RT_NULL) + { + return ERR_MEM; + } + + ping_prepare_echo(iecho, (u16_t)ping_size); + + to.sin_len = sizeof(to); + to.sin_family = AF_INET; + to.sin_addr.s_addr = addr->addr; + + err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)); + rt_free(iecho); + + return (err == ping_size ? ERR_OK : ERR_VAL); +} + +static int ping_recv(int s, int *ttl) +{ + char buf[64]; + int fromlen = sizeof(struct sockaddr_in), len; + struct sockaddr_in from; + struct ip_hdr *iphdr; + struct icmp_echo_hdr *iecho; + + while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) + { + if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) + { + iphdr = (struct ip_hdr *)buf; + iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4)); + if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) + { + *ttl = iphdr->_ttl; + return len; + } + } + } + + return len; +} + +rt_err_t ping(char* target, rt_uint32_t times, rt_size_t size) +{ + int s, ttl, recv_len; + struct timeval timeout = { PING_RCV_TIMEO / RT_TICK_PER_SECOND, PING_RCV_TIMEO % RT_TICK_PER_SECOND }; + ip_addr_t ping_target; + rt_uint32_t send_times; + rt_tick_t recv_start_tick; + struct _ip_addr + { + rt_uint8_t addr0, addr1, addr2, addr3; + } *addr; + + send_times = 0; + ping_seq_num = 0; + + if(size == 0) + size = PING_DATA_SIZE; + + if (inet_aton(target, &ping_target) == 0) + { + rt_kprintf("ping: unknown host %s\n", target); + return -RT_ERROR; + } + addr = (struct _ip_addr*)&ping_target; + + if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) + { + rt_kprintf("ping: create socket failled\n"); + return -RT_ERROR; + } + + lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)); + + while (1) + { + if (ping_send(s, &ping_target, size) == ERR_OK) + { + recv_start_tick = rt_tick_get(); + if ((recv_len = ping_recv(s, &ttl)) >= 0) + { + rt_kprintf("%d bytes from %d.%d.%d.%d icmp_seq=%d ttl=%d time=%d ticks\n", recv_len, addr->addr0, + addr->addr1, addr->addr2, addr->addr3, send_times, ttl, rt_tick_get() - recv_start_tick); + } + else + { + rt_kprintf("From %d.%d.%d.%d icmp_seq=%d timeout\n", addr->addr0, addr->addr1, addr->addr2, + addr->addr3, send_times); + } + } + else + { + rt_kprintf("Send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3); + } + + send_times ++; + if (send_times >= times) break; /* send ping times reached, stop */ + + rt_thread_delay(PING_DELAY); /* take a delay */ + } + + lwip_close(s); + + return RT_EOK; +} +#ifdef RT_USING_FINSH +#include <finsh.h> + +FINSH_FUNCTION_EXPORT(ping, ping network host); + +int cmd_ping(int argc, char **argv) +{ + if (argc == 1) + { + rt_kprintf("Please input: ping <host address>\n"); + } + else + { + ping(argv[1], 4, 0); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_ping, __cmd_ping, ping network host); +#endif diff --git a/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c b/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c new file mode 100644 index 0000000000..129cc7da17 --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c @@ -0,0 +1,87 @@ +/* + * File : tftp_port.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017-08-17 armink first version. + */ + + +#include <rtthread.h> +#include <dfs_posix.h> +#include <lwip/apps/tftp_server.h> + +static struct tftp_context ctx; + +static void* tftp_open(const char* fname, const char* mode, u8_t write) +{ + int fd = -1; + + if (!rt_strcmp(mode, "octet")) + { + if (write) + { + fd = open(fname, O_WRONLY | O_CREAT, 0); + } + else + { + fd = open(fname, O_RDONLY, 0); + } + } + else + { + rt_kprintf("tftp: No support this mode(%s).", mode); + } + + return (void *) fd; +} + +static int tftp_write(void* handle, struct pbuf* p) +{ + int fd = (int) handle; + + return write(fd, p->payload, p->len); +} + +#if defined(RT_USING_FINSH) +#include <finsh.h> + +static void tftp_server(uint8_t argc, char **argv) +{ + ctx.open = tftp_open; + ctx.close = (void (*)(void *)) close; + ctx.read = (int (*)(void *, void *, int)) read; + ctx.write = tftp_write; + + if (tftp_init(&ctx) == ERR_OK) + { + rt_kprintf("TFTP server start successfully.\n"); + } + else + { + rt_kprintf("TFTP server start failed.\n"); + } +} +FINSH_FUNCTION_EXPORT(tftp_server, start tftp server.); + +#if defined(FINSH_USING_MSH) +MSH_CMD_EXPORT(tftp_server, start tftp server.); +#endif /* defined(FINSH_USING_MSH) */ + +#endif /* defined(RT_USING_FINSH) */ diff --git a/components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c b/components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c index 243b0924bd..afaa3bb08d 100644 --- a/components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c +++ b/components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c @@ -226,8 +226,8 @@ recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16 case PP_HTONS(TFTP_WRQ): { const char tftp_null = 0; - char filename[TFTP_MAX_FILENAME_LEN]; - char mode[TFTP_MAX_MODE_LEN]; + char filename[TFTP_MAX_FILENAME_LEN + 1] = { 0 }; + char mode[TFTP_MAX_MODE_LEN] = { 0 }; u16_t filename_end_offset; u16_t mode_end_offset; diff --git a/components/net/lwip-2.0.2/src/arch/sys_arch.c b/components/net/lwip-2.0.2/src/arch/sys_arch.c index 4cddf86eb6..bb809ac6ad 100644 --- a/components/net/lwip-2.0.2/src/arch/sys_arch.c +++ b/components/net/lwip-2.0.2/src/arch/sys_arch.c @@ -114,7 +114,7 @@ static void tcpip_init_done_callback(void *arg) netif_set_up(ethif->netif); #endif - if (!(ethif->flags & ETHIF_LINK_PHYUP)) + if (ethif->flags & ETHIF_LINK_PHYUP) { netif_set_link_up(ethif->netif); } @@ -177,7 +177,7 @@ int lwip_system_init(void) return 0; } -//INIT_COMPONENT_EXPORT(lwip_system_init); +INIT_COMPONENT_EXPORT(lwip_system_init); void sys_init(void) { @@ -602,7 +602,7 @@ u32_t sys_now(void) } -WEAK +RT_WEAK void mem_init(void) { } diff --git a/components/net/lwip-2.0.2/src/lwipopts.h b/components/net/lwip-2.0.2/src/lwipopts.h index 8afc0b97c4..d846cf2fb0 100644 --- a/components/net/lwip-2.0.2/src/lwipopts.h +++ b/components/net/lwip-2.0.2/src/lwipopts.h @@ -287,6 +287,12 @@ #define DEFAULT_UDP_RECVMBOX_SIZE 1 /* ---------- RAW options ---------- */ +#ifdef RT_LWIP_RAW +#define LWIP_RAW 1 +#else +#define LWIP_RAW 0 +#endif + #define DEFAULT_RAW_RECVMBOX_SIZE 1 #define DEFAULT_ACCEPTMBOX_SIZE 10 @@ -348,9 +354,30 @@ #endif /* PPP_SUPPORT */ -/* no read/write/close for socket */ -#define LWIP_POSIX_SOCKETS_IO_NAMES 0 -#define LWIP_NETIF_API 1 +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 1 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 1 +#endif /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. */ #define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT) @@ -419,4 +446,22 @@ #define SO_REUSE 0 #endif +/* + ------------------------------------ + ------- Applications options ------- + ------------------------------------ +*/ + +/** + * Max. length of TFTP filename + */ +#ifdef RT_LWIP_TFTP_MAX_FILENAME_LEN +#define TFTP_MAX_FILENAME_LEN RT_LWIP_TFTP_MAX_FILENAME_LEN +#elif defined(RT_DFS_ELM_MAX_LFN) +#define TFTP_MAX_FILENAME_LEN RT_DFS_ELM_MAX_LFN +#else +#define TFTP_MAX_FILENAME_LEN 64 +#endif + + #endif /* __LWIPOPTS_H__ */ diff --git a/components/net/lwip-2.0.2/src/netif/ethernetif.c b/components/net/lwip-2.0.2/src/netif/ethernetif.c index 4dca17b3e1..5b82649662 100644 --- a/components/net/lwip-2.0.2/src/netif/ethernetif.c +++ b/components/net/lwip-2.0.2/src/netif/ethernetif.c @@ -180,7 +180,7 @@ static err_t eth_netif_device_init(struct netif *netif) netif_set_up(ethif->netif); #endif - if (!(ethif->flags & ETHIF_LINK_PHYUP)) + if (ethif->flags & ETHIF_LINK_PHYUP) { /* set link_up for this netif */ netif_set_link_up(ethif->netif); @@ -451,7 +451,7 @@ int eth_system_device_init(void) return (int)result; } -//INIT_DEVICE_EXPORT(eth_system_device_init); +INIT_DEVICE_EXPORT(eth_system_device_init); #ifdef RT_USING_FINSH #include <finsh.h> diff --git a/components/net/netutils/README.md b/components/net/netutils/README.md new file mode 100644 index 0000000000..49545bab32 --- /dev/null +++ b/components/net/netutils/README.md @@ -0,0 +1 @@ +Some net utils which using standard interface such as BSD Sockets.
\ No newline at end of file diff --git a/components/net/netutils/SConscript b/components/net/netutils/SConscript new file mode 100644 index 0000000000..853b94a857 --- /dev/null +++ b/components/net/netutils/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +CPPPATH = [cwd] + +group = DefineGroup('LwIP', src, depend = ['RT_USING_NETUTILS'], CPPPATH = CPPPATH) + +Return('group')
\ No newline at end of file diff --git a/components/net/netutils/telnet.c b/components/net/netutils/telnet.c new file mode 100644 index 0000000000..d5c127b713 --- /dev/null +++ b/components/net/netutils/telnet.c @@ -0,0 +1,391 @@ +#include <rtthread.h> +#include <lwip/api.h> +#include <lwip/sockets.h> +#include <rtdevice.h> + +#include <finsh.h> +#include <shell.h> + +#define TELNET_PORT 23 +#define TELNET_BACKLOG 5 +#define RX_BUFFER_SIZE 256 +#define TX_BUFFER_SIZE 4096 + +#define ISO_nl 0x0a +#define ISO_cr 0x0d + +#define STATE_NORMAL 0 +#define STATE_IAC 1 +#define STATE_WILL 2 +#define STATE_WONT 3 +#define STATE_DO 4 +#define STATE_DONT 5 +#define STATE_CLOSE 6 + +#define TELNET_IAC 255 +#define TELNET_WILL 251 +#define TELNET_WONT 252 +#define TELNET_DO 253 +#define TELNET_DONT 254 + +struct telnet_session +{ + struct rt_ringbuffer rx_ringbuffer; + struct rt_ringbuffer tx_ringbuffer; + + rt_mutex_t rx_ringbuffer_lock; + rt_mutex_t tx_ringbuffer_lock; + + struct rt_device device; + rt_int32_t server_fd; + rt_int32_t client_fd; + + /* telnet protocol */ + rt_uint8_t state; + rt_uint8_t echo_mode; + +}; + +static struct telnet_session* telnet; + +/* process tx data */ +static void send_to_client(struct telnet_session* telnet) +{ + rt_size_t length; + rt_uint8_t tx_buffer[32]; + + while (1) + { + rt_memset(tx_buffer, 0, sizeof(tx_buffer)); + rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); + /* get buffer from ringbuffer */ + length = rt_ringbuffer_get(&(telnet->tx_ringbuffer), tx_buffer, sizeof(tx_buffer)); + rt_mutex_release(telnet->tx_ringbuffer_lock); + + /* do a tx procedure */ + if (length > 0) + { + send(telnet->client_fd, tx_buffer, length, 0); + } + else break; + } +} + +/* send telnet option to remote */ +static void send_option_to_client(struct telnet_session* telnet, rt_uint8_t option, rt_uint8_t value) +{ + rt_uint8_t optbuf[4]; + + optbuf[0] = TELNET_IAC; + optbuf[1] = option; + optbuf[2] = value; + optbuf[3] = 0; + + rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); + rt_ringbuffer_put(&telnet->tx_ringbuffer, optbuf, 3); + rt_mutex_release(telnet->tx_ringbuffer_lock); + + send_to_client(telnet); +} + +/* process rx data */ +static void process_rx(struct telnet_session* telnet, rt_uint8_t *data, rt_size_t length) +{ + rt_size_t rx_length, index; + + for (index = 0; index < length; index ++) + { + switch(telnet->state) + { + case STATE_IAC: + if (*data == TELNET_IAC) + { + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + /* put buffer to ringbuffer */ + rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data); + rt_mutex_release(telnet->rx_ringbuffer_lock); + + telnet->state = STATE_NORMAL; + } + else + { + /* set telnet state according to received package */ + switch (*data) + { + case TELNET_WILL: telnet->state = STATE_WILL; break; + case TELNET_WONT: telnet->state = STATE_WONT; break; + case TELNET_DO: telnet->state = STATE_DO; break; + case TELNET_DONT: telnet->state = STATE_DONT; break; + default: telnet->state = STATE_NORMAL; break; + } + } + break; + + /* don't option */ + case STATE_WILL: + case STATE_WONT: + send_option_to_client(telnet, TELNET_DONT, *data); + telnet->state = STATE_NORMAL; + break; + + /* won't option */ + case STATE_DO: + case STATE_DONT: + send_option_to_client(telnet, TELNET_WONT, *data); + telnet->state = STATE_NORMAL; + break; + + case STATE_NORMAL: + if (*data == TELNET_IAC) telnet->state = STATE_IAC; + else if (*data != '\r') /* ignore '\r' */ + { + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + /* put buffer to ringbuffer */ + rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data); + rt_mutex_release(telnet->rx_ringbuffer_lock); + } + break; + } + + data ++; + } + + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + /* get total size */ + rx_length = rt_ringbuffer_data_len(&telnet->rx_ringbuffer); + rt_mutex_release(telnet->rx_ringbuffer_lock); + + /* indicate there are reception data */ + if ((rx_length > 0) && (telnet->device.rx_indicate != RT_NULL)) + telnet->device.rx_indicate(&telnet->device, rx_length); + + return; +} + +/* client close */ +static void client_close(struct telnet_session* telnet) +{ + /* set console */ + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); + /* set finsh device */ + finsh_set_device(RT_CONSOLE_DEVICE_NAME); + + /* close connection */ + closesocket(telnet->client_fd); + + /* restore shell option */ + finsh_set_echo(telnet->echo_mode); + + rt_kprintf("resume console to %s\n", RT_CONSOLE_DEVICE_NAME); +} + +/* RT-Thread Device Driver Interface */ +static rt_err_t telnet_init(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_err_t telnet_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t telnet_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t telnet_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + rt_size_t result; + + /* read from rx ring buffer */ + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + result = rt_ringbuffer_get(&(telnet->rx_ringbuffer), buffer, size); + rt_mutex_release(telnet->rx_ringbuffer_lock); + + return result; +} + +static rt_size_t telnet_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + const rt_uint8_t *ptr; + + ptr = (rt_uint8_t*) buffer; + + rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); + while (size) + { + if (*ptr == '\n') + rt_ringbuffer_putchar(&telnet->tx_ringbuffer, '\r'); + + if (rt_ringbuffer_putchar(&telnet->tx_ringbuffer, *ptr) == 0) /* overflow */ + break; + ptr++; + size--; + } + rt_mutex_release(telnet->tx_ringbuffer_lock); + + /* send data to telnet client */ + send_to_client(telnet); + + return (rt_uint32_t) ptr - (rt_uint32_t) buffer; +} + +static rt_err_t telnet_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + return RT_EOK; +} + +/* telnet server thread entry */ +static void telnet_thread(void* parameter) +{ +#define RECV_BUF_LEN 64 + + struct sockaddr_in addr; + socklen_t addr_size; + rt_uint8_t recv_buf[RECV_BUF_LEN]; + rt_int32_t recv_len = 0; + + if ((telnet->server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + { + rt_kprintf("telnet: create socket failed\n"); + return; + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(TELNET_PORT); + addr.sin_addr.s_addr = INADDR_ANY; + rt_memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero)); + if (bind(telnet->server_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) + { + rt_kprintf("telnet: bind socket failed\n"); + return; + } + + if (listen(telnet->server_fd, TELNET_BACKLOG) == -1) + { + rt_kprintf("telnet: listen socket failed\n"); + return; + } + + /* register telnet device */ + telnet->device.type = RT_Device_Class_Char; + telnet->device.init = telnet_init; + telnet->device.open = telnet_open; + telnet->device.close = telnet_close; + telnet->device.read = telnet_read; + telnet->device.write = telnet_write; + telnet->device.control = telnet_control; + + /* no private */ + telnet->device.user_data = RT_NULL; + + /* register telnet device */ + rt_device_register(&telnet->device, "telnet", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM); + + while (1) + { + rt_kprintf("telnet server waiting for connection\n"); + + /* grab new connection */ + if ((telnet->client_fd = accept(telnet->server_fd, (struct sockaddr * )&addr, &addr_size)) == -1) + { + continue; + } + + rt_kprintf("new telnet client(%s:%d) connection, switch console to telnet...\n", inet_ntoa(addr.sin_addr), addr.sin_port); + + /* process the new connection */ + /* set console */ + rt_console_set_device("telnet"); + /* set finsh device */ + finsh_set_device("telnet"); + + /* set init state */ + telnet->state = STATE_NORMAL; + + telnet->echo_mode = finsh_get_echo(); + /* disable echo mode */ + finsh_set_echo(0); + + while (1) + { + /* try to send all data in tx ringbuffer */ + send_to_client(telnet); + + /* do a rx procedure */ + if ((recv_len = recv(telnet->client_fd, recv_buf, RECV_BUF_LEN, 0)) > 0) + { + process_rx(telnet, recv_buf, recv_len); + } + else + { + /* close connection */ + client_close(telnet); + break; + } + } + } +} + +/* telnet server */ +void telnet_srv(void) +{ + rt_thread_t tid; + + if (telnet == RT_NULL) + { + rt_uint8_t *ptr; + + telnet = rt_malloc(sizeof(struct telnet_session)); + if (telnet == RT_NULL) + { + rt_kprintf("telnet: no memory\n"); + return; + } + /* init ringbuffer */ + ptr = rt_malloc(RX_BUFFER_SIZE); + if (ptr) + { + rt_ringbuffer_init(&telnet->rx_ringbuffer, ptr, RX_BUFFER_SIZE); + } + else + { + rt_kprintf("telnet: no memory\n"); + return; + } + ptr = rt_malloc(TX_BUFFER_SIZE); + if (ptr) + { + rt_ringbuffer_init(&telnet->tx_ringbuffer, ptr, TX_BUFFER_SIZE); + } + else + { + rt_kprintf("telnet: no memory\n"); + return; + } + /* create tx ringbuffer lock */ + telnet->tx_ringbuffer_lock = rt_mutex_create("telnet_tx", RT_IPC_FLAG_FIFO); + /* create rx ringbuffer lock */ + telnet->rx_ringbuffer_lock = rt_mutex_create("telnet_rx", RT_IPC_FLAG_FIFO); + + tid = rt_thread_create("telnet", telnet_thread, RT_NULL, 2048, 25, 5); + if (tid != RT_NULL) + rt_thread_startup(tid); + } + else + { + rt_kprintf("telnet: already running\n"); + } + +} + +#ifdef RT_USING_FINSH +#include <finsh.h> +FINSH_FUNCTION_EXPORT(telnet_srv, startup telnet server); +#ifdef FINSH_USING_MSH +MSH_CMD_EXPORT(telnet_srv, startup telnet server) +#endif /* FINSH_USING_MSH */ +#endif /* RT_USING_FINSH */ diff --git a/components/utilities/logtrace/log_file.c b/components/utilities/logtrace/log_file.c index 2f4a28b63c..7a77008798 100644 --- a/components/utilities/logtrace/log_file.c +++ b/components/utilities/logtrace/log_file.c @@ -93,6 +93,25 @@ static rt_size_t fdevice_write(rt_device_t dev, rt_off_t pos, const void *buffer return write(fdev->fd, buffer, size); } +static rt_err_t fdevice_control(rt_device_t dev, rt_uint8_t cmd, void *arg) +{ + struct file_device *fdev = (struct file_device *)dev; + + if (fdev->fd < 0) + return 0; + + switch (cmd) + { + case LOG_TRACE_CTRL_FLUSH: + if (fsync(fdev->fd) != 0) + return RT_ERROR; + break; + default: + break; + } + return RT_EOK; +} + void log_trace_file_init(const char *filename) { rt_device_t device; @@ -104,10 +123,11 @@ void log_trace_file_init(const char *filename) _file_device.parent.type = RT_Device_Class_Char; - _file_device.parent.init = RT_NULL; - _file_device.parent.open = fdevice_open; - _file_device.parent.close = fdevice_close; - _file_device.parent.write = fdevice_write; + _file_device.parent.init = RT_NULL; + _file_device.parent.open = fdevice_open; + _file_device.parent.close = fdevice_close; + _file_device.parent.write = fdevice_write; + _file_device.parent.control = fdevice_control; rt_device_register(&_file_device.parent, "logfile", O_RDWR); } |
