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/drivers | |
| parent | e9a77b513f0a4b37d539a030592a61b08d03602d (diff) | |
| parent | 3691b67e83ab57196dfc62606b1be18db76994a7 (diff) | |
Merge branch 'master' of https://github.com/RT-Thread/rt-thread
Diffstat (limited to 'components/drivers')
21 files changed, 776 insertions, 842 deletions
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 ); } |
