From 981d929b562610328309ee4e01d66727f5e6896e Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 19 Aug 2013 10:50:20 +0800 Subject: [PATCH 01/28] ringbuffer: fix the ambiguous name RT_RINGBUFFER_SIZE could mean "the size of the whole buffer", "the size of the empty space" or "the size of the data". Moreover, it's never a micro anymore. Change it to rt_ringbuffer_data_len before it's too late. Also, RT_RINGBUFFER_EMPTY is changed to rt_ringbuffer_space_len. --- components/drivers/include/rtdevice.h | 53 ++++++++++--------- components/drivers/src/ringbuffer.c | 8 +-- .../drivers/usb/usbdevice/class/cdc_vcom.c | 10 ++-- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index f8a944f5a7..a941b22131 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -45,9 +45,9 @@ struct rt_ringbuffer /* use the msb of the {read,write}_index as mirror bit. You can see this as * if the buffer adds a virtual mirror and the pointers point either to the * normal or to the mirrored buffer. If the write_index has the same value - * with the read_index, but in differenct mirro, the buffer is full. While - * if the write_index and the read_index are the same and within the same - * mirror, the buffer is empty. The ASCII art of the ringbuffer is: + * with the read_index, but in a different mirror, the buffer is full. + * While if the write_index and the read_index are the same and within the + * same mirror, the buffer is empty. The ASCII art of the ringbuffer is: * * mirror = 0 mirror = 1 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+ @@ -73,29 +73,6 @@ struct rt_ringbuffer rt_int16_t buffer_size; }; -/** return the size of data in rb */ -rt_inline rt_uint16_t RT_RINGBUFFER_SIZE(struct rt_ringbuffer *rb) -{ - if (rb->read_index == rb->write_index) - { - if (rb->read_mirror == rb->write_mirror) - /* we are in the same side, the ringbuffer is empty. */ - return 0; - else - return rb->buffer_size; - } - else - { - if (rb->write_index > rb->read_index) - return rb->write_index - rb->read_index; - else - return rb->buffer_size - (rb->read_index - rb->write_index); - } -} - -/** return the size of empty space in rb */ -#define RT_RINGBUFFER_EMPTY(rb) ((rb)->buffer_size - RT_RINGBUFFER_SIZE(rb)) - /* pipe device */ #define PIPE_DEVICE(device) ((struct rt_pipe_device*)(device)) struct rt_pipe_device @@ -163,12 +140,36 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_uint8_t *ptr, rt_uint16_t length); rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch); + rt_inline rt_uint16_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb) { RT_ASSERT(rb != RT_NULL); return rb->buffer_size; } +/** return the size of data in rb */ +rt_inline rt_uint16_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb) +{ + if (rb->read_index == rb->write_index) + { + if (rb->read_mirror == rb->write_mirror) + /* we are in the same side, the ringbuffer is empty. */ + return 0; + else + return rb->buffer_size; + } + else + { + if (rb->write_index > rb->read_index) + return rb->write_index - rb->read_index; + else + return rb->buffer_size - (rb->read_index - rb->write_index); + } +} + +/** return the size of empty space in rb */ +#define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb)) + /** * Pipe Device */ diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index 8e7e8c7895..ecc2587042 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -53,7 +53,7 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, RT_ASSERT(rb != RT_NULL); /* whether has enough space */ - size = RT_RINGBUFFER_EMPTY(rb); + size = rt_ringbuffer_space_len(rb); /* no space */ if (size == 0) @@ -100,7 +100,7 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, RT_ASSERT(rb != RT_NULL); /* whether has enough data */ - size = RT_RINGBUFFER_SIZE(rb); + size = rt_ringbuffer_data_len(rb); /* no data */ if (size == 0) @@ -143,7 +143,7 @@ rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch) RT_ASSERT(rb != RT_NULL); /* whether has enough space */ - if (!RT_RINGBUFFER_EMPTY(rb)) + if (!rt_ringbuffer_space_len(rb)) return 0; rb->buffer_ptr[rb->write_index] = ch; @@ -171,7 +171,7 @@ rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch) RT_ASSERT(rb != RT_NULL); /* ringbuffer is empty */ - if (!RT_RINGBUFFER_SIZE(rb)) + if (!rt_ringbuffer_data_len(rb)) return 0; /* put character */ diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index 1dee3a4d79..5f284b0294 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -188,7 +188,7 @@ static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size) eps = (cdc_eps_t)cls->eps; level = rt_hw_interrupt_disable(); - remain = RT_RINGBUFFER_SIZE(&tx_ringbuffer); + remain = rt_ringbuffer_data_len(&tx_ringbuffer); if (remain != 0) { /* although vcom_in_sending is set in SOF handler in the very @@ -453,7 +453,7 @@ static rt_err_t _class_sof_handler(udevice_t device, uclass_t cls) eps = (cdc_eps_t)cls->eps; - size = RT_RINGBUFFER_SIZE(&tx_ringbuffer); + size = rt_ringbuffer_data_len(&tx_ringbuffer); if (size == 0) return -RT_EFULL; @@ -611,7 +611,7 @@ static int _vcom_putc(struct rt_serial_device *serial, char c) * data out soon. But we cannot rely on that and if we wait to long, just * return. */ for (cnt = 500; - RT_RINGBUFFER_EMPTY(&tx_ringbuffer) == 0 && cnt; + rt_ringbuffer_space_len(&tx_ringbuffer) == 0 && cnt; cnt--) { /*rt_kprintf("wait for %d\n", cnt);*/ @@ -628,7 +628,7 @@ static int _vcom_putc(struct rt_serial_device *serial, char c) } level = rt_hw_interrupt_disable(); - if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer)) + if (rt_ringbuffer_space_len(&tx_ringbuffer)) { rt_ringbuffer_putchar(&tx_ringbuffer, c); } @@ -646,7 +646,7 @@ static int _vcom_getc(struct rt_serial_device *serial) result = -1; level = rt_hw_interrupt_disable(); - if (RT_RINGBUFFER_SIZE(&rx_ringbuffer)) + if (rt_ringbuffer_data_len(&rx_ringbuffer)) { rt_ringbuffer_getchar(&rx_ringbuffer, &ch); result = ch; From 4919d29d693491e8eae9697deed7b808c7bcbb93 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 19 Aug 2013 11:52:04 +0800 Subject: [PATCH 02/28] ringbuffer: add put_force and putchar_force API Add the APIs that will discard the old data when rb is full. --- components/drivers/include/rtdevice.h | 38 +++++++++-- components/drivers/src/ringbuffer.c | 93 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index a941b22131..bd6e243b0a 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -134,37 +134,61 @@ void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length); +rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, + const rt_uint8_t *ptr, + rt_uint16_t length); rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch); +rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, + const rt_uint8_t ch); rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_uint8_t *ptr, rt_uint16_t length); rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch); +enum rt_ringbuffer_state +{ + RT_RINGBUFFER_EMPTY, + RT_RINGBUFFER_FULL, + /* half full is neither full nor empty */ + RT_RINGBUFFER_HALFFULL, +}; + rt_inline rt_uint16_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb) { RT_ASSERT(rb != RT_NULL); return rb->buffer_size; } -/** return the size of data in rb */ -rt_inline rt_uint16_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb) +rt_inline enum rt_ringbuffer_state +rt_ringbuffer_status(struct rt_ringbuffer *rb) { if (rb->read_index == rb->write_index) { if (rb->read_mirror == rb->write_mirror) - /* we are in the same side, the ringbuffer is empty. */ - return 0; + return RT_RINGBUFFER_EMPTY; else - return rb->buffer_size; + return RT_RINGBUFFER_FULL; } - else + return RT_RINGBUFFER_HALFFULL; +} + +/** return the size of data in rb */ +rt_inline rt_uint16_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb) +{ + switch (rt_ringbuffer_status(rb)) { + case RT_RINGBUFFER_EMPTY: + return 0; + case RT_RINGBUFFER_FULL: + return rb->buffer_size; + case RT_RINGBUFFER_HALFFULL: + default: if (rb->write_index > rb->read_index) return rb->write_index - rb->read_index; else return rb->buffer_size - (rb->read_index - rb->write_index); - } + }; } /** return the size of empty space in rb */ diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index ecc2587042..6212b10258 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -44,6 +44,9 @@ void rt_ringbuffer_init(struct rt_ringbuffer *rb, } RTM_EXPORT(rt_ringbuffer_init); +/** + * put a block of data into ring buffer + */ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length) @@ -88,6 +91,59 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, } RTM_EXPORT(rt_ringbuffer_put); +/** + * put a block of data into ring buffer + * + * When the buffer is full, it will discard the old data. + */ +rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, + const rt_uint8_t *ptr, + rt_uint16_t length) +{ + enum rt_ringbuffer_state old_state; + + RT_ASSERT(rb != RT_NULL); + + old_state = rt_ringbuffer_status(rb); + + if (length > rb->buffer_size) + length = rb->buffer_size; + + if (rb->buffer_size - rb->write_index > length) + { + /* read_index - write_index = empty space */ + memcpy(&rb->buffer_ptr[rb->write_index], ptr, length); + /* this should not cause overflow because there is enough space for + * length of data in current mirror */ + rb->write_index += length; + + if (old_state == RT_RINGBUFFER_FULL) + rb->read_index = rb->write_index; + + return length; + } + + memcpy(&rb->buffer_ptr[rb->write_index], + &ptr[0], + rb->buffer_size - rb->write_index); + memcpy(&rb->buffer_ptr[0], + &ptr[rb->buffer_size - rb->write_index], + length - (rb->buffer_size - rb->write_index)); + + /* we are going into the other side of the mirror */ + rb->write_mirror = ~rb->write_mirror; + rb->write_index = length - (rb->buffer_size - rb->write_index); + + if (old_state == RT_RINGBUFFER_FULL) + { + rb->read_mirror = ~rb->read_mirror; + rb->read_index = rb->write_index; + } + + return length; +} +RTM_EXPORT(rt_ringbuffer_put_force); + /** * get data from ring buffer */ @@ -163,6 +219,43 @@ rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch) } RTM_EXPORT(rt_ringbuffer_putchar); +/** + * put a character into ring buffer + * + * When the buffer is full, it will discard one old data. + */ +rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch) +{ + enum rt_ringbuffer_state old_state; + + RT_ASSERT(rb != RT_NULL); + + old_state = rt_ringbuffer_status(rb); + + rb->buffer_ptr[rb->write_index] = ch; + + /* flip mirror */ + if (rb->write_index == rb->buffer_size-1) + { + rb->write_mirror = ~rb->write_mirror; + rb->write_index = 0; + if (old_state == RT_RINGBUFFER_FULL) + { + rb->read_mirror = ~rb->read_mirror; + rb->read_index = rb->write_index; + } + } + else + { + rb->write_index++; + if (old_state == RT_RINGBUFFER_FULL) + rb->read_index = rb->write_index; + } + + return 1; +} +RTM_EXPORT(rt_ringbuffer_putchar_force); + /** * get a character from a ringbuffer */ From d683d32bd5502c15be600145966400a41710a7f4 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 19 Aug 2013 15:35:56 +0800 Subject: [PATCH 03/28] device/pipe: add nonblocking read/write and force write mode The previous implementation will always blocks the reader/writer. However, at least FinSh would expect the device to be nonblocking --- read should return 0 when there is no data in it. --- components/drivers/include/rtdevice.h | 19 +++- components/drivers/src/pipe.c | 127 +++++++++++++++++--------- 2 files changed, 104 insertions(+), 42 deletions(-) diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index bd6e243b0a..734839e69e 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -75,6 +75,20 @@ struct rt_ringbuffer /* pipe device */ #define PIPE_DEVICE(device) ((struct rt_pipe_device*)(device)) +enum rt_pipe_flag +{ + /* both read and write won't block */ + RT_PIPE_FLAG_NONBLOCK_RDWR = 0x00, + /* read would block */ + RT_PIPE_FLAG_BLOCK_RD = 0x01, + /* write would block */ + RT_PIPE_FLAG_BLOCK_WR = 0x02, + /* write to this pipe will discard some data when the pipe is full. + * When this flag is set, RT_PIPE_FLAG_BLOCK_WR will be ignored since write + * operation will always be success. */ + RT_PIPE_FLAG_FORCE_WR = 0x04, +}; + struct rt_pipe_device { struct rt_device parent; @@ -82,6 +96,8 @@ struct rt_pipe_device /* ring buffer in pipe device */ struct rt_ringbuffer ringbuffer; + enum rt_pipe_flag flag; + /* suspended list */ rt_list_t suspended_read_list; rt_list_t suspended_write_list; @@ -199,11 +215,12 @@ rt_inline rt_uint16_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb) */ rt_err_t rt_pipe_init(struct rt_pipe_device *pipe, const char *name, + enum rt_pipe_flag flag, rt_uint8_t *buf, rt_size_t size); rt_err_t rt_pipe_detach(struct rt_pipe_device *pipe); #ifdef RT_USING_HEAP -rt_err_t rt_pipe_create(const char *name, rt_size_t size); +rt_err_t rt_pipe_create(const char *name, enum rt_pipe_flag flag, rt_size_t size); void rt_pipe_destroy(struct rt_pipe_device *pipe); #endif diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 469c2d06e6..f01244ce22 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -26,6 +26,26 @@ #include #include +static void _rt_pipe_resume_writer(struct rt_pipe_device *pipe) +{ + if (!rt_list_isempty(&pipe->suspended_write_list)) + { + rt_thread_t thread; + + RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_WR); + + /* get suspended thread */ + thread = rt_list_entry(pipe->suspended_write_list.next, + struct rt_thread, + tlist); + + /* resume the write thread */ + rt_thread_resume(thread); + + rt_schedule(); + } +} + static rt_size_t rt_pipe_read(rt_device_t dev, rt_off_t pos, void *buffer, @@ -39,13 +59,26 @@ static rt_size_t rt_pipe_read(rt_device_t dev, pipe = PIPE_DEVICE(dev); RT_ASSERT(pipe != RT_NULL); + if (!(pipe->flag & RT_PIPE_FLAG_BLOCK_RD)) + { + level = rt_hw_interrupt_disable(); + read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); + + /* if the ringbuffer is empty, there won't be any writer waiting */ + if (read_nbytes) + _rt_pipe_resume_writer(pipe); + + rt_hw_interrupt_enable(level); + + return read_nbytes; + } + thread = rt_thread_self(); /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do - { + do { level = rt_hw_interrupt_disable(); read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); if (read_nbytes == 0) @@ -60,23 +93,8 @@ static rt_size_t rt_pipe_read(rt_device_t dev, } else { - if (!rt_list_isempty(&pipe->suspended_write_list)) - { - /* get suspended thread */ - thread = rt_list_entry(pipe->suspended_write_list.next, - struct rt_thread, - tlist); - - /* resume the write thread */ - rt_thread_resume(thread); - rt_hw_interrupt_enable(level); - - rt_schedule(); - } - else - { - rt_hw_interrupt_enable(level); - } + _rt_pipe_resume_writer(pipe); + rt_hw_interrupt_enable(level); break; } } while (read_nbytes == 0); @@ -84,6 +102,26 @@ static rt_size_t rt_pipe_read(rt_device_t dev, return read_nbytes; } +static void _rt_pipe_resume_reader(struct rt_pipe_device *pipe) +{ + if (!rt_list_isempty(&pipe->suspended_read_list)) + { + rt_thread_t thread; + + RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_RD); + + /* get suspended thread */ + thread = rt_list_entry(pipe->suspended_read_list.next, + struct rt_thread, + tlist); + + /* resume the read thread */ + rt_thread_resume(thread); + + rt_schedule(); + } +} + struct rt_pipe_device *_pipe = RT_NULL; static rt_size_t rt_pipe_write(rt_device_t dev, rt_off_t pos, @@ -100,13 +138,31 @@ static rt_size_t rt_pipe_write(rt_device_t dev, if (_pipe == RT_NULL) _pipe = pipe; + if ((pipe->flag & RT_PIPE_FLAG_FORCE_WR) || + !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) + { + level = rt_hw_interrupt_disable(); + + if (pipe->flag & RT_PIPE_FLAG_FORCE_WR) + write_nbytes = rt_ringbuffer_put_force(&(pipe->ringbuffer), + buffer, size); + else + write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), + buffer, size); + + _rt_pipe_resume_reader(pipe); + + rt_hw_interrupt_enable(level); + + return write_nbytes; + } + thread = rt_thread_self(); /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do - { + do { level = rt_hw_interrupt_disable(); write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), buffer, size); if (write_nbytes == 0) @@ -122,26 +178,11 @@ static rt_size_t rt_pipe_write(rt_device_t dev, } else { - if (!rt_list_isempty(&pipe->suspended_read_list)) - { - /* get suspended thread */ - thread = rt_list_entry(pipe->suspended_read_list.next, - struct rt_thread, - tlist); - - /* resume the read thread */ - rt_thread_resume(thread); - rt_hw_interrupt_enable(level); - - rt_schedule(); - } - else - { - rt_hw_interrupt_enable(level); - } + _rt_pipe_resume_reader(pipe); + rt_hw_interrupt_enable(level); break; } - }while (write_nbytes == 0); + } while (write_nbytes == 0); return write_nbytes; } @@ -157,6 +198,7 @@ static rt_err_t rt_pipe_control(rt_device_t dev, rt_uint8_t cmd, void *args) * * @param pipe the pipe device * @param name the name of pipe device + * @param flag the attribute of the pipe device * @param buf the buffer of pipe device * @param size the size of pipe device buffer * @@ -164,6 +206,7 @@ static rt_err_t rt_pipe_control(rt_device_t dev, rt_uint8_t cmd, void *args) */ rt_err_t rt_pipe_init(struct rt_pipe_device *pipe, const char *name, + enum rt_pipe_flag flag, rt_uint8_t *buf, rt_size_t size) { @@ -177,6 +220,8 @@ rt_err_t rt_pipe_init(struct rt_pipe_device *pipe, /* initialize ring buffer */ rt_ringbuffer_init(&pipe->ringbuffer, buf, size); + pipe->flag = flag; + /* create pipe */ pipe->parent.type = RT_Device_Class_Char; pipe->parent.init = RT_NULL; @@ -204,7 +249,7 @@ rt_err_t rt_pipe_detach(struct rt_pipe_device *pipe) RTM_EXPORT(rt_pipe_detach); #ifdef RT_USING_HEAP -rt_err_t rt_pipe_create(const char *name, rt_size_t size) +rt_err_t rt_pipe_create(const char *name, enum rt_pipe_flag flag, rt_size_t size) { rt_uint8_t *rb_memptr = RT_NULL; struct rt_pipe_device *pipe = RT_NULL; @@ -223,7 +268,7 @@ rt_err_t rt_pipe_create(const char *name, rt_size_t size) return -RT_ENOMEM; } - return rt_pipe_init(pipe, name, rb_memptr, size); + return rt_pipe_init(pipe, name, flag, rb_memptr, size); } RTM_EXPORT(rt_pipe_create); From e8cca2315a790d61c743a71e1a682e6ace7866fd Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 19 Aug 2013 15:57:59 +0800 Subject: [PATCH 04/28] dev/pipe: call rx_indicate the time we resume reader Some reader(FinSh again) would like to block on a semaphore which is released in rx_indicate. So we should invoke rx_indicate in _rt_pipe_resume_reader. --- components/drivers/src/pipe.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index f01244ce22..f0368e87db 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -104,6 +104,10 @@ static rt_size_t rt_pipe_read(rt_device_t dev, static void _rt_pipe_resume_reader(struct rt_pipe_device *pipe) { + if (pipe->parent.rx_indicate) + pipe->parent.rx_indicate(&pipe->parent, + rt_ringbuffer_data_len(&pipe->ringbuffer)); + if (!rt_list_isempty(&pipe->suspended_read_list)) { rt_thread_t thread; From 0340300f89a924b30fd8042b76686a236720d3d7 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 19 Aug 2013 16:25:17 +0800 Subject: [PATCH 05/28] dev/pipe: cleanup --- components/drivers/src/pipe.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index f0368e87db..3f14e6a837 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -126,7 +126,6 @@ static void _rt_pipe_resume_reader(struct rt_pipe_device *pipe) } } -struct rt_pipe_device *_pipe = RT_NULL; static rt_size_t rt_pipe_write(rt_device_t dev, rt_off_t pos, const void *buffer, @@ -139,8 +138,6 @@ static rt_size_t rt_pipe_write(rt_device_t dev, pipe = PIPE_DEVICE(dev); RT_ASSERT(pipe != RT_NULL); - if (_pipe == RT_NULL) - _pipe = pipe; if ((pipe->flag & RT_PIPE_FLAG_FORCE_WR) || !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) From 7e68096a88aaa9279507df54da191893be99f7df Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 20 Aug 2013 10:16:55 +0800 Subject: [PATCH 06/28] dev/pipe: make pipe a type of device Pipe have many differences with char device. The main difference is altough pipe have both read and write, it is unidirectional in nature. --- components/drivers/src/pipe.c | 2 +- include/rtdef.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 3f14e6a837..8a6c97aabf 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -224,7 +224,7 @@ rt_err_t rt_pipe_init(struct rt_pipe_device *pipe, pipe->flag = flag; /* create pipe */ - pipe->parent.type = RT_Device_Class_Char; + pipe->parent.type = RT_Device_Class_Pipe; pipe->parent.init = RT_NULL; pipe->parent.open = RT_NULL; pipe->parent.close = RT_NULL; diff --git a/include/rtdef.h b/include/rtdef.h index a3d13bfc44..6caf713f45 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -739,6 +739,7 @@ enum rt_device_class_type RT_Device_Class_SPIDevice, /**< SPI device */ RT_Device_Class_SDIO, /**< SDIO bus device */ RT_Device_Class_PM, /**< PM pseudo device */ + RT_Device_Class_Pipe, /**< Pipe device */ RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ RT_Device_Class_Unknown /**< unknown device */ }; From 6e676e7754e9042c333ff7f3826766c6462f92be Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 20 Aug 2013 10:48:15 +0800 Subject: [PATCH 07/28] dev/portal: implement portal device Portal is a device that connect devices. Currently, you can only connect pipes in portal. Pipes are unidirectional. But with portal, you can construct a bidirectional device with two pipes. --- components/drivers/include/rtdevice.h | 28 +++ components/drivers/src/portal.c | 251 ++++++++++++++++++++++++++ include/rtdef.h | 1 + 3 files changed, 280 insertions(+) create mode 100644 components/drivers/src/portal.c diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index 734839e69e..60d4dc1e8a 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -73,6 +73,14 @@ struct rt_ringbuffer rt_int16_t buffer_size; }; +/* portal device */ +struct rt_portal_device +{ + struct rt_device parent; + struct rt_device *write_dev; + struct rt_device *read_dev; +}; + /* pipe device */ #define PIPE_DEVICE(device) ((struct rt_pipe_device*)(device)) enum rt_pipe_flag @@ -101,6 +109,9 @@ struct rt_pipe_device /* suspended list */ rt_list_t suspended_read_list; rt_list_t suspended_write_list; + + struct rt_portal_device *write_portal; + struct rt_portal_device *read_portal; }; #define RT_DATAQUEUE_EVENT_UNKNOWN 0x00 @@ -224,6 +235,23 @@ rt_err_t rt_pipe_create(const char *name, enum rt_pipe_flag flag, rt_size_t size void rt_pipe_destroy(struct rt_pipe_device *pipe); #endif +/** + * Portal for DeviceDriver + */ + +rt_err_t rt_portal_init(struct rt_portal_device *portal, + const char *portal_name, + const char *write_dev, + const char *read_dev); +rt_err_t rt_portal_detach(struct rt_portal_device *portal); + +#ifdef RT_USING_HEAP +rt_err_t rt_portal_create(const char *name, + const char *write_dev, + const char *read_dev); +void rt_portal_destroy(struct rt_portal_device *portal); +#endif + /** * DataQueue for DeviceDriver */ diff --git a/components/drivers/src/portal.c b/components/drivers/src/portal.c new file mode 100644 index 0000000000..82d9d4e802 --- /dev/null +++ b/components/drivers/src/portal.c @@ -0,0 +1,251 @@ +/* + * File : portal.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013, 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 + * 2013-08-19 Grissiom initial version + */ + +#include +#include + +#define PT_WRITE_DEV(pt) (((struct rt_portal_device*)pt)->write_dev) +#define PT_READ_DEV(pt) (((struct rt_portal_device*)pt)->read_dev) + +static rt_err_t _portal_init(rt_device_t dev) +{ + rt_err_t err; + struct rt_portal_device *portal; + + RT_ASSERT(dev); + + portal = (struct rt_portal_device*)dev; + + err = rt_device_init(portal->write_dev); + if (err != RT_EOK) + return err; + + err = rt_device_init(portal->read_dev); + + return err; +} + +static rt_err_t _portal_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_err_t err; + struct rt_portal_device *portal; + + RT_ASSERT(dev); + + portal = (struct rt_portal_device*)dev; + + if (oflag & RT_DEVICE_OFLAG_RDONLY) + { + err = rt_device_open(portal->read_dev, RT_DEVICE_OFLAG_RDONLY); + if (err != RT_EOK) + return err; + } + + if (oflag & RT_DEVICE_OFLAG_WRONLY) + { + err = rt_device_open(portal->write_dev, RT_DEVICE_OFLAG_WRONLY); + if (err != RT_EOK) + return err; + } + + return RT_EOK; +} + +static rt_err_t _portal_close(rt_device_t dev) +{ + struct rt_portal_device *portal; + + RT_ASSERT(dev); + + portal = (struct rt_portal_device*)dev; + + rt_device_close(portal->write_dev); + rt_device_close(portal->read_dev); + + return RT_EOK; +} + +static rt_size_t _portal_read(rt_device_t dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + return rt_device_read(PT_READ_DEV(dev), + pos, buffer, size); +} + +static rt_size_t _portal_write(rt_device_t dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + return rt_device_write(PT_WRITE_DEV(dev), + pos, buffer, size); +} + +static rt_err_t _portal_rx_indicate(rt_device_t dev, rt_size_t size) +{ + struct rt_pipe_device *pipe; + + RT_ASSERT(dev && dev->type == RT_Device_Class_Pipe); + + pipe = (struct rt_pipe_device*)dev; + + if (pipe->read_portal->parent.rx_indicate) + return pipe->read_portal->parent.rx_indicate(dev, size); + + return -RT_ENOSYS; +} + +static rt_err_t _portal_tx_complete(rt_device_t dev, void *buf) +{ + struct rt_pipe_device *pipe; + + RT_ASSERT(dev && dev->type == RT_Device_Class_Pipe); + + pipe = (struct rt_pipe_device*)dev; + + if (pipe->write_portal->parent.tx_complete) + return pipe->write_portal->parent.tx_complete(dev, buf); + + return -RT_ENOSYS; +} + +/** + * This function will initialize a portal device and put it under control of + * resource management. + * + * Portal is a device that connect devices + * + * Currently, you can only connect pipes in portal. Pipes are unidirectional. + * But with portal, you can construct a bidirectional device with two pipes. + * The inner connection is just like this: + * + * portal0 portal1 + * read || || write + * <--<---||<---<---||<---<-- (pipe0) + * || || + * -->--->||--->--->||--->--> (pipe1) + * write || || read + * + * You will always construct two portals on two pipes, say, "portal0" and + * "portal1". Data written into "portal0" can be retrieved in "portal1" and + * vice versa. `rx_indicate` and `tx_complete` events are propagated + * accordingly. + * + * @param portal the portal device + * @param portal_name the name of the portal device + * @param write_dev the name of the pipe device that this portal write into + * @param read_dev the name of the pipe device that this portal read from + * + * @return the operation status, RT_EOK on successful. -RT_ENOSYS on one pipe + * device could not be found. + */ +rt_err_t rt_portal_init(struct rt_portal_device *portal, + const char *portal_name, + const char *write_dev, + const char *read_dev) +{ + rt_device_t dev; + + RT_ASSERT(portal); + + portal->parent.type = RT_Device_Class_Portal; + portal->parent.init = _portal_init; + portal->parent.open = _portal_open; + portal->parent.close = _portal_close; + portal->parent.write = _portal_write; + portal->parent.read = _portal_read; + /* single control of the two devices makes no sense */ + portal->parent.control = RT_NULL; + + dev = rt_device_find(write_dev); + if (dev == RT_NULL) + return -RT_ENOSYS; + RT_ASSERT(dev->type == RT_Device_Class_Pipe); + portal->write_dev = dev; + rt_device_set_tx_complete(&portal->parent, dev->tx_complete); + rt_device_set_tx_complete(dev, _portal_tx_complete); + ((struct rt_pipe_device*)dev)->write_portal = portal; + + dev = rt_device_find(read_dev); + if (dev == RT_NULL) + { + rt_device_set_tx_complete(dev, portal->parent.tx_complete); + return -RT_ENOSYS; + } + RT_ASSERT(dev->type == RT_Device_Class_Pipe); + portal->read_dev = dev; + rt_device_set_rx_indicate(&portal->parent, dev->rx_indicate); + rt_device_set_rx_indicate(dev, _portal_rx_indicate); + ((struct rt_pipe_device*)dev)->read_portal = portal; + + return rt_device_register(&(portal->parent), + portal_name, + RT_DEVICE_FLAG_RDWR); +} +RTM_EXPORT(rt_portal_init); + +/** + * This function will detach a portal device from resource management + * + * @param portal the portal device + * + * @return the operation status, RT_EOK on successful + */ +rt_err_t rt_portal_detach(struct rt_portal_device *portal) +{ + return rt_device_unregister(&portal->parent); +} +RTM_EXPORT(rt_portal_detach); + +#ifdef RT_USING_HEAP +rt_err_t rt_portal_create(const char *name, + const char *write_dev, + const char *read_dev) +{ + struct rt_portal_device *portal; + + portal = (struct rt_portal_device*)rt_calloc(1, sizeof(*portal)); + if (portal == RT_NULL) + return -RT_ENOMEM; + + return rt_portal_init(portal, name, write_dev, read_dev); +} +RTM_EXPORT(rt_portal_create); + +void rt_portal_destroy(struct rt_portal_device *portal) +{ + if (portal == RT_NULL) + return; + + rt_portal_detach(portal); + + rt_free(portal); + + return; +} +RTM_EXPORT(rt_portal_destroy); +#endif /* RT_USING_HEAP */ + diff --git a/include/rtdef.h b/include/rtdef.h index 6caf713f45..09574d2233 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -740,6 +740,7 @@ enum rt_device_class_type RT_Device_Class_SDIO, /**< SDIO bus device */ RT_Device_Class_PM, /**< PM pseudo device */ RT_Device_Class_Pipe, /**< Pipe device */ + RT_Device_Class_Portal, /**< Portal device */ RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ RT_Device_Class_Unknown /**< unknown device */ }; From b4ab82284f6a17e43098acea207b390321d569ec Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 20 Aug 2013 14:27:28 +0800 Subject: [PATCH 08/28] finsh/cmd: add description for new pipe and portal device --- components/finsh/cmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index e6c576252c..00dc384a1e 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -455,6 +455,8 @@ static long _list_device(struct rt_list_node *list) "SPI Device", "SDIO Bus", "PM Pseudo Device", + "Pipe", + "Portal Device", "Miscellaneous Device", "Unknown" }; From 824261d3bc8467f6220061f43d22321f1ce50bc3 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Thu, 22 Aug 2013 15:12:00 +0800 Subject: [PATCH 09/28] dev/portal: add checks on oflag It does not make sense to open portal without a flag. One should open a portal with RT_DEVICE_OFLAG_RDWR in most cases. --- components/drivers/src/portal.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/drivers/src/portal.c b/components/drivers/src/portal.c index 82d9d4e802..26977a8259 100644 --- a/components/drivers/src/portal.c +++ b/components/drivers/src/portal.c @@ -53,6 +53,9 @@ static rt_err_t _portal_open(rt_device_t dev, rt_uint16_t oflag) RT_ASSERT(dev); + if (!oflag) + return -RT_ERROR; + portal = (struct rt_portal_device*)dev; if (oflag & RT_DEVICE_OFLAG_RDONLY) From 246bdde8de4167065b4a52530a9c7be85c189dd8 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Thu, 22 Aug 2013 16:43:06 +0800 Subject: [PATCH 10/28] dev/portal: fix bug in portal callback forwarding When forwarding rx/tx callback from the underlaying device(pipe), the "dev" argument should be the portal. So the portal callback could think itself as called. --- components/drivers/src/portal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/drivers/src/portal.c b/components/drivers/src/portal.c index 26977a8259..779812e9ca 100644 --- a/components/drivers/src/portal.c +++ b/components/drivers/src/portal.c @@ -116,7 +116,8 @@ static rt_err_t _portal_rx_indicate(rt_device_t dev, rt_size_t size) pipe = (struct rt_pipe_device*)dev; if (pipe->read_portal->parent.rx_indicate) - return pipe->read_portal->parent.rx_indicate(dev, size); + return pipe->read_portal->parent.rx_indicate( + (rt_device_t)pipe->read_portal, size); return -RT_ENOSYS; } @@ -130,7 +131,8 @@ static rt_err_t _portal_tx_complete(rt_device_t dev, void *buf) pipe = (struct rt_pipe_device*)dev; if (pipe->write_portal->parent.tx_complete) - return pipe->write_portal->parent.tx_complete(dev, buf); + return pipe->write_portal->parent.tx_complete( + (rt_device_t)pipe->write_portal, buf); return -RT_ENOSYS; } From 3d0c0af3718a89a5d614b79ea9910bdc5409415f Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 31 Aug 2013 16:30:32 +0800 Subject: [PATCH 11/28] simulator: fix SDL initialization under Linux rt_hw_sdl_start should wait untill the rtgui_graphic_set_device is called int the sdl_loop. Use pthread_cond_wait to achieve this in Linux. --- bsp/simulator/drivers/sdl_fb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/bsp/simulator/drivers/sdl_fb.c b/bsp/simulator/drivers/sdl_fb.c index d7ebbc8245..78bca6f07f 100755 --- a/bsp/simulator/drivers/sdl_fb.c +++ b/bsp/simulator/drivers/sdl_fb.c @@ -152,8 +152,12 @@ static void sdlfb_hw_init(void) #ifdef _WIN32 static HANDLE sdl_ok_event = NULL; + static DWORD WINAPI sdl_loop(LPVOID lpParam) #else +static pthread_mutex_t sdl_ok_mutex; +static pthread_cond_t sdl_ok_event; + static void *sdl_loop(void *lpParam) #endif { @@ -167,14 +171,19 @@ static void *sdl_loop(void *lpParam) /* set the getchar without buffer */ sigfillset(&sigmask); pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask); + pthread_mutex_lock(&sdl_ok_mutex); #endif sdlfb_hw_init(); device = rt_device_find("sdl"); + RT_ASSERT(device); rtgui_graphic_set_device(device); #ifdef _WIN32 SetEvent(sdl_ok_event); +#else + pthread_cond_signal(&sdl_ok_event); + pthread_mutex_unlock(&sdl_ok_mutex); #endif /* handle SDL event */ while (!quit) @@ -338,11 +347,20 @@ void rt_hw_sdl_start(void) /* Linux */ pthread_t pid; int res; + + pthread_mutex_init(&sdl_ok_mutex, NULL); + pthread_cond_init(&sdl_ok_event, NULL); + res = pthread_create(&pid, NULL, &sdl_loop, NULL); if (res) { printf("pthread create sdl thread faild, <%d>\n", res); exit(EXIT_FAILURE); } + pthread_mutex_lock(&sdl_ok_mutex); + pthread_cond_wait(&sdl_ok_event, &sdl_ok_mutex); + + pthread_mutex_destroy(&sdl_ok_mutex); + pthread_cond_destroy(&sdl_ok_event); #endif } From 6563ae6cab1615df3e1abbccf8df1498934983f9 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 31 Aug 2013 16:46:36 +0800 Subject: [PATCH 12/28] simulator: init SDL after rt_components_init SDL may use DFS to open files. It should be run after rt_components_init. --- bsp/simulator/applications/application.c | 6 ++++++ bsp/simulator/applications/platform.c | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/bsp/simulator/applications/application.c b/bsp/simulator/applications/application.c index 4abecb872e..ea07f01c5f 100755 --- a/bsp/simulator/applications/application.c +++ b/bsp/simulator/applications/application.c @@ -30,6 +30,12 @@ void rt_init_thread_entry(void *parameter) /* initialization RT-Thread Components */ rt_components_init(); +#ifdef RT_USING_RTGUI + /* start sdl thread to simulate an LCD. SDL may depend on DFS and should be + * called after rt_components_init. */ + rt_hw_sdl_start(); +#endif /* RT_USING_RTGUI */ + #if defined(RT_USING_COMPONENTS_INIT) && defined(__GNUC__) && defined(RT_USING_FINSH) finsh_set_device(RT_CONSOLE_DEVICE_NAME); #endif diff --git a/bsp/simulator/applications/platform.c b/bsp/simulator/applications/platform.c index 3c7ffdb541..fbc1003d2a 100644 --- a/bsp/simulator/applications/platform.c +++ b/bsp/simulator/applications/platform.c @@ -17,11 +17,6 @@ void rt_platform_init(void) #endif /* RT_USING_DFS */ -#ifdef RT_USING_RTGUI - /* start sdl thread to simulate an LCD */ - rt_hw_sdl_start(); -#endif /* RT_USING_RTGUI */ - #ifdef _WIN32 rt_thread_idle_sethook(rt_hw_win32_low_cpu); #endif From c05b2053904dbcef44a000230860b56586c87a71 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 31 Aug 2013 17:58:34 +0800 Subject: [PATCH 13/28] finsh: use alias in the variable definition With this patch, one could define two alias for the same function like: FINSH_FUNCTION_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reboot the cpu); FINSH_FUNCTION_EXPORT_ALIAS(rt_hw_cpu_reset, __cmd_reboot, reboot the cpu); Suitable for being used in MSH/Finsh. --- components/finsh/finsh.h | 47 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/components/finsh/finsh.h b/components/finsh/finsh.h index 99851e8d36..c93986de6e 100644 --- a/components/finsh/finsh.h +++ b/components/finsh/finsh.h @@ -237,33 +237,34 @@ struct finsh_sysvar* finsh_sysvar_lookup(const char* name); */ #ifdef _MSC_VER #define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc) \ - const char __fsym_##name##_name[] = #alias; \ - const char __fsym_##name##_desc[] = #desc; \ - __declspec(allocate("FSymTab$f")) const struct finsh_syscall __fsym_##name = \ + const char __fsym_##alias##_name[] = #alias; \ + const char __fsym_##alias##_desc[] = #desc; \ + __declspec(allocate("FSymTab$f")) \ + const struct finsh_syscall __fsym_##alias = \ { \ - __fsym_##name##_name, \ - __fsym_##name##_desc, \ + __fsym_##alias##_name, \ + __fsym_##alias##_desc, \ (syscall_func)&name \ }; #elif defined(__TI_COMPILER_VERSION__) #define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc) \ - __TI_FINSH_EXPORT_FUNCTION(__fsym_##name); \ - const char __fsym_##name##_name[] = #alias; \ - const char __fsym_##name##_desc[] = #desc; \ - const struct finsh_syscall __fsym_##name = \ + __TI_FINSH_EXPORT_FUNCTION(__fsym_##alias); \ + const char __fsym_##alias##_name[] = #alias; \ + const char __fsym_##alias##_desc[] = #desc; \ + const struct finsh_syscall __fsym_##alias = \ { \ - __fsym_##name##_name, \ - __fsym_##name##_desc, \ + __fsym_##alias##_name, \ + __fsym_##alias##_desc, \ (syscall_func)&name \ }; #else #define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc) \ - const char __fsym_##name##_name[] = #alias; \ - const char __fsym_##name##_desc[] = #desc; \ - const struct finsh_syscall __fsym_##name SECTION("FSymTab")= \ + const char __fsym_##alias##_name[] = #alias; \ + const char __fsym_##alias##_desc[] = #desc; \ + const struct finsh_syscall __fsym_##alias SECTION("FSymTab")= \ { \ - __fsym_##name##_name, \ - __fsym_##name##_desc, \ + __fsym_##alias##_name, \ + __fsym_##alias##_desc, \ (syscall_func)&name \ }; #endif /* FINSH_FUNCTION_EXPORT_ALIAS defines */ @@ -324,11 +325,11 @@ struct finsh_sysvar* finsh_sysvar_lookup(const char* name); (syscall_func)&name \ }; #define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc) \ - const char __fsym_##name##_name[] = #alias; \ - __TI_FINSH_EXPORT_FUNCTION(__fsym_##name); \ - const struct finsh_syscall __fsym_##name = \ + const char __fsym_##alias##_name[] = #alias; \ + __TI_FINSH_EXPORT_FUNCTION(__fsym_##alias); \ + const struct finsh_syscall __fsym_##alias = \ { \ - __fsym_##name##_name, \ + __fsym_##alias##_name, \ (syscall_func)&name \ }; @@ -351,10 +352,10 @@ struct finsh_sysvar* finsh_sysvar_lookup(const char* name); }; #define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc) \ - const char __fsym_##name##_name[] = #alias; \ - const struct finsh_syscall __fsym_##name SECTION("FSymTab")= \ + const char __fsym_##alias##_name[] = #alias; \ + const struct finsh_syscall __fsym_##alias SECTION("FSymTab")= \ { \ - __fsym_##name##_name, \ + __fsym_##alias##_name, \ (syscall_func)&name \ }; From ea66b820e11c89026a9af9523875e021754d7b13 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 3 Sep 2013 16:09:16 +0800 Subject: [PATCH 14/28] log_trace: cleanup --- components/utilities/logtrace/log_file.c | 49 ++++++++++++++--------- components/utilities/logtrace/log_trace.c | 9 ----- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/components/utilities/logtrace/log_file.c b/components/utilities/logtrace/log_file.c index c5815536b2..5487aeb7bd 100644 --- a/components/utilities/logtrace/log_file.c +++ b/components/utilities/logtrace/log_file.c @@ -41,52 +41,56 @@ struct file_device static struct file_device _file_device; /* common device interface */ -rt_err_t fdevice_open(rt_device_t dev, rt_uint16_t oflag) +static rt_err_t fdevice_open(rt_device_t dev, rt_uint16_t oflag) { int fd; - struct file_device *file = (struct file_device *)dev; - if (file->fd >= 0) return -RT_EBUSY; + struct file_device *fdev = (struct file_device *)dev; - fd = open(file->filename, O_RDONLY, 0); + if (fdev->fd >= 0) + return -RT_EBUSY; + + /* test and open */ + fd = open(fdev->filename, O_RDONLY, 0); if (fd >= 0) { close(fd); - - /* file exists */ - fd = open(file->filename, O_WRONLY | O_APPEND, 0); + fd = open(fdev->filename, O_WRONLY | O_APPEND, 0); } else { /* file not exists */ - fd = open(file->filename, O_WRONLY | O_CREAT, 0); + fd = open(fdev->filename, O_WRONLY | O_CREAT, 0); } + fdev->fd = fd; - file->fd = fd; return RT_EOK; } -rt_err_t fdevice_close(rt_device_t dev) +static rt_err_t fdevice_close(rt_device_t dev) { rt_err_t result; + struct file_device *fdev = (struct file_device *)dev; - struct file_device *file = (struct file_device *)dev; - if (file->fd < 0) return -RT_EBUSY; + if (fdev->fd < 0) + return -RT_EBUSY; - result = close(file->fd); + result = close(fdev->fd); if (result == 0) { - file->fd = -1; + fdev->fd = -1; } return result; } -rt_size_t fdevice_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +static rt_size_t fdevice_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { - struct file_device *file = (struct file_device *)dev; - if (file->fd < 0) return 0; + struct file_device *fdev = (struct file_device *)dev; - return write(file->fd, buffer, size); + if (fdev->fd < 0) + return 0; + + return write(fdev->fd, buffer, size); } void log_trace_file_init(const char *filename) @@ -112,4 +116,11 @@ void log_trace_file_init(const char *filename) _file_device.fd = -1; } -#endif // RT_USING_DFS +void log_trace_set_file(const char *filename) +{ + log_trace_file_init(filename); + log_trace_set_device("logfile"); +} +FINSH_FUNCTION_EXPORT_ALIAS(log_trace_set_file, log_file, set output filename of log trace); + +#endif /* RT_USING_DFS */ diff --git a/components/utilities/logtrace/log_trace.c b/components/utilities/logtrace/log_trace.c index 7b17874445..79d5a21884 100644 --- a/components/utilities/logtrace/log_trace.c +++ b/components/utilities/logtrace/log_trace.c @@ -416,12 +416,3 @@ rt_err_t log_trace_set_device(const char *device_name) } FINSH_FUNCTION_EXPORT_ALIAS(log_trace_set_device, log_device, set device of log trace); -#ifdef RT_USING_DFS -void log_trace_set_file(const char *filename) -{ - log_trace_file_init(filename); - log_trace_set_device("logfile"); -} -FINSH_FUNCTION_EXPORT_ALIAS(log_trace_set_file, log_file, set output filename of log trace); -#endif // RT_USING_DFS - From d70761222c4924aac9105ddbbe62089c1118c712 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 3 Sep 2013 20:09:45 +0800 Subject: [PATCH 15/28] stm32f10x: fix the rtgui initialization The rtgui_system_server_init prototype is wrong. And if we use RT_USING_COMPONENTS_INIT, there is no need to call rtgui_system_server_init again. --- bsp/stm32f10x/applications/application.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bsp/stm32f10x/applications/application.c b/bsp/stm32f10x/applications/application.c index 7031711460..d57bb4e4c0 100644 --- a/bsp/stm32f10x/applications/application.c +++ b/bsp/stm32f10x/applications/application.c @@ -111,7 +111,6 @@ void rt_init_thread_entry(void* parameter) #ifdef RT_USING_RTGUI { - extern void rtgui_system_server_init(void); extern void rt_hw_lcd_init(); extern void rtgui_touch_hw_init(void); @@ -132,8 +131,10 @@ void rt_init_thread_entry(void* parameter) /* set lcd device as rtgui graphic driver */ rtgui_graphic_set_device(lcd); +#ifndef RT_USING_COMPONENTS_INIT /* init rtgui system server */ rtgui_system_server_init(); +#endif calibration_set_restore(cali_setup); calibration_set_after(cali_store); From 3ebc76652197b47e117ed2a856786a4d199d79a7 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Wed, 4 Sep 2013 00:05:03 +0800 Subject: [PATCH 16/28] sim/posix: move rt_hw_context_switch_interrupt after it's definition This fix a compile error in Clang. --- libcpu/sim/posix/cpu_port.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libcpu/sim/posix/cpu_port.c b/libcpu/sim/posix/cpu_port.c index e094edb6bc..eb1ae4865c 100644 --- a/libcpu/sim/posix/cpu_port.c +++ b/libcpu/sim/posix/cpu_port.c @@ -363,12 +363,6 @@ void rt_hw_interrupt_enable(rt_base_t level) /*TODO: It may need to unmask the signal */ } -void rt_hw_context_switch_interrupt(rt_uint32_t from, - rt_uint32_t to) -{ - rt_hw_context_switch(from, to); -} - void rt_hw_context_switch(rt_uint32_t from, rt_uint32_t to) { @@ -400,6 +394,12 @@ void rt_hw_context_switch(rt_uint32_t from, pthread_mutex_unlock(ptr_int_mutex); } +void rt_hw_context_switch_interrupt(rt_uint32_t from, + rt_uint32_t to) +{ + rt_hw_context_switch(from, to); +} + void rt_hw_context_switch_to(rt_uint32_t to) { //set to thread From c6e81b58d9da3866287b02f48e231db7d272acd5 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Fri, 6 Sep 2013 21:32:27 +0800 Subject: [PATCH 17/28] simulator: move SDL setting staff into drivers/SConstruct This could not only make a cleaner SConstruct, but could also benefit RTGUI building. --- bsp/simulator/SConstruct | 7 ------- bsp/simulator/drivers/SConscript | 14 +++++++++++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/bsp/simulator/SConstruct b/bsp/simulator/SConstruct index af6534906b..b2e958e65b 100755 --- a/bsp/simulator/SConstruct +++ b/bsp/simulator/SConstruct @@ -84,13 +84,6 @@ else: objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False, remove_components=['rtgui']) if GetDepend('RT_USING_RTGUI'): - sdl_lib = ['SDL', 'SDLmain'] - sdl_lib_path = [os.path.abspath('SDL/lib/x86')] - sdl_include_path = [os.path.abspath('SDL/include')] - env.Append(LIBS=sdl_lib) - env.Append(LIBPATH=sdl_lib_path) - env.Append(CPPPATH=sdl_include_path) - if RTT_RTGUI: objs += SConscript(os.path.join(RTT_RTGUI, 'SConscript'), variant_dir='build/components/rtgui', diff --git a/bsp/simulator/drivers/SConscript b/bsp/simulator/drivers/SConscript index d939535da8..eb491b810e 100644 --- a/bsp/simulator/drivers/SConscript +++ b/bsp/simulator/drivers/SConscript @@ -3,10 +3,19 @@ from building import * cwd = GetCurrentDir() src = Glob('*.c') +LIBS = [] +LIBPATH = [] +CPPPATH = [cwd] # remove no need file. if GetDepend('RT_USING_RTGUI') == False: SrcRemove(src, 'sdl_fb.c') +else: + LIBS.append('SDL') + if sys.platform == 'win32': + LIBPATH.append(os.path.abspath(os.path.join(cwd, '../SDL/lib/x86'))) + CPPPATH.append(os.path.abspath(os.path.join(cwd, '../SDL/include'))) + if GetDepend('RT_USING_DFS') == False or GetDepend('RT_USING_DFS_ELMFAT') == False: SrcRemove(src, 'sd_sim.c') if GetDepend('RT_USING_DFS') == False or GetDepend('RT_USING_MTD_NAND') == False: @@ -20,8 +29,7 @@ if GetDepend('RT_USING_MODULE') == False: if sys.platform[0:5]=="linux": #check whether under linux SrcRemove(src, ['module_win32.c', 'dfs_win32.c']) -CPPPATH = [cwd] - -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) +group = DefineGroup('Drivers', src, depend = [''], + CPPPATH = CPPPATH, LIBS=LIBS, LIBPATH=LIBPATH) Return('group') From 18692c29b8d8a24dcd6710c4bea4339789c21c17 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Fri, 6 Sep 2013 21:54:27 +0800 Subject: [PATCH 18/28] simulator: get CROSS_TOOL and EXEC_PATH from env Simulator get it's way to Travis CI ready. --- bsp/simulator/rtconfig.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bsp/simulator/rtconfig.py b/bsp/simulator/rtconfig.py index 7a42bddbcf..9328a087f8 100755 --- a/bsp/simulator/rtconfig.py +++ b/bsp/simulator/rtconfig.py @@ -1,3 +1,5 @@ +import os + # toolchains options ARCH='sim' #CROSS_TOOL='msvc' or 'gcc' or 'mingw' @@ -5,6 +7,9 @@ ARCH='sim' # 'gcc' is for linux CROSS_TOOL='msvc' +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + # cross_tool provides the cross compiler # EXEC_PATH is the compiler execute path if CROSS_TOOL == 'gcc': @@ -26,6 +31,9 @@ else : print "bad CROSS TOOL!" exit(1) +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + BUILD = 'debug' #BUILD = '' From 3b4f3f5931185ea3224e16430b75ae32ed1718b1 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 12:06:04 +0800 Subject: [PATCH 19/28] Scons: run `clang -Wall -fsyntax-only` in clang-analyze The `clang -fsyntax-only` will give us additional warning messages in the console. --- tools/building.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/building.py b/tools/building.py index 56b4ebdc8d..65bd14d882 100644 --- a/tools/building.py +++ b/tools/building.py @@ -113,8 +113,11 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ AS = 'true',) env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_")) # only check, don't compile. ccc-analyzer use CCC_CC as the CC. - env['ENV']['CCC_CC'] = 'true' - env['ENV']['CCC_CXX'] = 'true' + # fsyntax-only will give us some additional warning messages + env['ENV']['CCC_CC'] = 'clang' + env.Append(CFLAGS=['-fsyntax-only', '-Wall', '-Wno-invalid-source-encoding']) + env['ENV']['CCC_CXX'] = 'clang++' + env.Append(CXXFLAGS=['-fsyntax-only', '-Wall', '-Wno-invalid-source-encoding']) # remove the POST_ACTION as it will cause meaningless errors(file not # found or something like that). rtconfig.POST_ACTION = '' From c289aa9fc1955910af3c8fd4086c35e762b8368b Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 14:53:31 +0800 Subject: [PATCH 20/28] Scons: add a custom tool to do clang static analyze Bsps can use the clang analyzer as a tool: env = Environment(toolpath=[os.path.join(RTT_ROOT, 'tools', 'tools')], tools = ['clang-analyze']) When building the project, the static analyzer will be called to check all the C code. The warnings are print to stderr. --- tools/tools/clang-analyze.py | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tools/tools/clang-analyze.py diff --git a/tools/tools/clang-analyze.py b/tools/tools/clang-analyze.py new file mode 100644 index 0000000000..6008e684df --- /dev/null +++ b/tools/tools/clang-analyze.py @@ -0,0 +1,69 @@ +""" +Tool-specific initialization for Clang static analyzer + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. +""" + +__revision__ = "tools/clang-analyze.py 2013-09-06 grissiom" + +import os +import os.path + +import SCons.Action +import SCons.Builder +import SCons.Defaults +import SCons.Tool +import SCons.Util + +import rtconfig + +def generate(env): + assert(rtconfig.CROSS_TOOL == 'clang-analyze') + # let gnu_tools setup a basic env(learnt from SCons/Tools/mingw.py) + gnu_tools = ['gcc', 'g++', 'gnulink', 'ar', 'gas', 'm4'] + for tool in gnu_tools: + SCons.Tool.Tool(tool)(env) + + # then we could stand on the shoulders of gaints + env['CC'] = 'ccc-analyzer' + env['CXX'] = 'c++-analyzer' + env['AS'] = 'true' + env['AR'] = 'true' + env['LINK'] = 'true' + + env['CFLAGS'] = ['-fsyntax-only', '-Wall', '-Wno-invalid-source-encoding'] + env['LINKFLAGS'] = '-Wl,--gc-sections' + env['ARFLAGS'] = '-rc' + + # only check, don't compile. ccc-analyzer use CCC_CC as the CC. + # fsyntax-only will give us some additional warning messages + env['ENV']['CCC_CC'] = 'clang' + env['ENV']['CCC_CXX'] = 'clang++' + + # setup the output dir and format + env['ENV']['CCC_ANALYZER_HTML'] = './build/' + env['ENV']['CCC_ANALYZER_OUTPUT_FORMAT'] = 'html' + + # Some setting from the platform also have to be overridden: + env['OBJSUFFIX'] = '.o' + env['LIBPREFIX'] = 'lib' + env['LIBSUFFIX'] = '.a' + + if rtconfig.EXEC_PATH: + if not os.path.exists(rtconfig.EXEC_PATH): + print + print 'warning: rtconfig.EXEC_PATH(%s) does not exists.' % rtconfig.EXEC_PATH + print + return + env.AppendENVPath('PATH', rtconfig.EXEC_PATH) + +def exists(env): + return env.Detect(['clang', 'clang++']) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: From 35cac170fa0cf6829afda14ecc124b20bce2b061 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 15:01:28 +0800 Subject: [PATCH 21/28] simulator: add clang-analyze tool support When CROSS_TOOL or 'RTT_CC' env is setted to 'clang-analyze', it will use Clang to check the codes. --- bsp/simulator/SConstruct | 4 ++++ bsp/simulator/rtconfig.py | 7 +++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bsp/simulator/SConstruct b/bsp/simulator/SConstruct index b2e958e65b..4db7328f2a 100755 --- a/bsp/simulator/SConstruct +++ b/bsp/simulator/SConstruct @@ -73,6 +73,10 @@ elif rtconfig.PLATFORM == 'mingw': LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env['LIBS']=libs env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +elif rtconfig.CROSS_TOOL == 'clang-analyze': + TARGET = 'rtthread' + env = Environment(toolpath=[os.path.join(RTT_ROOT, 'tools', 'tools')], + tools = [rtconfig.CROSS_TOOL]) else: TARGET = 'rtthread' env['CC']=rtconfig.CC diff --git a/bsp/simulator/rtconfig.py b/bsp/simulator/rtconfig.py index 9328a087f8..d3ed2599d5 100755 --- a/bsp/simulator/rtconfig.py +++ b/bsp/simulator/rtconfig.py @@ -12,10 +12,10 @@ if os.getenv('RTT_CC'): # cross_tool provides the cross compiler # EXEC_PATH is the compiler execute path -if CROSS_TOOL == 'gcc': +if CROSS_TOOL == 'gcc' or CROSS_TOOL == 'clang-analyze': CPU = 'posix' PLATFORM = 'gcc' - EXEC_PATH = '/usr/bin/gcc' + EXEC_PATH = '' elif CROSS_TOOL == 'mingw': CPU = 'win32' @@ -26,8 +26,7 @@ elif CROSS_TOOL == 'msvc': CPU = 'win32' PLATFORM = 'cl' EXEC_PATH = '' - -else : +else: print "bad CROSS TOOL!" exit(1) From 0168048f27e9558b5367eac28a008dc3f91e114b Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 15:21:46 +0800 Subject: [PATCH 22/28] travis: auto build the simulator Building is only the first step. Correctness is what we need. There are already many GCC builds for other bsp so GCC building for simulator is not important. So I use clang-analyze to check all the source codes in simulator project. Hope it will help us. --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b18fcd107..11b255954f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,13 +6,15 @@ notifications: before_script: # travis has changed to 64-bit and we require 32-bit compatibility libraries - sudo apt-get update - - "sudo apt-get -qq install libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 || true" + - "sudo apt-get -qq install clang libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-arm' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/arm-none-eabi/arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/arm-2012.09/bin && /opt/arm-2012.09/bin/arm-none-eabi-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-mips' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/mips-sde-elf/mips-2012.09-98-mips-sde-elf-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/mips-2012.09/bin && /opt/mips-2012.09/bin/mips-sde-elf-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-ppc' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/powerpc-eabi/freescale-2011.03-39-powerpc-eabi-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/freescale-2011.03/bin && /opt/freescale-2011.03/bin/powerpc-eabi-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'atmel-avr32' ] && curl -s http://www.atmel.com/images/avr32-gnu-toolchain-3.4.1.348-linux.any.x86.tar.gz | sudo tar xzf - -C /opt && export RTT_EXEC_PATH=/opt/avr32-gnu-toolchain-linux_x86/bin && /opt/avr32-gnu-toolchain-linux_x86/bin/avr32-gcc --version && curl -sO http://www.atmel.com/images/avr-headers-3.2.3.970.zip && unzip -qq avr-headers-3.2.3.970.zip -d bsp/$RTT_BSP || true" - export RTT_ROOT=`pwd` - export RTT_CC='gcc' + - git clone --depth 1 https://github.com/RT-Thread/RTGUI.git $HOME/RTGUI + - export RTT_RTGUI=$HOME/RTGUI/components/rtgui script: - scons -C bsp/$RTT_BSP @@ -57,3 +59,4 @@ env: # - RTT_BSP='wh44b0' # no scons # - RTT_BSP='x86' # x86 # - RTT_BSP='xplorer4330' # no scons + - RTT_BSP='simulator' RTT_CC='clang-analyze' From 5ab9943eb5468491352f32837fb8dbf13d5394f0 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 16:01:03 +0800 Subject: [PATCH 23/28] travis: try to fix the SDL building --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 11b255954f..b60854d93d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ notifications: before_script: # travis has changed to 64-bit and we require 32-bit compatibility libraries - sudo apt-get update - - "sudo apt-get -qq install clang libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 || true" + - "sudo apt-get -qq install clang libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 libsdl-dev || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-arm' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/arm-none-eabi/arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/arm-2012.09/bin && /opt/arm-2012.09/bin/arm-none-eabi-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-mips' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/mips-sde-elf/mips-2012.09-98-mips-sde-elf-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/mips-2012.09/bin && /opt/mips-2012.09/bin/mips-sde-elf-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-ppc' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/powerpc-eabi/freescale-2011.03-39-powerpc-eabi-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/freescale-2011.03/bin && /opt/freescale-2011.03/bin/powerpc-eabi-gcc --version || true" @@ -17,7 +17,7 @@ before_script: - export RTT_RTGUI=$HOME/RTGUI/components/rtgui script: - - scons -C bsp/$RTT_BSP + - scons -C bsp/$RTT_BSP --verbose env: - RTT_BSP='at91sam9260' RTT_TOOL_CHAIN='sourcery-arm' From eae89b95764a4929fab6c8c2bfe94a0562e40c24 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 16:15:43 +0800 Subject: [PATCH 24/28] travis: install the gcc-multilib to get the 32bit build OK --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b60854d93d..28413ac218 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ notifications: before_script: # travis has changed to 64-bit and we require 32-bit compatibility libraries - sudo apt-get update - - "sudo apt-get -qq install clang libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 libsdl-dev || true" + - "sudo apt-get -qq install clang gcc-multilib libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 libsdl-dev || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-arm' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/arm-none-eabi/arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/arm-2012.09/bin && /opt/arm-2012.09/bin/arm-none-eabi-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-mips' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/mips-sde-elf/mips-2012.09-98-mips-sde-elf-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/mips-2012.09/bin && /opt/mips-2012.09/bin/mips-sde-elf-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'sourcery-ppc' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/powerpc-eabi/freescale-2011.03-39-powerpc-eabi-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/freescale-2011.03/bin && /opt/freescale-2011.03/bin/powerpc-eabi-gcc --version || true" From 4240ebd73f05cb3501037962d6410a917d438c79 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 16:32:50 +0800 Subject: [PATCH 25/28] travis: don't export RTT_CC in before_script if it's been set This gives ways for bsp to set it's own RTT_CC. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 28413ac218..5619d65627 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ before_script: - "[ $RTT_TOOL_CHAIN = 'sourcery-ppc' ] && curl -s https://sourcery.mentor.com/public/gnu_toolchain/powerpc-eabi/freescale-2011.03-39-powerpc-eabi-i686-pc-linux-gnu.tar.bz2 | sudo tar xjf - -C /opt && export RTT_EXEC_PATH=/opt/freescale-2011.03/bin && /opt/freescale-2011.03/bin/powerpc-eabi-gcc --version || true" - "[ $RTT_TOOL_CHAIN = 'atmel-avr32' ] && curl -s http://www.atmel.com/images/avr32-gnu-toolchain-3.4.1.348-linux.any.x86.tar.gz | sudo tar xzf - -C /opt && export RTT_EXEC_PATH=/opt/avr32-gnu-toolchain-linux_x86/bin && /opt/avr32-gnu-toolchain-linux_x86/bin/avr32-gcc --version && curl -sO http://www.atmel.com/images/avr-headers-3.2.3.970.zip && unzip -qq avr-headers-3.2.3.970.zip -d bsp/$RTT_BSP || true" - export RTT_ROOT=`pwd` - - export RTT_CC='gcc' + - "[ x$RTT_CC == x ] && export RTT_CC='gcc' || true" - git clone --depth 1 https://github.com/RT-Thread/RTGUI.git $HOME/RTGUI - export RTT_RTGUI=$HOME/RTGUI/components/rtgui @@ -20,6 +20,7 @@ script: - scons -C bsp/$RTT_BSP --verbose env: + - RTT_BSP='simulator' RTT_CC='clang-analyze' - RTT_BSP='at91sam9260' RTT_TOOL_CHAIN='sourcery-arm' - RTT_BSP='avr32uc3b0' RTT_TOOL_CHAIN='atmel-avr32' # - RTT_BSP='bf533' # no scons @@ -59,4 +60,3 @@ env: # - RTT_BSP='wh44b0' # no scons # - RTT_BSP='x86' # x86 # - RTT_BSP='xplorer4330' # no scons - - RTT_BSP='simulator' RTT_CC='clang-analyze' From dacd2cb9a9d9563b1986e6cef856d8f5017fe4ff Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 7 Sep 2013 17:22:45 +0800 Subject: [PATCH 26/28] travis: add scan-build in PATH --- .travis.yml | 4 ++-- tools/tools/clang-analyze.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5619d65627..67dd2defcb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,10 +17,10 @@ before_script: - export RTT_RTGUI=$HOME/RTGUI/components/rtgui script: - - scons -C bsp/$RTT_BSP --verbose + - scons -C bsp/$RTT_BSP env: - - RTT_BSP='simulator' RTT_CC='clang-analyze' + - RTT_BSP='simulator' RTT_CC='clang-analyze' RTT_EXEC_PATH=/usr/share/clang/scan-build - RTT_BSP='at91sam9260' RTT_TOOL_CHAIN='sourcery-arm' - RTT_BSP='avr32uc3b0' RTT_TOOL_CHAIN='atmel-avr32' # - RTT_BSP='bf533' # no scons diff --git a/tools/tools/clang-analyze.py b/tools/tools/clang-analyze.py index 6008e684df..a966a7b56a 100644 --- a/tools/tools/clang-analyze.py +++ b/tools/tools/clang-analyze.py @@ -60,7 +60,7 @@ def generate(env): env.AppendENVPath('PATH', rtconfig.EXEC_PATH) def exists(env): - return env.Detect(['clang', 'clang++']) + return env.Detect(['ccc-analyzer', 'c++-analyzer']) # Local Variables: # tab-width:4 From 2bcb9edd91df59e068f82b2ce438215e2c5df32b Mon Sep 17 00:00:00 2001 From: Bernard Xiong Date: Sun, 8 Sep 2013 15:01:29 +0800 Subject: [PATCH 27/28] Add gettimeofday declaration in sys/time.h --- components/libc/minilibc/sys/time.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/libc/minilibc/sys/time.h b/components/libc/minilibc/sys/time.h index 3df6d8c570..ada613251b 100644 --- a/components/libc/minilibc/sys/time.h +++ b/components/libc/minilibc/sys/time.h @@ -40,4 +40,6 @@ struct tm { const char *tm_zone; /* Timezone abbreviation. */ }; +int gettimeofday(struct timeval *tp, void *ignore); + #endif From c465bc2c2e837ad2d9ab9eb83f4aa138450ad16c Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sat, 14 Sep 2013 13:12:23 +0800 Subject: [PATCH 28/28] rt_event_recv: add a check on the option flag Either RT_EVENT_FLAG_AND or RT_EVENT_FLAG_OR should be set in the option flag. If none of them is present, the waiting thread will never be resumed. --- src/ipc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ipc.c b/src/ipc.c index 54cad042ba..116bde863b 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -45,6 +45,7 @@ * 2010-10-26 yi.qiu add module support in rt_mp_delete and rt_mq_delete * 2010-11-10 Bernard add IPC reset command implementation. * 2011-12-18 Bernard add more parameter checking in message queue + * 2013-09-14 Grissiom add an option check in rt_event_recv */ #include @@ -1079,7 +1080,8 @@ RTM_EXPORT(rt_event_send); * * @param event the fast event object * @param set the interested event set - * @param option the receive option + * @param option the receive option, either RT_EVENT_FLAG_AND or + * RT_EVENT_FLAG_OR should be set. * @param timeout the waiting time * @param recved the received event * @@ -1125,6 +1127,11 @@ rt_err_t rt_event_recv(rt_event_t event, if (event->set & set) status = RT_EOK; } + else + { + /* either RT_EVENT_FLAG_AND or RT_EVENT_FLAG_OR should be set */ + RT_ASSERT(0); + } if (status == RT_EOK) {