summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
author陈豪 <[email protected]>2014-08-06 22:55:49 +0800
committer陈豪 <[email protected]>2014-08-06 22:55:49 +0800
commit5fc32bf12ef4356ecbd46cfa21079cddb522b5c7 (patch)
tree8f77e59c1bcec59c3c5efd0fe022f3dc0a0c901e /components
parent0c8335d5ab046ce9fe36c4e01d5d40e4ba152b49 (diff)
parenta8fadf15b1828569e7684049d983cc6cb7fda2c9 (diff)
Merge pull request #1 from RT-Thread/master
sync
Diffstat (limited to 'components')
-rw-r--r--components/dfs/include/dfs_fs.h2
-rw-r--r--components/dfs/src/dfs_file.c16
-rw-r--r--components/dfs/src/dfs_fs.c31
-rw-r--r--components/dfs/src/dfs_posix.c24
-rw-r--r--components/drivers/i2c/i2c-bit-ops.c3
-rw-r--r--components/drivers/i2c/i2c_dev.c11
-rw-r--r--components/drivers/include/drivers/serial.h73
-rw-r--r--components/drivers/include/drivers/usb_common.h4
-rw-r--r--components/drivers/include/drivers/usb_device.h6
-rw-r--r--components/drivers/include/rtdevice.h34
-rw-r--r--components/drivers/serial/serial.c690
-rw-r--r--components/drivers/spi/SConscript24
-rw-r--r--components/drivers/spi/device_driver_list.txt15
-rw-r--r--components/drivers/spi/enc28j60.c876
-rw-r--r--components/drivers/spi/enc28j60.h329
-rw-r--r--components/drivers/spi/spi_dev.c35
-rw-r--r--components/drivers/spi/spi_flash_at45dbxx.c437
-rw-r--r--components/drivers/spi/spi_flash_at45dbxx.h17
-rw-r--r--components/drivers/spi/spi_flash_sst25vfxx.c346
-rw-r--r--components/drivers/spi/spi_flash_sst25vfxx.h32
-rw-r--r--components/drivers/spi/spi_flash_w25qxx.c371
-rw-r--r--components/drivers/spi/spi_flash_w25qxx.h34
-rw-r--r--components/drivers/spi/spi_wifi_rw009.c590
-rw-r--r--components/drivers/spi/spi_wifi_rw009.h123
-rw-r--r--components/drivers/src/workqueue.c102
-rw-r--r--components/drivers/usb/usbdevice/class/cdc_vcom.c4
-rw-r--r--components/drivers/usb/usbdevice/core/core.c47
-rw-r--r--components/external/libpng/pngconf.h2
-rw-r--r--components/finsh/cmd.c9
-rw-r--r--components/finsh/finsh.h1
-rw-r--r--components/finsh/msh_cmd.c44
-rw-r--r--components/finsh/shell.c10
-rw-r--r--components/libc/armlibc/mem_std.c22
-rw-r--r--components/libc/armlibc/stubs.c35
-rw-r--r--components/libc/minilibc/sys/types.h2
-rw-r--r--components/libc/newlib/syscalls.c8
-rw-r--r--components/net/lwip-1.3.2/apps/ping.c189
-rw-r--r--components/net/lwip-1.4.1/src/arch/sys_arch.c48
-rw-r--r--components/net/lwip-1.4.1/src/include/netif/ethernetif.h4
-rw-r--r--components/net/lwip-1.4.1/src/lwipopts.h22
-rw-r--r--components/net/lwip-1.4.1/src/netif/ethernetif.c45
-rw-r--r--components/net/lwip/apps/ping.c189
-rw-r--r--components/pthreads/mqueue.c3
-rw-r--r--components/pthreads/pthread_cond.c6
-rw-r--r--components/pthreads/semaphore.c2
-rw-r--r--components/utilities/ymodem/ymodem.c25
-rw-r--r--components/utilities/ymodem/ymodem.h2
47 files changed, 4328 insertions, 616 deletions
diff --git a/components/dfs/include/dfs_fs.h b/components/dfs/include/dfs_fs.h
index 3fa999c344..498aa5db54 100644
--- a/components/dfs/include/dfs_fs.h
+++ b/components/dfs/include/dfs_fs.h
@@ -94,6 +94,8 @@ struct dfs_mount_tbl
int dfs_register(const struct dfs_filesystem_operation *ops);
struct dfs_filesystem *dfs_filesystem_lookup(const char *path);
+const char* dfs_filesystem_get_mounted_path(struct rt_device* device);
+
rt_err_t dfs_filesystem_get_partition(struct dfs_partition *part,
rt_uint8_t *buf,
rt_uint32_t pindex);
diff --git a/components/dfs/src/dfs_file.c b/components/dfs/src/dfs_file.c
index 32198371d7..f5619e2354 100644
--- a/components/dfs/src/dfs_file.c
+++ b/components/dfs/src/dfs_file.c
@@ -555,7 +555,7 @@ void ls(const char *pathname)
if (pathname == RT_NULL)
rt_free(path);
}
-FINSH_FUNCTION_EXPORT(ls, list directory contents)
+FINSH_FUNCTION_EXPORT(ls, list directory contents);
void rm(const char *filename)
{
@@ -564,7 +564,7 @@ void rm(const char *filename)
rt_kprintf("Delete %s failed\n", filename);
}
}
-FINSH_FUNCTION_EXPORT(rm, remove files or directories)
+FINSH_FUNCTION_EXPORT(rm, remove files or directories);
void cat(const char* filename)
{
@@ -590,7 +590,7 @@ void cat(const char* filename)
dfs_file_close(&fd);
}
-FINSH_FUNCTION_EXPORT(cat, print file)
+FINSH_FUNCTION_EXPORT(cat, print file);
#define BUF_SZ 4096
static void copyfile(const char *src, const char *dst)
@@ -629,7 +629,15 @@ static void copyfile(const char *src, const char *dst)
read_bytes = dfs_file_read(&src_fd, block_ptr, BUF_SZ);
if (read_bytes > 0)
{
- dfs_file_write(&fd, block_ptr, read_bytes);
+ int length;
+
+ length = dfs_file_write(&fd, block_ptr, read_bytes);
+ if (length != read_bytes)
+ {
+ /* write failed. */
+ rt_kprintf("Write file data failed, errno=%d\n", length);
+ break;
+ }
}
} while (read_bytes > 0);
diff --git a/components/dfs/src/dfs_fs.c b/components/dfs/src/dfs_fs.c
index a41f36cf09..bdd9560d56 100644
--- a/components/dfs/src/dfs_fs.c
+++ b/components/dfs/src/dfs_fs.c
@@ -116,6 +116,37 @@ struct dfs_filesystem *dfs_filesystem_lookup(const char *path)
}
/**
+ * this function will return the mounted path for specified device.
+ *
+ * @param device the device object which is mounted.
+ *
+ * @return the mounted path or RT_NULL if none device mounted.
+ */
+const char* dfs_filesystem_get_mounted_path(struct rt_device* device)
+{
+ const char* path = RT_NULL;
+ struct dfs_filesystem *iter;
+
+ dfs_lock();
+ for (iter = &filesystem_table[0];
+ iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
+ {
+ /* fint the mounted device */
+ if (iter->ops == RT_NULL) continue;
+ else if (iter->dev_id == device)
+ {
+ path = iter->path;
+ break;
+ }
+ }
+
+ /* release filesystem_table lock */
+ dfs_unlock();
+
+ return path;
+}
+
+/**
* this function will fetch the partition table on specified buffer.
*
* @param part the returned partition structure.
diff --git a/components/dfs/src/dfs_posix.c b/components/dfs/src/dfs_posix.c
index 96139837e9..c1a6a5beb6 100644
--- a/components/dfs/src/dfs_posix.c
+++ b/components/dfs/src/dfs_posix.c
@@ -33,11 +33,11 @@
/**
* this function is a POSIX compliant version, which will open a file and
- * return a file descriptor.
+ * return a file descriptor according specified flags.
*
* @param file the path name of file.
* @param flags the file open flags.
- * @param mode
+ * @param mode ignored parameter
*
* @return the non-negative integer on successful open, others for failed.
*/
@@ -120,7 +120,8 @@ RTM_EXPORT(close);
* @param buf the buffer to save the read data.
* @param len the maximal length of data buffer
*
- * @return the actual read data buffer length
+ * @return the actual read data buffer length. If the returned value is 0, it
+ * may be reach the end of file, please check errno.
*/
int read(int fd, void *buf, size_t len)
{
@@ -200,7 +201,7 @@ RTM_EXPORT(write);
* @param offset the offset to be seeked.
* @param whence the directory of seek.
*
- * @return the current file position, or -1 on failed.
+ * @return the current read/write position in the file, or -1 on failed.
*/
off_t lseek(int fd, off_t offset, int whence)
{
@@ -336,6 +337,8 @@ RTM_EXPORT(stat);
*
* @param fildes the file description
* @param buf the data buffer to save stat description.
+ *
+ * @return 0 on successful, -1 on failed.
*/
int fstat(int fildes, struct stat *buf)
{
@@ -470,7 +473,7 @@ RTM_EXPORT(rmdir);
*
* @param name the path name to be open.
*
- * @return the DIR pointer of directory, NULL on open failed.
+ * @return the DIR pointer of directory, NULL on open directory failed.
*/
DIR *opendir(const char *name)
{
@@ -537,12 +540,17 @@ struct dirent *readdir(DIR *d)
if (fd == RT_NULL)
{
rt_set_errno(-DFS_STATUS_EBADF);
-
return RT_NULL;
}
- if (!d->num ||
- (d->cur += ((struct dirent *)(d->buf + d->cur))->d_reclen) >= d->num)
+ if (d->num)
+ {
+ struct dirent* dirent_ptr;
+ dirent_ptr = (struct dirent*)&d->buf[d->cur];
+ d->cur += dirent_ptr->d_reclen;
+ }
+
+ if (!d->num || d->cur >= d->num)
{
/* get a new entry */
result = dfs_file_getdents(fd,
diff --git a/components/drivers/i2c/i2c-bit-ops.c b/components/drivers/i2c/i2c-bit-ops.c
index 0d82d55fd4..d4a26ea72a 100644
--- a/components/drivers/i2c/i2c-bit-ops.c
+++ b/components/drivers/i2c/i2c-bit-ops.c
@@ -451,9 +451,6 @@ static const struct rt_i2c_bus_device_ops i2c_bit_bus_ops =
rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus,
const char *bus_name)
{
- struct rt_i2c_bit_ops *bit_ops = bus->priv;
- RT_ASSERT(bit_ops != RT_NULL);
-
bus->ops = &i2c_bit_bus_ops;
return rt_i2c_bus_device_register(bus, bus_name);
diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c
index cce53d5c92..4b811c62ea 100644
--- a/components/drivers/i2c/i2c_dev.c
+++ b/components/drivers/i2c/i2c_dev.c
@@ -20,18 +20,11 @@
* Change Logs:
* Date Author Notes
* 2012-04-25 weety first version
+ * 2014-08-03 bernard fix some compiling warning
*/
#include <rtdevice.h>
-static rt_err_t i2c_bus_device_init(rt_device_t dev)
-{
- struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data;
- RT_ASSERT(bus != RT_NULL);
-
- return RT_EOK;
-}
-
static rt_size_t i2c_bus_device_read(rt_device_t dev,
rt_off_t pos,
void *buffer,
@@ -122,7 +115,7 @@ rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus,
/* set device type */
device->type = RT_Device_Class_I2CBUS;
/* initialize device interface */
- device->init = i2c_bus_device_init;
+ device->init = RT_NULL;
device->open = RT_NULL;
device->close = RT_NULL;
device->read = i2c_bus_device_read;
diff --git a/components/drivers/include/drivers/serial.h b/components/drivers/include/drivers/serial.h
index 41132ed916..bf2a25ae1e 100644
--- a/components/drivers/include/drivers/serial.h
+++ b/components/drivers/include/drivers/serial.h
@@ -30,9 +30,15 @@
#include <rtthread.h>
+#define BAUD_RATE_2400 2400
#define BAUD_RATE_4800 4800
#define BAUD_RATE_9600 9600
+#define BAUD_RATE_38400 38400
+#define BAUD_RATE_57600 57600
#define BAUD_RATE_115200 115200
+#define BAUD_RATE_230400 230400
+#define BAUD_RATE_460800 460800
+#define BAUD_RATE_921600 921600
#define DATA_BITS_5 5
#define DATA_BITS_6 6
@@ -64,6 +70,15 @@
#define RT_DEVICE_CTRL_CLR_INT 0x11 /* disable receive irq */
#define RT_DEVICE_CTRL_GET_INT 0x12
+#define RT_SERIAL_EVENT_RX_IND 0x01 /* Rx indication */
+#define RT_SERIAL_EVENT_TX_DONE 0x02 /* Tx complete */
+#define RT_SERIAL_EVENT_RX_DMADONE 0x03 /* Rx DMA transfer done */
+#define RT_SERIAL_EVENT_TX_DMADONE 0x04 /* Tx DMA transfer done */
+#define RT_SERIAL_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */
+
+#define RT_SERIAL_DMA_RX 0x01
+#define RT_SERIAL_DMA_TX 0x02
+
#define RT_SERIAL_RX_INT 0x01
#define RT_SERIAL_TX_INT 0x02
@@ -83,24 +98,51 @@
PARITY_NONE, /* No parity */ \
BIT_ORDER_LSB, /* LSB first sent */ \
NRZ_NORMAL, /* Normal mode */ \
+ RT_SERIAL_RB_BUFSZ, /* Buffer size */ \
0 \
}
-struct serial_ringbuffer
-{
- rt_uint8_t buffer[RT_SERIAL_RB_BUFSZ];
- rt_uint16_t put_index, get_index;
-};
-
struct serial_configure
{
rt_uint32_t baud_rate;
+
rt_uint32_t data_bits :4;
rt_uint32_t stop_bits :2;
rt_uint32_t parity :2;
rt_uint32_t bit_order :1;
rt_uint32_t invert :1;
- rt_uint32_t reserved :20;
+ rt_uint32_t bufsz :16;
+ rt_uint32_t reserved :4;
+};
+
+/*
+ * Serial FIFO mode
+ */
+struct rt_serial_rx_fifo
+{
+ /* software fifo */
+ rt_uint8_t *buffer;
+
+ rt_uint16_t put_index, get_index;
+};
+
+struct rt_serial_tx_fifo
+{
+ struct rt_completion completion;
+};
+
+/*
+ * Serial DMA mode
+ */
+struct rt_serial_rx_dma
+{
+ rt_bool_t activated;
+};
+
+struct rt_serial_tx_dma
+{
+ rt_bool_t activated;
+ struct rt_data_queue data_queue;
};
struct rt_serial_device
@@ -110,14 +152,8 @@ struct rt_serial_device
const struct rt_uart_ops *ops;
struct serial_configure config;
- /* rx structure */
- struct serial_ringbuffer *int_rx;
- /* tx structure */
- struct serial_ringbuffer *int_tx;
-
- struct rt_data_queue tx_dq; /* tx dataqueue */
-
- volatile rt_bool_t dma_flag; /* dma transfer flag */
+ void *serial_rx;
+ void *serial_tx;
};
typedef struct rt_serial_device rt_serial_t;
@@ -132,14 +168,15 @@ struct rt_uart_ops
int (*putc)(struct rt_serial_device *serial, char c);
int (*getc)(struct rt_serial_device *serial);
- rt_size_t (*dma_transmit)(struct rt_serial_device *serial, const char *buf, rt_size_t size);
+ rt_size_t (*dma_transmit)(struct rt_serial_device *serial, const rt_uint8_t *buf, rt_size_t size, int direction);
};
-void rt_hw_serial_isr(struct rt_serial_device *serial);
-void rt_hw_serial_dma_tx_isr(struct rt_serial_device *serial);
+void rt_hw_serial_isr(struct rt_serial_device *serial, int event);
+
rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
const char *name,
rt_uint32_t flag,
void *data);
#endif
+
diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h
index cd6f0432f3..1e9cf3dc9f 100644
--- a/components/drivers/include/drivers/usb_common.h
+++ b/components/drivers/include/drivers/usb_common.h
@@ -373,7 +373,7 @@ struct uhid_descriptor
};
typedef struct uhid_descriptor* uhid_desc_t;
-struct ureqest
+struct urequest
{
rt_uint8_t request_type;
rt_uint8_t request;
@@ -381,7 +381,7 @@ struct ureqest
rt_uint16_t index;
rt_uint16_t length;
};
-typedef struct ureqest* ureq_t;
+typedef struct urequest* ureq_t;
#ifndef MIN
#define MIN(a, b) (a < b ? a : b)
diff --git a/components/drivers/include/drivers/usb_device.h b/components/drivers/include/drivers/usb_device.h
index 722251c82a..b104da6ab9 100644
--- a/components/drivers/include/drivers/usb_device.h
+++ b/components/drivers/include/drivers/usb_device.h
@@ -76,7 +76,7 @@ typedef enum
/* request to read full count */
UIO_REQUEST_READ_FULL,
/* request to read any count */
- UIO_REQUEST_READ_BEST,
+ UIO_REQUEST_READ_MOST,
/* request to write full count */
UIO_REQUEST_WRITE,
}UIO_REQUEST_TYPE;
@@ -239,7 +239,7 @@ struct udev_msg
union
{
struct ep_msg ep_msg;
- struct ureqest setup;
+ struct urequest setup;
} content;
};
typedef struct udev_msg* udev_msg_t;
@@ -292,7 +292,7 @@ rt_err_t rt_usbd_ep_set_stall(udevice_t device, uep_t ep);
rt_err_t rt_usbd_ep_clear_stall(udevice_t device, uep_t ep);
rt_err_t rt_usbd_ep0_set_stall(udevice_t device);
rt_err_t rt_usbd_ep0_clear_stall(udevice_t device);
-rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct ureqest* setup);
+rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct urequest* setup);
rt_err_t rt_usbd_ep0_in_handler(udcd_t dcd);
rt_err_t rt_usbd_ep0_out_handler(udcd_t dcd, rt_size_t size);
rt_err_t rt_usbd_ep_in_handler(udcd_t dcd, rt_uint8_t address);
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index dac85eb716..dc9761032e 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -20,6 +20,7 @@
* Change Logs:
* Date Author Notes
* 2012-01-08 bernard first version.
+ * 2014-07-12 bernard Add workqueue implementation.
*/
#ifndef __RT_DEVICE_H__
@@ -143,6 +144,21 @@ struct rt_data_queue
void (*evt_notify)(struct rt_data_queue *queue, rt_uint32_t event);
};
+/* workqueue implementation */
+struct rt_workqueue
+{
+ rt_list_t work_list;
+ rt_thread_t work_thread;
+};
+
+struct rt_work
+{
+ rt_list_t list;
+
+ void (*work_func)(struct rt_work* work, void* work_data);
+ void *work_data;
+};
+
/**
* Completion
*/
@@ -274,6 +290,24 @@ rt_err_t rt_data_queue_peak(struct rt_data_queue *queue,
rt_size_t *size);
void rt_data_queue_reset(struct rt_data_queue *queue);
+#ifdef RT_USING_HEAP
+/**
+ * WorkQueue for DeviceDriver
+ */
+struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_size, rt_uint8_t priority);
+rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue);
+rt_err_t rt_workqueue_dowork(struct rt_workqueue* queue, struct rt_work* work);
+rt_err_t rt_workqueue_cancel_work(struct rt_workqueue* queue, struct rt_work* work);
+
+rt_inline void rt_work_init(struct rt_work* work, void (*work_func)(struct rt_work* work, void* work_data),
+ void* work_data)
+{
+ rt_list_init(&(work->list));
+ work->work_func = work_func;
+ work->work_data = work_data;
+}
+#endif
+
#ifdef RT_USING_RTC
#include "drivers/rtc.h"
#ifdef RT_USING_ALARM
diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c
index 622d2cd68c..776316baf5 100644
--- a/components/drivers/serial/serial.c
+++ b/components/drivers/serial/serial.c
@@ -25,104 +25,197 @@
* 2012-11-23 bernard fix compiler warning.
* 2013-02-20 bernard use RT_SERIAL_RB_BUFSZ to define
* the size of ring buffer.
+ * 2014-07-10 bernard rewrite serial framework
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
-rt_inline void serial_ringbuffer_init(struct serial_ringbuffer *rbuffer)
+/*
+ * Serial poll routines
+ */
+rt_inline int _serial_poll_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
{
- rt_memset(rbuffer->buffer, 0, sizeof(rbuffer->buffer));
- rbuffer->put_index = 0;
- rbuffer->get_index = 0;
+ int ch;
+ int size;
+
+ RT_ASSERT(serial != RT_NULL);
+ size = length;
+
+ while (length)
+ {
+ ch = serial->ops->getc(serial);
+ *data = ch;
+ data ++; length --;
+
+ if (ch == '\n') break;
+ }
+
+ return size - length;
}
-rt_inline void serial_ringbuffer_putc(struct serial_ringbuffer *rbuffer,
- char ch)
+rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
{
- rt_base_t level;
+ int size;
+ RT_ASSERT(serial != RT_NULL);
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ size = length;
+ while (length)
+ {
+ /*
+ * to be polite with serial console add a line feed
+ * to the carriage return character
+ */
+ if (*data == '\n' && (serial->parent.flag & RT_DEVICE_FLAG_STREAM))
+ {
+ serial->ops->putc(serial, '\r');
+ }
+
+ serial->ops->putc(serial, *data);
+
+ ++ data;
+ -- length;
+ }
- rbuffer->buffer[rbuffer->put_index] = ch;
- rbuffer->put_index = (rbuffer->put_index + 1) & (RT_SERIAL_RB_BUFSZ - 1);
+ return size - length;
+}
- /* if the next position is read index, discard this 'read char' */
- if (rbuffer->put_index == rbuffer->get_index)
- {
- rbuffer->get_index = (rbuffer->get_index + 1) & (RT_SERIAL_RB_BUFSZ - 1);
- }
+/*
+ * Serial interrupt routines
+ */
+rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
+{
+ int size;
+ struct rt_serial_rx_fifo* rx_fifo;
+
+ RT_ASSERT(serial != RT_NULL);
+ size = length;
+
+ rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+
+ /* read from software FIFO */
+ while (length)
+ {
+ int ch;
+ rt_base_t level;
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+ if (rx_fifo->get_index != rx_fifo->put_index)
+ {
+ ch = rx_fifo->buffer[rx_fifo->get_index];
+ rx_fifo->get_index += 1;
+ if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
+ }
+ else
+ {
+ /* no data, enable interrupt and break out */
+ rt_hw_interrupt_enable(level);
+ break;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ *data = ch & 0xff;
+ data ++; length --;
+ }
+
+ return size - length;
}
-rt_inline int serial_ringbuffer_putchar(struct serial_ringbuffer *rbuffer,
- char ch)
+rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
{
- rt_base_t level;
- rt_uint16_t next_index;
+ int size;
+ struct rt_serial_tx_fifo *tx;
+
+ RT_ASSERT(serial != RT_NULL);
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ size = length;
+ tx = (struct rt_serial_tx_fifo*) serial->serial_tx;
+ RT_ASSERT(tx != RT_NULL);
- next_index = (rbuffer->put_index + 1) & (RT_SERIAL_RB_BUFSZ - 1);
- if (next_index != rbuffer->get_index)
- {
- rbuffer->buffer[rbuffer->put_index] = ch;
- rbuffer->put_index = next_index;
- }
- else
- {
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ while (length)
+ {
+ if (serial->ops->putc(serial, *(char*)data) == -1)
+ {
+ rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER);
+ continue;
+ }
- return -1;
- }
+ data ++; length --;
+ }
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
-
- return 1;
+ return size - length;
}
-rt_inline int serial_ringbuffer_getc(struct serial_ringbuffer *rbuffer)
+/*
+ * Serial DMA routines
+ */
+rt_inline int _serial_dma_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
{
- int ch;
- rt_base_t level;
+ rt_base_t level;
+ int result = RT_EOK;
+ struct rt_serial_rx_dma *rx_dma;
- ch = -1;
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
- if (rbuffer->get_index != rbuffer->put_index)
- {
- ch = rbuffer->buffer[rbuffer->get_index];
- rbuffer->get_index = (rbuffer->get_index + 1) & (RT_SERIAL_RB_BUFSZ - 1);
- }
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ RT_ASSERT((serial != RT_NULL) && (data != RT_NULL));
+ rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
+ RT_ASSERT(rx_dma != RT_NULL);
+
+ level = rt_hw_interrupt_disable();
+ if (rx_dma->activated != RT_TRUE)
+ {
+ rx_dma->activated = RT_TRUE;
+ serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_RX);
+ }
+ else result = -RT_EBUSY;
+ rt_hw_interrupt_enable(level);
- return ch;
+ if (result == RT_EOK) return length;
+
+ rt_set_errno(result);
+ return 0;
}
-rt_inline rt_uint32_t serial_ringbuffer_size(struct serial_ringbuffer *rbuffer)
+rt_inline int _serial_dma_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
{
- rt_uint32_t size;
- rt_base_t level;
+ rt_base_t level;
+ rt_err_t result;
+ struct rt_serial_tx_dma *tx_dma;
+
+ tx_dma = (struct rt_serial_tx_dma*)(serial->serial_tx);
+
+ result = rt_data_queue_push(&(tx_dma->data_queue), data, length, RT_WAITING_FOREVER);
+ if (result == RT_EOK)
+ {
+ level = rt_hw_interrupt_disable();
+ if (tx_dma->activated != RT_TRUE)
+ {
+ tx_dma->activated = RT_TRUE;
+ rt_hw_interrupt_enable(level);
- level = rt_hw_interrupt_disable();
- size = (rbuffer->put_index - rbuffer->get_index) & (RT_SERIAL_RB_BUFSZ - 1);
- rt_hw_interrupt_enable(level);
+ /* make a DMA transfer */
+ serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_TX);
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
- return size;
+ return length;
+ }
+ else
+ {
+ rt_set_errno(result);
+ return 0;
+ }
}
/* RT-Thread Device Interface */
-
/*
- * This function initializes serial
+ * This function initializes serial device.
*/
static rt_err_t rt_serial_init(struct rt_device *dev)
{
@@ -132,61 +225,107 @@ static rt_err_t rt_serial_init(struct rt_device *dev)
RT_ASSERT(dev != RT_NULL);
serial = (struct rt_serial_device *)dev;
- if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
- {
- /* apply configuration */
- if (serial->ops->configure)
- result = serial->ops->configure(serial, &serial->config);
-
- if (result != RT_EOK)
- return result;
-
- if (dev->flag & RT_DEVICE_FLAG_INT_RX)
- serial_ringbuffer_init(serial->int_rx);
-
- if (dev->flag & RT_DEVICE_FLAG_INT_TX)
- {
- /* not supported yet */
- /*
- serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_NULL);
- serial_ringbuffer_init(serial->int_tx);
- serial->int_sending_flag = RT_FALSE;
- */
- }
+ /* initialize rx/tx */
+ serial->serial_rx = RT_NULL;
+ serial->serial_tx = RT_NULL;
- if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
- {
- serial->dma_flag = RT_FALSE;
-
- /* init data queue */
- rt_data_queue_init(&(serial->tx_dq), RT_SERIAL_TX_DATAQUEUE_SIZE,
- RT_SERIAL_TX_DATAQUEUE_LWM, RT_NULL);
- }
+ /* apply configuration */
+ if (serial->ops->configure)
+ result = serial->ops->configure(serial, &serial->config);
- /* set activated */
- dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
- }
-
- return result;
+ return result;
}
static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)
{
struct rt_serial_device *serial;
- rt_uint32_t int_flags = 0;
RT_ASSERT(dev != RT_NULL);
serial = (struct rt_serial_device *)dev;
- if (dev->flag & RT_DEVICE_FLAG_INT_RX)
- int_flags = RT_SERIAL_RX_INT;
- if (dev->flag & RT_DEVICE_FLAG_INT_TX)
- int_flags |= RT_SERIAL_TX_INT;
+ /* check device flag with the open flag */
+ if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX))
+ return -RT_EIO;
+ if ((oflag & RT_DEVICE_FLAG_DMA_TX) && !(dev->flag & RT_DEVICE_FLAG_DMA_TX))
+ return -RT_EIO;
+ if ((oflag & RT_DEVICE_FLAG_INT_RX) && !(dev->flag & RT_DEVICE_FLAG_INT_RX))
+ return -RT_EIO;
+ if ((oflag & RT_DEVICE_FLAG_INT_TX) && !(dev->flag & RT_DEVICE_FLAG_INT_TX))
+ return -RT_EIO;
- if (int_flags)
- {
- serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)int_flags);
- }
+ /* get open flags */
+ dev->open_flag = oflag & 0xff;
+
+ /* initialize the Rx/Tx structure according to open flag */
+ if (serial->serial_rx == RT_NULL)
+ {
+ if (oflag & RT_DEVICE_FLAG_DMA_RX)
+ {
+ struct rt_serial_rx_dma* rx_dma;
+
+ rx_dma = (struct rt_serial_rx_dma*) rt_malloc (sizeof(struct rt_serial_rx_dma));
+ RT_ASSERT(rx_dma != RT_NULL);
+ rx_dma->activated = RT_FALSE;
+
+ serial->serial_rx = rx_dma;
+ dev->open_flag |= RT_DEVICE_FLAG_DMA_RX;
+ }
+ else if (oflag & RT_DEVICE_FLAG_INT_RX)
+ {
+ struct rt_serial_rx_fifo* rx_fifo;
+
+ rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) +
+ serial->config.bufsz);
+ RT_ASSERT(rx_fifo != RT_NULL);
+ rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1);
+ rt_memset(rx_fifo->buffer, 0, RT_SERIAL_RB_BUFSZ);
+ rx_fifo->put_index = 0;
+ rx_fifo->get_index = 0;
+
+ serial->serial_rx = rx_fifo;
+ dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
+ /* configure low level device */
+ serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+ }
+ else
+ {
+ serial->serial_rx = RT_NULL;
+ }
+ }
+
+ if (serial->serial_tx == RT_NULL)
+ {
+ if (oflag & RT_DEVICE_FLAG_DMA_TX)
+ {
+ struct rt_serial_tx_dma* tx_dma;
+
+ tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma));
+ RT_ASSERT(tx_dma != RT_NULL);
+
+ rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL);
+ serial->serial_tx = tx_dma;
+
+ dev->open_flag |= RT_DEVICE_FLAG_DMA_TX;
+ }
+ else if (oflag & RT_DEVICE_FLAG_INT_TX)
+ {
+ struct rt_serial_tx_fifo *tx_fifo;
+
+ tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc(sizeof(struct rt_serial_tx_fifo));
+ RT_ASSERT(tx_fifo != RT_NULL);
+
+ rt_completion_init(&(tx_fifo->completion));
+ serial->serial_tx = tx_fifo;
+
+ dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
+ /* configure low level device */
+ serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX);
+ }
+ else
+ {
+ serial->serial_tx = RT_NULL;
+ }
+ }
return RT_EOK;
}
@@ -194,20 +333,62 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)
static rt_err_t rt_serial_close(struct rt_device *dev)
{
struct rt_serial_device *serial;
- rt_uint32_t int_flags = 0;
RT_ASSERT(dev != RT_NULL);
serial = (struct rt_serial_device *)dev;
- if (dev->flag & RT_DEVICE_FLAG_INT_RX)
- int_flags = RT_SERIAL_RX_INT;
- if (dev->flag & RT_DEVICE_FLAG_INT_TX)
- int_flags |= RT_SERIAL_TX_INT;
+ /* this device has more reference count */
+ if (dev->ref_count > 1) return RT_EOK;
+
+ if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
+ {
+ struct rt_serial_rx_fifo* rx_fifo;
- if (int_flags)
- {
- serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)int_flags);
- }
+ rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+
+ rt_free(rx_fifo);
+ serial->serial_rx = RT_NULL;
+ dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX;
+ /* configure low level device */
+ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX);
+ }
+ else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
+ {
+ struct rt_serial_rx_dma* rx_dma;
+
+ rx_dma = (struct rt_serial_rx_dma*)serial->serial_tx;
+ RT_ASSERT(rx_dma != RT_NULL);
+
+ rt_free(rx_dma);
+ serial->serial_rx = RT_NULL;
+ dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX;
+ }
+
+ if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
+ {
+ struct rt_serial_tx_fifo* tx_fifo;
+
+ tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_rx;
+ RT_ASSERT(tx_fifo != RT_NULL);
+
+ rt_free(tx_fifo);
+ serial->serial_tx = RT_NULL;
+ dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX;
+ /* configure low level device */
+ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX);
+ }
+ else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
+ {
+ struct rt_serial_tx_dma* tx_dma;
+
+ tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx;
+ RT_ASSERT(tx_dma != RT_NULL);
+
+ rt_free(tx_dma);
+ serial->serial_tx = RT_NULL;
+ dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX;
+ }
return RT_EOK;
}
@@ -217,53 +398,23 @@ static rt_size_t rt_serial_read(struct rt_device *dev,
void *buffer,
rt_size_t size)
{
- rt_uint8_t *ptr;
- rt_uint32_t read_nbytes;
struct rt_serial_device *serial;
RT_ASSERT(dev != RT_NULL);
-
- if (size == 0)
- return 0;
+ if (size == 0) return 0;
serial = (struct rt_serial_device *)dev;
- ptr = (rt_uint8_t *)buffer;
+ if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
+ {
+ return _serial_int_rx(serial, buffer, size);
+ }
+ else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
+ {
+ return _serial_dma_rx(serial, buffer, size);
+ }
- if (dev->flag & RT_DEVICE_FLAG_INT_RX)
- {
- /* interrupt mode Rx */
- while (size)
- {
- int ch;
-
- ch = serial_ringbuffer_getc(serial->int_rx);
- if (ch == -1)
- break;
-
- *ptr = ch & 0xff;
- ptr ++;
- size --;
- }
- }
- else
- {
- /* polling mode */
- while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
- {
- *ptr = serial->ops->getc(serial);
- ptr ++;
- }
- }
-
- read_nbytes = (rt_uint32_t)ptr - (rt_uint32_t)buffer;
- /* set error code */
- if (read_nbytes == 0)
- {
- rt_set_errno(-RT_EEMPTY);
- }
-
- return read_nbytes;
+ return _serial_poll_rx(serial, buffer, size);
}
static rt_size_t rt_serial_write(struct rt_device *dev,
@@ -271,90 +422,23 @@ static rt_size_t rt_serial_write(struct rt_device *dev,
const void *buffer,
rt_size_t size)
{
- rt_uint8_t *ptr;
- rt_size_t write_nbytes = 0;
struct rt_serial_device *serial;
RT_ASSERT(dev != RT_NULL);
-
- if (size == 0)
- return 0;
+ if (size == 0) return 0;
serial = (struct rt_serial_device *)dev;
- ptr = (rt_uint8_t*)buffer;
-
- if (dev->flag & RT_DEVICE_FLAG_INT_TX)
- {
- /* warning: data will be discarded if buffer is full */
- while (size)
- {
- if (serial_ringbuffer_putchar(serial->int_tx, *ptr) != -1)
- {
- ptr ++;
- size --;
- }
- else
- break;
- }
- }
- else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
- {
- rt_base_t level;
- rt_err_t result;
-
- RT_ASSERT(0 == (dev->flag & RT_DEVICE_FLAG_STREAM));
-
- result = rt_data_queue_push(&(serial->tx_dq), buffer, size, 20);
- if (result == RT_EOK)
- {
- level = rt_hw_interrupt_disable();
- if (serial->dma_flag == RT_FALSE)
- {
- serial->dma_flag = RT_TRUE;
- rt_hw_interrupt_enable(level);
- serial->ops->dma_transmit(serial, buffer, size);
- }
- else
- rt_hw_interrupt_enable(level);
-
- return size;
- }
- else
- {
- rt_set_errno(result);
-
- return 0;
- }
- }
- else
- {
- /* polling mode */
- while (size)
- {
- /*
- * to be polite with serial console add a line feed
- * to the carriage return character
- */
- if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM))
- {
- serial->ops->putc(serial, '\r');
- }
+ if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
+ {
+ _serial_int_tx(serial, buffer, size);
+ }
+ else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
+ {
+ _serial_dma_tx(serial, buffer, size);
+ }
- serial->ops->putc(serial, *ptr);
-
- ++ ptr;
- -- size;
- }
- }
-
- write_nbytes = (rt_uint32_t)ptr - (rt_uint32_t)buffer;
- if (write_nbytes == 0)
- {
- rt_set_errno(-RT_EFULL);
- }
-
- return write_nbytes;
+ return _serial_poll_tx(serial, buffer, size);
}
static rt_err_t rt_serial_control(struct rt_device *dev,
@@ -422,56 +506,108 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
}
/* ISR for serial interrupt */
-void rt_hw_serial_isr(struct rt_serial_device *serial)
+void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
{
- int ch = -1;
+ switch (event & 0xff)
+ {
+ case RT_SERIAL_EVENT_RX_IND:
+ {
+ int ch = -1;
+ rt_base_t level;
+ struct rt_serial_rx_fifo* rx_fifo;
- /* interrupt mode receive */
- RT_ASSERT(serial->parent.flag & RT_DEVICE_FLAG_INT_RX);
+ rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+
+ /* interrupt mode receive */
+ RT_ASSERT(serial->parent.open_flag & RT_DEVICE_FLAG_INT_RX);
+
+ while (1)
+ {
+ ch = serial->ops->getc(serial);
+ if (ch == -1) break;
- while (1)
- {
- ch = serial->ops->getc(serial);
- if (ch == -1)
- break;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ rx_fifo->buffer[rx_fifo->put_index] = ch;
+ rx_fifo->put_index += 1;
+ if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;
+
+ /* if the next position is read index, discard this 'read char' */
+ if (rx_fifo->put_index == rx_fifo->get_index)
+ {
+ rx_fifo->get_index += 1;
+ if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ }
+
+ /* invoke callback */
+ if (serial->parent.rx_indicate != RT_NULL)
+ {
+ rt_size_t rx_length;
+
+ /* get rx length */
+ level = rt_hw_interrupt_disable();
+ rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index):
+ (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index));
+ rt_hw_interrupt_enable(level);
- serial_ringbuffer_putc(serial->int_rx, ch);
- }
+ serial->parent.rx_indicate(&serial->parent, rx_length);
+ }
+ break;
+ }
+ case RT_SERIAL_EVENT_TX_DONE:
+ {
+ struct rt_serial_tx_fifo* tx_fifo;
- /* invoke callback */
- if (serial->parent.rx_indicate != RT_NULL)
- {
- rt_size_t rx_length;
+ tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx;
+ rt_completion_done(&(tx_fifo->completion));
+ break;
+ }
+ case RT_SERIAL_EVENT_TX_DMADONE:
+ {
+ const void *data_ptr;
+ rt_size_t data_size;
+ const void *last_data_ptr;
+ struct rt_serial_tx_dma* tx_dma;
- /* get rx length */
- rx_length = serial_ringbuffer_size(serial->int_rx);
- serial->parent.rx_indicate(&serial->parent, rx_length);
- }
-}
-
-/*
- * ISR for DMA mode Tx
- */
-void rt_hw_serial_dma_tx_isr(struct rt_serial_device *serial)
-{
- const void *data_ptr;
- rt_size_t data_size;
- const void *last_data_ptr;
-
- rt_data_queue_pop(&(serial->tx_dq), &last_data_ptr, &data_size, 0);
- if (RT_EOK == rt_data_queue_peak(&(serial->tx_dq), &data_ptr, &data_size))
- {
- /* transmit next data node */
- serial->ops->dma_transmit(serial, data_ptr, data_size);
- }
- else
- {
- serial->dma_flag = RT_FALSE;
- }
+ tx_dma = (struct rt_serial_tx_dma*) serial->serial_tx;
+
+ rt_data_queue_pop(&(tx_dma->data_queue), &last_data_ptr, &data_size, 0);
+ if (rt_data_queue_peak(&(tx_dma->data_queue), &data_ptr, &data_size) == RT_EOK)
+ {
+ /* transmit next data node */
+ tx_dma->activated = RT_TRUE;
+ serial->ops->dma_transmit(serial, data_ptr, data_size, RT_SERIAL_DMA_TX);
+ }
+ else
+ {
+ tx_dma->activated = RT_FALSE;
+ }
+
+ /* invoke callback */
+ if (serial->parent.tx_complete != RT_NULL)
+ {
+ serial->parent.tx_complete(&serial->parent, (void*)last_data_ptr);
+ }
+ break;
+ }
+ case RT_SERIAL_EVENT_RX_DMADONE:
+ {
+ int length;
+ struct rt_serial_rx_dma* rx_dma;
- /* invoke callback */
- if (serial->parent.tx_complete != RT_NULL)
- {
- serial->parent.tx_complete(&serial->parent, (void*)last_data_ptr);
- }
+ rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
+ /* get DMA rx length */
+ length = (event & (~0xff)) >> 8;
+ serial->parent.rx_indicate(&(serial->parent), length);
+ rx_dma->activated = RT_FALSE;
+ break;
+ }
+ }
}
diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript
index f114ef7a41..f9fc82a777 100644
--- a/components/drivers/spi/SConscript
+++ b/components/drivers/spi/SConscript
@@ -1,8 +1,28 @@
from building import *
-cwd = GetCurrentDir()
-src = Glob('*.c')
+cwd = GetCurrentDir()
+src = ['spi_core.c', 'spi_dev.c']
CPPPATH = [cwd + '/../include']
+
+src_device = []
+
+if GetDepend('RT_USING_SPI_WIFI'):
+ src_device += ['spi_wifi_rw009.c']
+
+if GetDepend('RT_USING_W25QXX'):
+ src_device += ['spi_flash_w25qxx.c']
+
+if GetDepend('RT_USING_ENC28J60'):
+ src_device += ['enc28j60.c']
+
+if GetDepend('RT_USING_AT45DBXX'):
+ src_device += ['spi_flash_at45dbxx.c']
+
+if GetDepend('RT_USING_SST25VFXX'):
+ src_device += ['spi_flash_sst25vfxx.c']
+
+src += src_device
+
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SPI'], CPPPATH = CPPPATH)
Return('group')
diff --git a/components/drivers/spi/device_driver_list.txt b/components/drivers/spi/device_driver_list.txt
new file mode 100644
index 0000000000..2c9d6a16b8
--- /dev/null
+++ b/components/drivers/spi/device_driver_list.txt
@@ -0,0 +1,15 @@
+spi_wifi_rw009.c/spi_wifi_rw009.h
+RW009
+http://www.rt-thread.com/
+
+enc28j60.c/enc28j60.h
+http://www.microchip.com/
+
+spi_flash_at45dbxx.c/spi_flash_at45dbxx.h
+http://www.atmel.com/
+
+spi_flash_sst25vfxx.c/spi_flash_sst25vfxx.h
+http://www.microchip.com/
+
+spi_flash_w25qxx.c/spi_flash_w25qxx.h
+http://www.winbond.com/
diff --git a/components/drivers/spi/enc28j60.c b/components/drivers/spi/enc28j60.c
new file mode 100644
index 0000000000..68f1181dcc
--- /dev/null
+++ b/components/drivers/spi/enc28j60.c
@@ -0,0 +1,876 @@
+#include "enc28j60.h"
+
+#define NET_TRACE
+#define ETH_RX_DUMP
+#define ETH_TX_DUMP
+
+#ifdef NET_TRACE
+#define NET_DEBUG rt_kprintf
+#else
+#define NET_DEBUG(...)
+#endif /* #ifdef NET_TRACE */
+
+struct enc28j60_tx_list_typedef
+{
+ struct enc28j60_tx_list_typedef * prev;
+ struct enc28j60_tx_list_typedef * next;
+ rt_uint32_t addr; /* pkt addr in buffer */
+ rt_uint32_t len; /* pkt len */
+ volatile rt_bool_t free; /* 0:busy, 1:free */
+};
+static struct enc28j60_tx_list_typedef enc28j60_tx_list[2];
+static volatile struct enc28j60_tx_list_typedef * tx_current;
+static volatile struct enc28j60_tx_list_typedef * tx_ack;
+static struct rt_event tx_event;
+
+/* private enc28j60 define */
+/* enc28j60 spi interface function */
+static uint8_t spi_read_op(struct rt_spi_device * spi_device, uint8_t op, uint8_t address);
+static void spi_write_op(struct rt_spi_device * spi_device, uint8_t op, uint8_t address, uint8_t data);
+
+static uint8_t spi_read(struct rt_spi_device * spi_device, uint8_t address);
+static void spi_write(struct rt_spi_device * spi_device, rt_uint8_t address, rt_uint8_t data);
+
+static void enc28j60_clkout(struct rt_spi_device * spi_device, rt_uint8_t clk);
+static void enc28j60_set_bank(struct rt_spi_device * spi_device, uint8_t address);
+static uint32_t enc28j60_interrupt_disable(struct rt_spi_device * spi_device);
+static void enc28j60_interrupt_enable(struct rt_spi_device * spi_device, uint32_t level);
+
+static uint16_t enc28j60_phy_read(struct rt_spi_device * spi_device, rt_uint8_t address);
+static void enc28j60_phy_write(struct rt_spi_device * spi_device, rt_uint8_t address, uint16_t data);
+static rt_bool_t enc28j60_check_link_status(struct rt_spi_device * spi_device);
+
+#define enc28j60_lock(dev) rt_mutex_take(&((struct net_device*)dev)->lock, RT_WAITING_FOREVER);
+#define enc28j60_unlock(dev) rt_mutex_release(&((struct net_device*)dev)->lock);
+
+static struct net_device enc28j60_dev;
+static uint8_t Enc28j60Bank;
+//struct rt_spi_device * spi_device;
+static uint16_t NextPacketPtr;
+
+static void _delay_us(uint32_t us)
+{
+ volatile uint32_t len;
+ for (; us > 0; us --)
+ for (len = 0; len < 20; len++ );
+}
+
+/* enc28j60 spi interface function */
+static uint8_t spi_read_op(struct rt_spi_device * spi_device, uint8_t op, uint8_t address)
+{
+ uint8_t send_buffer[2];
+ uint8_t recv_buffer[1];
+ uint32_t send_size = 1;
+
+ send_buffer[0] = op | (address & ADDR_MASK);
+ send_buffer[1] = 0xFF;
+
+ /* do dummy read if needed (for mac and mii, see datasheet page 29). */
+ if(address & 0x80)
+ {
+ send_size = 2;
+ }
+
+ rt_spi_send_then_recv(spi_device, send_buffer, send_size, recv_buffer, 1);
+ return (recv_buffer[0]);
+}
+
+static void spi_write_op(struct rt_spi_device * spi_device, uint8_t op, uint8_t address, uint8_t data)
+{
+ uint32_t level;
+ uint8_t buffer[2];
+
+ level = rt_hw_interrupt_disable();
+
+ buffer[0] = op | (address & ADDR_MASK);
+ buffer[1] = data;
+ rt_spi_send(spi_device, buffer, 2);
+
+ rt_hw_interrupt_enable(level);
+}
+
+/* enc28j60 function */
+static void enc28j60_clkout(struct rt_spi_device * spi_device, rt_uint8_t clk)
+{
+ /* setup clkout: 2 is 12.5MHz: */
+ spi_write(spi_device, ECOCON, clk & 0x7);
+}
+
+static void enc28j60_set_bank(struct rt_spi_device * spi_device, uint8_t address)
+{
+ /* set the bank (if needed) .*/
+ if((address & BANK_MASK) != Enc28j60Bank)
+ {
+ /* set the bank. */
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
+ Enc28j60Bank = (address & BANK_MASK);
+ }
+}
+
+static uint8_t spi_read(struct rt_spi_device * spi_device, uint8_t address)
+{
+ /* set the bank. */
+ enc28j60_set_bank(spi_device, address);
+ /* do the read. */
+ return spi_read_op(spi_device, ENC28J60_READ_CTRL_REG, address);
+}
+
+static void spi_write(struct rt_spi_device * spi_device, rt_uint8_t address, rt_uint8_t data)
+{
+ /* set the bank. */
+ enc28j60_set_bank(spi_device, address);
+ /* do the write. */
+ spi_write_op(spi_device, ENC28J60_WRITE_CTRL_REG, address, data);
+}
+
+static uint16_t enc28j60_phy_read(struct rt_spi_device * spi_device, rt_uint8_t address)
+{
+ uint16_t value;
+
+ /* Set the right address and start the register read operation. */
+ spi_write(spi_device, MIREGADR, address);
+ spi_write(spi_device, MICMD, MICMD_MIIRD);
+
+ _delay_us(15);
+
+ /* wait until the PHY read completes. */
+ while(spi_read(spi_device, MISTAT) & MISTAT_BUSY);
+
+ /* reset reading bit */
+ spi_write(spi_device, MICMD, 0x00);
+
+ value = spi_read(spi_device, MIRDL) | spi_read(spi_device, MIRDH)<<8;
+
+ return (value);
+}
+
+static void enc28j60_phy_write(struct rt_spi_device * spi_device, rt_uint8_t address, uint16_t data)
+{
+ /* set the PHY register address. */
+ spi_write(spi_device, MIREGADR, address);
+
+ /* write the PHY data. */
+ spi_write(spi_device, MIWRL, data);
+ spi_write(spi_device, MIWRH, data>>8);
+
+ /* wait until the PHY write completes. */
+ while(spi_read(spi_device, MISTAT) & MISTAT_BUSY)
+ {
+ _delay_us(15);
+ }
+}
+
+static uint32_t enc28j60_interrupt_disable(struct rt_spi_device * spi_device)
+{
+ uint32_t level;
+
+ /* switch to bank 0 */
+ enc28j60_set_bank(spi_device, EIE);
+
+ /* get last interrupt level */
+ level = spi_read(spi_device, EIE);
+ /* disable interrutps */
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIE, level);
+
+ return level;
+}
+
+static void enc28j60_interrupt_enable(struct rt_spi_device * spi_device, uint32_t level)
+{
+ /* switch to bank 0 */
+ enc28j60_set_bank(spi_device, EIE);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, EIE, level);
+}
+
+/*
+ * Access the PHY to determine link status
+ */
+static rt_bool_t enc28j60_check_link_status(struct rt_spi_device * spi_device)
+{
+ uint16_t reg;
+ int duplex;
+
+ reg = enc28j60_phy_read(spi_device, PHSTAT2);
+ duplex = reg & PHSTAT2_DPXSTAT;
+
+ if (reg & PHSTAT2_LSTAT)
+ {
+ /* on */
+ return RT_TRUE;
+ }
+ else
+ {
+ /* off */
+ return RT_FALSE;
+ }
+}
+
+
+/************************* RT-Thread Device Interface *************************/
+void enc28j60_isr(void)
+{
+ eth_device_ready(&enc28j60_dev.parent);
+ NET_DEBUG("enc28j60_isr\r\n");
+}
+
+static void _tx_chain_init(void)
+{
+ enc28j60_tx_list[0].next = &enc28j60_tx_list[1];
+ enc28j60_tx_list[1].next = &enc28j60_tx_list[0];
+
+ enc28j60_tx_list[0].prev = &enc28j60_tx_list[1];
+ enc28j60_tx_list[1].prev = &enc28j60_tx_list[0];
+
+ enc28j60_tx_list[0].addr = TXSTART_INIT;
+ enc28j60_tx_list[1].addr = TXSTART_INIT + MAX_TX_PACKAGE_SIZE;
+
+ enc28j60_tx_list[0].free = RT_TRUE;
+ enc28j60_tx_list[1].free = RT_TRUE;
+
+ tx_current = &enc28j60_tx_list[0];
+ tx_ack = tx_current;
+}
+
+/* initialize the interface */
+static rt_err_t enc28j60_init(rt_device_t dev)
+{
+ struct net_device * enc28j60 = (struct net_device *)dev;
+ struct rt_spi_device * spi_device = enc28j60->spi_device;
+
+ enc28j60_lock(dev);
+
+ _tx_chain_init();
+
+ // perform system reset
+ spi_write_op(spi_device, ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
+ rt_thread_delay(RT_TICK_PER_SECOND/50); /* delay 20ms */
+
+ NextPacketPtr = RXSTART_INIT;
+
+ // Rx start
+ spi_write(spi_device, ERXSTL, RXSTART_INIT&0xFF);
+ spi_write(spi_device, ERXSTH, RXSTART_INIT>>8);
+ // set receive pointer address
+ spi_write(spi_device, ERXRDPTL, RXSTOP_INIT&0xFF);
+ spi_write(spi_device, ERXRDPTH, RXSTOP_INIT>>8);
+ // RX end
+ spi_write(spi_device, ERXNDL, RXSTOP_INIT&0xFF);
+ spi_write(spi_device, ERXNDH, RXSTOP_INIT>>8);
+
+ // TX start
+ spi_write(spi_device, ETXSTL, TXSTART_INIT&0xFF);
+ spi_write(spi_device, ETXSTH, TXSTART_INIT>>8);
+ // set transmission pointer address
+ spi_write(spi_device, EWRPTL, TXSTART_INIT&0xFF);
+ spi_write(spi_device, EWRPTH, TXSTART_INIT>>8);
+ // TX end
+ spi_write(spi_device, ETXNDL, TXSTOP_INIT&0xFF);
+ spi_write(spi_device, ETXNDH, TXSTOP_INIT>>8);
+
+ // do bank 1 stuff, packet filter:
+ // For broadcast packets we allow only ARP packtets
+ // All other packets should be unicast only for our mac (MAADR)
+ //
+ // The pattern to match on is therefore
+ // Type ETH.DST
+ // ARP BROADCAST
+ // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
+ // in binary these poitions are:11 0000 0011 1111
+ // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
+ spi_write(spi_device, ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_BCEN);
+
+ // do bank 2 stuff
+ // enable MAC receive
+ spi_write(spi_device, MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
+ // enable automatic padding to 60bytes and CRC operations
+ // spi_write_op(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX);
+ // bring MAC out of reset
+
+ // set inter-frame gap (back-to-back)
+ // spi_write(MABBIPG, 0x12);
+ spi_write(spi_device, MABBIPG, 0x15);
+
+ spi_write(spi_device, MACON4, MACON4_DEFER);
+ spi_write(spi_device, MACLCON2, 63);
+
+ // set inter-frame gap (non-back-to-back)
+ spi_write(spi_device, MAIPGL, 0x12);
+ spi_write(spi_device, MAIPGH, 0x0C);
+
+ // Set the maximum packet size which the controller will accept
+ // Do not send packets longer than MAX_FRAMELEN:
+ spi_write(spi_device, MAMXFLL, MAX_FRAMELEN&0xFF);
+ spi_write(spi_device, MAMXFLH, MAX_FRAMELEN>>8);
+
+ // do bank 3 stuff
+ // write MAC address
+ // NOTE: MAC address in ENC28J60 is byte-backward
+ spi_write(spi_device, MAADR0, enc28j60->dev_addr[5]);
+ spi_write(spi_device, MAADR1, enc28j60->dev_addr[4]);
+ spi_write(spi_device, MAADR2, enc28j60->dev_addr[3]);
+ spi_write(spi_device, MAADR3, enc28j60->dev_addr[2]);
+ spi_write(spi_device, MAADR4, enc28j60->dev_addr[1]);
+ spi_write(spi_device, MAADR5, enc28j60->dev_addr[0]);
+
+ /* output off */
+ spi_write(spi_device, ECOCON, 0x00);
+
+ // enc28j60_phy_write(PHCON1, 0x00);
+ enc28j60_phy_write(spi_device, PHCON1, PHCON1_PDPXMD); // full duplex
+ // no loopback of transmitted frames
+ enc28j60_phy_write(spi_device, PHCON2, PHCON2_HDLDIS);
+
+ enc28j60_set_bank(spi_device, ECON2);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON2, ECON2_AUTOINC);
+
+ // switch to bank 0
+ enc28j60_set_bank(spi_device, ECON1);
+ // enable all interrutps
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, EIE, 0xFF);
+ // enable packet reception
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
+
+ /* clock out */
+ enc28j60_clkout(spi_device, 2);
+
+ enc28j60_phy_write(spi_device, PHLCON, 0xD76); //0x476
+ rt_thread_delay(RT_TICK_PER_SECOND/50); /* delay 20ms */
+
+ enc28j60_unlock(dev);
+ return RT_EOK;
+}
+
+/* control the interface */
+static rt_err_t enc28j60_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+ struct net_device * enc28j60 = (struct net_device *)dev;
+ switch(cmd)
+ {
+ case NIOCTL_GADDR:
+ /* get mac address */
+ if(args) rt_memcpy(args, enc28j60->dev_addr, 6);
+ else return -RT_ERROR;
+ break;
+
+ default :
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/* Open the ethernet interface */
+static rt_err_t enc28j60_open(rt_device_t dev, uint16_t oflag)
+{
+ return RT_EOK;
+}
+
+/* Close the interface */
+static rt_err_t enc28j60_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+/* Read */
+static rt_size_t enc28j60_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return RT_EOK;
+}
+
+/* Write */
+static rt_size_t enc28j60_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+/* ethernet device interface */
+/* Transmit packet. */
+static rt_err_t enc28j60_tx( rt_device_t dev, struct pbuf* p)
+{
+ struct net_device * enc28j60 = (struct net_device *)dev;
+ struct rt_spi_device * spi_device = enc28j60->spi_device;
+ struct pbuf* q;
+ rt_uint32_t level;
+#ifdef ETH_TX_DUMP
+ rt_size_t dump_count = 0;
+ rt_uint8_t * dump_ptr;
+ rt_size_t dump_i;
+#endif
+
+ if(tx_current->free == RT_FALSE)
+ {
+ NET_DEBUG("[Tx] no empty buffer!\r\n");
+ while(tx_current->free == RT_FALSE)
+ {
+ rt_err_t result;
+ rt_uint32_t recved;
+
+ /* there is no block yet, wait a flag */
+ result = rt_event_recv(&tx_event, 0x01,
+ RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &recved);
+
+ RT_ASSERT(result == RT_EOK);
+ }
+ NET_DEBUG("[Tx] wait empty buffer done!\r\n");
+ }
+
+ enc28j60_lock(dev);
+
+ /* disable enc28j60 interrupt */
+ level = enc28j60_interrupt_disable(spi_device);
+
+ // Set the write pointer to start of transmit buffer area
+// spi_write(EWRPTL, TXSTART_INIT&0xFF);
+// spi_write(EWRPTH, TXSTART_INIT>>8);
+ spi_write(spi_device, EWRPTL, (tx_current->addr)&0xFF);
+ spi_write(spi_device, EWRPTH, (tx_current->addr)>>8);
+ // Set the TXND pointer to correspond to the packet size given
+ tx_current->len = p->tot_len;
+// spi_write(ETXNDL, (TXSTART_INIT+ p->tot_len + 1)&0xFF);
+// spi_write(ETXNDH, (TXSTART_INIT+ p->tot_len + 1)>>8);
+
+ // write per-packet control byte (0x00 means use macon3 settings)
+ spi_write_op(spi_device, ENC28J60_WRITE_BUF_MEM, 0, 0x00);
+
+#ifdef ETH_TX_DUMP
+ NET_DEBUG("tx_dump, size:%d\r\n", p->tot_len);
+#endif
+ for (q = p; q != NULL; q = q->next)
+ {
+ uint8_t cmd = ENC28J60_WRITE_BUF_MEM;
+ rt_spi_send_then_send(enc28j60->spi_device, &cmd, 1, q->payload, q->len);
+#ifdef ETH_RX_DUMP
+ dump_ptr = q->payload;
+ for(dump_i=0; dump_i<q->len; dump_i++)
+ {
+ NET_DEBUG("%02x ", *dump_ptr);
+ if( ((dump_count+1)%8) == 0 )
+ {
+ NET_DEBUG(" ");
+ }
+ if( ((dump_count+1)%16) == 0 )
+ {
+ NET_DEBUG("\r\n");
+ }
+ dump_count++;
+ dump_ptr++;
+ }
+#endif
+ }
+#ifdef ETH_RX_DUMP
+ NET_DEBUG("\r\n");
+#endif
+
+ // send the contents of the transmit buffer onto the network
+ if(tx_current == tx_ack)
+ {
+ NET_DEBUG("[Tx] stop, restart!\r\n");
+ // TX start
+ spi_write(spi_device, ETXSTL, (tx_current->addr)&0xFF);
+ spi_write(spi_device, ETXSTH, (tx_current->addr)>>8);
+ // TX end
+ spi_write(spi_device, ETXNDL, (tx_current->addr + tx_current->len)&0xFF);
+ spi_write(spi_device, ETXNDH, (tx_current->addr + tx_current->len)>>8);
+
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
+ }
+ else
+ {
+ NET_DEBUG("[Tx] busy, add to chain!\r\n");
+ }
+
+ tx_current->free = RT_FALSE;
+ tx_current = tx_current->next;
+
+ /* Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. */
+ if( (spi_read(spi_device, EIR) & EIR_TXERIF) )
+ {
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
+ }
+
+ /* enable enc28j60 interrupt */
+ enc28j60_interrupt_enable(spi_device, level);
+
+ enc28j60_unlock(dev);
+
+ return RT_EOK;
+}
+
+/* recv packet. */
+static struct pbuf *enc28j60_rx(rt_device_t dev)
+{
+ struct net_device * enc28j60 = (struct net_device *)dev;
+ struct rt_spi_device * spi_device = enc28j60->spi_device;
+ struct pbuf* p = RT_NULL;
+
+ uint8_t eir, eir_clr;
+ uint32_t pk_counter;
+ rt_uint32_t level;
+ rt_uint32_t len;
+ rt_uint16_t rxstat;
+
+ enc28j60_lock(dev);
+
+ /* disable enc28j60 interrupt */
+ level = enc28j60_interrupt_disable(spi_device);
+
+ /* get EIR */
+ eir = spi_read(spi_device, EIR);
+
+ while(eir & ~EIR_PKTIF)
+ {
+ eir_clr = 0;
+
+ /* clear PKTIF */
+ if (eir & EIR_PKTIF)
+ {
+ NET_DEBUG("EIR_PKTIF\r\n");
+
+ /* switch to bank 0. */
+ enc28j60_set_bank(spi_device, EIE);
+ /* disable rx interrutps. */
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIE, EIE_PKTIE);
+ eir_clr |= EIR_PKTIF;
+// enc28j60_set_bank(spi_device, EIR);
+// spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF);
+ }
+
+ /* clear DMAIF */
+ if (eir & EIR_DMAIF)
+ {
+ NET_DEBUG("EIR_DMAIF\r\n");
+ eir_clr |= EIR_DMAIF;
+// enc28j60_set_bank(spi_device, EIR);
+// spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, EIR_DMAIF);
+ }
+
+ /* LINK changed handler */
+ if ( eir & EIR_LINKIF)
+ {
+ rt_bool_t link_status;
+
+ NET_DEBUG("EIR_LINKIF\r\n");
+ link_status = enc28j60_check_link_status(spi_device);
+
+ /* read PHIR to clear the flag */
+ enc28j60_phy_read(spi_device, PHIR);
+ eir_clr |= EIR_LINKIF;
+// enc28j60_set_bank(spi_device, EIR);
+// spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, EIR_LINKIF);
+
+ eth_device_linkchange(&(enc28j60->parent), link_status);
+ }
+
+ if (eir & EIR_TXIF)
+ {
+ /* A frame has been transmitted. */
+ enc28j60_set_bank(spi_device, EIR);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXIF);
+
+ tx_ack->free = RT_TRUE;
+ tx_ack = tx_ack->next;
+ if(tx_ack->free == RT_FALSE)
+ {
+ NET_DEBUG("[tx isr] Tx chain not empty, continue send the next pkt!\r\n");
+ // TX start
+ spi_write(spi_device, ETXSTL, (tx_ack->addr)&0xFF);
+ spi_write(spi_device, ETXSTH, (tx_ack->addr)>>8);
+ // TX end
+ spi_write(spi_device, ETXNDL, (tx_ack->addr + tx_ack->len)&0xFF);
+ spi_write(spi_device, ETXNDH, (tx_ack->addr + tx_ack->len)>>8);
+
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
+ }
+ else
+ {
+ NET_DEBUG("[tx isr] Tx chain empty, stop!\r\n");
+ }
+
+ /* set event */
+ rt_event_send(&tx_event, 0x01);
+ }
+
+ /* wake up handler */
+ if ( eir & EIR_WOLIF)
+ {
+ NET_DEBUG("EIR_WOLIF\r\n");
+ eir_clr |= EIR_WOLIF;
+// enc28j60_set_bank(spi_device, EIR);
+// spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, EIR_WOLIF);
+ }
+
+ /* TX Error handler */
+ if ((eir & EIR_TXERIF) != 0)
+ {
+ NET_DEBUG("EIR_TXERIF re-start tx chain!\r\n");
+ enc28j60_set_bank(spi_device, ECON1);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
+ eir_clr |= EIR_TXERIF;
+// enc28j60_set_bank(spi_device, EIR);
+// spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF);
+
+ /* re-init tx chain */
+ _tx_chain_init();
+ }
+
+ /* RX Error handler */
+ if ((eir & EIR_RXERIF) != 0)
+ {
+ NET_DEBUG("EIR_RXERIF re-start rx!\r\n");
+
+ NextPacketPtr = RXSTART_INIT;
+ enc28j60_set_bank(spi_device, ECON1);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXRST);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXRST);
+ /* switch to bank 0. */
+ enc28j60_set_bank(spi_device, ECON1);
+ /* enable packet reception. */
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
+ eir_clr |= EIR_RXERIF;
+// enc28j60_set_bank(spi_device, EIR);
+// spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, EIR_RXERIF);
+ }
+
+ enc28j60_set_bank(spi_device, EIR);
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_CLR, EIR, eir_clr);
+
+ eir = spi_read(spi_device, EIR);
+ }
+
+ /* read pkt */
+ pk_counter = spi_read(spi_device, EPKTCNT);
+ if(pk_counter)
+ {
+ /* Set the read pointer to the start of the received packet. */
+ spi_write(spi_device, ERDPTL, (NextPacketPtr));
+ spi_write(spi_device, ERDPTH, (NextPacketPtr)>>8);
+
+ /* read the next packet pointer. */
+ NextPacketPtr = spi_read_op(spi_device, ENC28J60_READ_BUF_MEM, 0);
+ NextPacketPtr |= spi_read_op(spi_device, ENC28J60_READ_BUF_MEM, 0)<<8;
+
+ /* read the packet length (see datasheet page 43). */
+ len = spi_read_op(spi_device, ENC28J60_READ_BUF_MEM, 0); //0x54
+ len |= spi_read_op(spi_device, ENC28J60_READ_BUF_MEM, 0)<<8; //5554
+
+ len-=4; //remove the CRC count
+
+ // read the receive status (see datasheet page 43)
+ rxstat = spi_read_op(spi_device, ENC28J60_READ_BUF_MEM, 0);
+ rxstat |= ((rt_uint16_t)spi_read_op(spi_device, ENC28J60_READ_BUF_MEM, 0))<<8;
+
+ // check CRC and symbol errors (see datasheet page 44, table 7-3):
+ // The ERXFCON.CRCEN is set by default. Normally we should not
+ // need to check this.
+ if ((rxstat & 0x80)==0)
+ {
+ // invalid
+ len=0;
+ }
+ else
+ {
+ /* allocation pbuf */
+ p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
+ if (p != RT_NULL)
+ {
+ struct pbuf* q;
+#ifdef ETH_RX_DUMP
+ rt_size_t dump_count = 0;
+ rt_uint8_t * dump_ptr;
+ rt_size_t dump_i;
+ NET_DEBUG("rx_dump, size:%d\r\n", len);
+#endif
+ for (q = p; q != RT_NULL; q= q->next)
+ {
+ uint8_t cmd = ENC28J60_READ_BUF_MEM;
+ rt_spi_send_then_recv(spi_device, &cmd, 1, q->payload, q->len);
+#ifdef ETH_RX_DUMP
+ dump_ptr = q->payload;
+ for(dump_i=0; dump_i<q->len; dump_i++)
+ {
+ NET_DEBUG("%02x ", *dump_ptr);
+ if( ((dump_count+1)%8) == 0 )
+ {
+ NET_DEBUG(" ");
+ }
+ if( ((dump_count+1)%16) == 0 )
+ {
+ NET_DEBUG("\r\n");
+ }
+ dump_count++;
+ dump_ptr++;
+ }
+#endif
+ }
+#ifdef ETH_RX_DUMP
+ NET_DEBUG("\r\n");
+#endif
+ }
+ }
+
+ /* Move the RX read pointer to the start of the next received packet. */
+ /* This frees the memory we just read out. */
+ spi_write(spi_device, ERXRDPTL, (NextPacketPtr));
+ spi_write(spi_device, ERXRDPTH, (NextPacketPtr)>>8);
+
+ /* decrement the packet counter indicate we are done with this packet. */
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
+ }
+ else
+ {
+ /* switch to bank 0. */
+ enc28j60_set_bank(spi_device, ECON1);
+ /* enable packet reception. */
+ spi_write_op(spi_device, ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
+
+ level |= EIE_PKTIE;
+ }
+
+ /* enable enc28j60 interrupt */
+ enc28j60_interrupt_enable(spi_device, level);
+
+ enc28j60_unlock(dev);
+
+ return p;
+}
+
+rt_err_t enc28j60_attach(const char * spi_device_name)
+{
+ struct rt_spi_device * spi_device;
+
+ spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
+ if(spi_device == RT_NULL)
+ {
+ NET_DEBUG("spi device %s not found!\r\n", spi_device_name);
+ return -RT_ENOSYS;
+ }
+
+ /* config spi */
+ {
+ struct rt_spi_configuration cfg;
+ cfg.data_width = 8;
+ cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 */
+ cfg.max_hz = 20 * 1000 * 1000; /* SPI Interface with Clock Speeds Up to 20 MHz */
+ rt_spi_configure(spi_device, &cfg);
+ } /* config spi */
+
+ memset(&enc28j60_dev, 0, sizeof(enc28j60_dev));
+
+ rt_event_init(&tx_event, "eth_tx", RT_IPC_FLAG_FIFO);
+ enc28j60_dev.spi_device = spi_device;
+
+ /* detect device */
+ {
+ uint16_t value;
+
+ /* perform system reset. */
+ spi_write_op(spi_device, ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
+ rt_thread_delay(1); /* delay 20ms */
+
+ enc28j60_dev.emac_rev = spi_read(spi_device, EREVID);
+ value = enc28j60_phy_read(spi_device, PHHID2);
+ enc28j60_dev.phy_rev = value&0x0F;
+ enc28j60_dev.phy_pn = (value>>4)&0x3F;
+ enc28j60_dev.phy_id = (enc28j60_phy_read(spi_device, PHHID1) | ((value>>10)<<16))<<3;
+
+ if(enc28j60_dev.phy_id != 0x00280418)
+ {
+ NET_DEBUG("ENC28J60 PHY ID not correct!\r\n");
+ NET_DEBUG("emac_rev:%d\r\n", enc28j60_dev.emac_rev);
+ NET_DEBUG("phy_rev:%02X\r\n", enc28j60_dev.phy_rev);
+ NET_DEBUG("phy_pn:%02X\r\n", enc28j60_dev.phy_pn);
+ NET_DEBUG("phy_id:%08X\r\n", enc28j60_dev.phy_id);
+ return RT_EIO;
+ }
+ }
+
+ /* OUI 00-04-A3 (hex): Microchip Technology, Inc. */
+ enc28j60_dev.dev_addr[0] = 0x00;
+ enc28j60_dev.dev_addr[1] = 0x04;
+ enc28j60_dev.dev_addr[2] = 0xA3;
+ /* set MAC address, only for test */
+ enc28j60_dev.dev_addr[3] = 0x12;
+ enc28j60_dev.dev_addr[4] = 0x34;
+ enc28j60_dev.dev_addr[5] = 0x56;
+
+ /* init rt-thread device struct */
+ enc28j60_dev.parent.parent.type = RT_Device_Class_NetIf;
+ enc28j60_dev.parent.parent.init = enc28j60_init;
+ enc28j60_dev.parent.parent.open = enc28j60_open;
+ enc28j60_dev.parent.parent.close = enc28j60_close;
+ enc28j60_dev.parent.parent.read = enc28j60_read;
+ enc28j60_dev.parent.parent.write = enc28j60_write;
+ enc28j60_dev.parent.parent.control = enc28j60_control;
+
+ /* init rt-thread ethernet device struct */
+ enc28j60_dev.parent.eth_rx = enc28j60_rx;
+ enc28j60_dev.parent.eth_tx = enc28j60_tx;
+
+ rt_mutex_init(&enc28j60_dev.lock, "enc28j60", RT_IPC_FLAG_FIFO);
+
+ eth_device_init(&(enc28j60_dev.parent), "e0");
+
+ return RT_EOK;
+}
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+/*
+ * Debug routine to dump useful register contents
+ */
+static void enc28j60(void)
+{
+ struct rt_spi_device * spi_device = enc28j60_dev.spi_device;
+ enc28j60_lock(&enc28j60_dev);
+
+ rt_kprintf("-- enc28j60 registers:\n");
+ rt_kprintf("HwRevID: 0x%02X\n", spi_read(spi_device, EREVID));
+
+ rt_kprintf("Cntrl: ECON1 ECON2 ESTAT EIR EIE\n");
+ rt_kprintf(" 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ spi_read(spi_device, ECON1),
+ spi_read(spi_device, ECON2),
+ spi_read(spi_device, ESTAT),
+ spi_read(spi_device, EIR),
+ spi_read(spi_device, EIE));
+
+ rt_kprintf("MAC : MACON1 MACON3 MACON4\n");
+ rt_kprintf(" 0x%02X 0x%02X 0x%02X\n",
+ spi_read(spi_device, MACON1),
+ spi_read(spi_device, MACON3),
+ spi_read(spi_device, MACON4));
+
+ rt_kprintf("Rx : ERXST ERXND ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL\n");
+ rt_kprintf(" 0x%04X 0x%04X 0x%04X 0x%04X ",
+ (spi_read(spi_device, ERXSTH) << 8) | spi_read(spi_device, ERXSTL),
+ (spi_read(spi_device, ERXNDH) << 8) | spi_read(spi_device, ERXNDL),
+ (spi_read(spi_device, ERXWRPTH) << 8) | spi_read(spi_device, ERXWRPTL),
+ (spi_read(spi_device, ERXRDPTH) << 8) | spi_read(spi_device, ERXRDPTL));
+
+ rt_kprintf("0x%02X 0x%02X 0x%04X\n",
+ spi_read(spi_device, ERXFCON),
+ spi_read(spi_device, EPKTCNT),
+ (spi_read(spi_device, MAMXFLH) << 8) | spi_read(spi_device, MAMXFLL));
+
+ rt_kprintf("Tx : ETXST ETXND MACLCON1 MACLCON2 MAPHSUP\n");
+ rt_kprintf(" 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X\n",
+ (spi_read(spi_device, ETXSTH) << 8) | spi_read(spi_device, ETXSTL),
+ (spi_read(spi_device, ETXNDH) << 8) | spi_read(spi_device, ETXNDL),
+ spi_read(spi_device, MACLCON1),
+ spi_read(spi_device, MACLCON2),
+ spi_read(spi_device, MAPHSUP));
+
+ rt_kprintf("PHY : PHCON1 PHSTAT1\r\n");
+ rt_kprintf(" 0x%04X 0x%04X\r\n",
+ enc28j60_phy_read(spi_device, PHCON1),
+ enc28j60_phy_read(spi_device, PHSTAT1));
+
+ enc28j60_unlock(&enc28j60_dev);
+}
+FINSH_FUNCTION_EXPORT(enc28j60, dump enc28j60 registers);
+#endif
diff --git a/components/drivers/spi/enc28j60.h b/components/drivers/spi/enc28j60.h
new file mode 100644
index 0000000000..8c647d5fc2
--- /dev/null
+++ b/components/drivers/spi/enc28j60.h
@@ -0,0 +1,329 @@
+#ifndef EN28J60_H_INCLUDED
+#define EN28J60_H_INCLUDED
+
+#include <stdint.h>
+
+#include <rtthread.h>
+#include <drivers/spi.h>
+#include <netif/ethernetif.h>
+
+// ENC28J60 Control Registers
+// Control register definitions are a combination of address,
+// bank number, and Ethernet/MAC/PHY indicator bits.
+// - Register address (bits 0-4)
+// - Bank number (bits 5-6)
+// - MAC/PHY indicator (bit 7)
+#define ADDR_MASK 0x1F
+#define BANK_MASK 0x60
+#define SPRD_MASK 0x80
+// All-bank registers
+#define EIE 0x1B
+#define EIR 0x1C
+#define ESTAT 0x1D
+#define ECON2 0x1E
+#define ECON1 0x1F
+// Bank 0 registers
+#define ERDPTL (0x00|0x00)
+#define ERDPTH (0x01|0x00)
+#define EWRPTL (0x02|0x00)
+#define EWRPTH (0x03|0x00)
+#define ETXSTL (0x04|0x00)
+#define ETXSTH (0x05|0x00)
+#define ETXNDL (0x06|0x00)
+#define ETXNDH (0x07|0x00)
+#define ERXSTL (0x08|0x00)
+#define ERXSTH (0x09|0x00)
+#define ERXNDL (0x0A|0x00)
+#define ERXNDH (0x0B|0x00)
+#define ERXRDPTL (0x0C|0x00)
+#define ERXRDPTH (0x0D|0x00)
+#define ERXWRPTL (0x0E|0x00)
+#define ERXWRPTH (0x0F|0x00)
+#define EDMASTL (0x10|0x00)
+#define EDMASTH (0x11|0x00)
+#define EDMANDL (0x12|0x00)
+#define EDMANDH (0x13|0x00)
+#define EDMADSTL (0x14|0x00)
+#define EDMADSTH (0x15|0x00)
+#define EDMACSL (0x16|0x00)
+#define EDMACSH (0x17|0x00)
+// Bank 1 registers
+#define EHT0 (0x00|0x20)
+#define EHT1 (0x01|0x20)
+#define EHT2 (0x02|0x20)
+#define EHT3 (0x03|0x20)
+#define EHT4 (0x04|0x20)
+#define EHT5 (0x05|0x20)
+#define EHT6 (0x06|0x20)
+#define EHT7 (0x07|0x20)
+#define EPMM0 (0x08|0x20)
+#define EPMM1 (0x09|0x20)
+#define EPMM2 (0x0A|0x20)
+#define EPMM3 (0x0B|0x20)
+#define EPMM4 (0x0C|0x20)
+#define EPMM5 (0x0D|0x20)
+#define EPMM6 (0x0E|0x20)
+#define EPMM7 (0x0F|0x20)
+#define EPMCSL (0x10|0x20)
+#define EPMCSH (0x11|0x20)
+#define EPMOL (0x14|0x20)
+#define EPMOH (0x15|0x20)
+#define EWOLIE (0x16|0x20)
+#define EWOLIR (0x17|0x20)
+#define ERXFCON (0x18|0x20)
+#define EPKTCNT (0x19|0x20)
+// Bank 2 registers
+#define MACON1 (0x00|0x40|0x80)
+#define MACON2 (0x01|0x40|0x80)
+#define MACON3 (0x02|0x40|0x80)
+#define MACON4 (0x03|0x40|0x80)
+#define MABBIPG (0x04|0x40|0x80)
+#define MAIPGL (0x06|0x40|0x80)
+#define MAIPGH (0x07|0x40|0x80)
+#define MACLCON1 (0x08|0x40|0x80)
+#define MACLCON2 (0x09|0x40|0x80)
+#define MAMXFLL (0x0A|0x40|0x80)
+#define MAMXFLH (0x0B|0x40|0x80)
+#define MAPHSUP (0x0D|0x40|0x80)
+#define MICON (0x11|0x40|0x80)
+#define MICMD (0x12|0x40|0x80)
+#define MIREGADR (0x14|0x40|0x80)
+#define MIWRL (0x16|0x40|0x80)
+#define MIWRH (0x17|0x40|0x80)
+#define MIRDL (0x18|0x40|0x80)
+#define MIRDH (0x19|0x40|0x80)
+// Bank 3 registers
+#define MAADR1 (0x00|0x60|0x80)
+#define MAADR0 (0x01|0x60|0x80)
+#define MAADR3 (0x02|0x60|0x80)
+#define MAADR2 (0x03|0x60|0x80)
+#define MAADR5 (0x04|0x60|0x80)
+#define MAADR4 (0x05|0x60|0x80)
+#define EBSTSD (0x06|0x60)
+#define EBSTCON (0x07|0x60)
+#define EBSTCSL (0x08|0x60)
+#define EBSTCSH (0x09|0x60)
+#define MISTAT (0x0A|0x60|0x80)
+#define EREVID (0x12|0x60)
+#define ECOCON (0x15|0x60)
+#define EFLOCON (0x17|0x60)
+#define EPAUSL (0x18|0x60)
+#define EPAUSH (0x19|0x60)
+// PHY registers
+#define PHCON1 0x00
+#define PHSTAT1 0x01
+#define PHHID1 0x02
+#define PHHID2 0x03
+#define PHCON2 0x10
+#define PHSTAT2 0x11
+#define PHIE 0x12
+#define PHIR 0x13
+#define PHLCON 0x14
+
+// ENC28J60 ERXFCON Register Bit Definitions
+#define ERXFCON_UCEN 0x80
+#define ERXFCON_ANDOR 0x40
+#define ERXFCON_CRCEN 0x20
+#define ERXFCON_PMEN 0x10
+#define ERXFCON_MPEN 0x08
+#define ERXFCON_HTEN 0x04
+#define ERXFCON_MCEN 0x02
+#define ERXFCON_BCEN 0x01
+// ENC28J60 EIE Register Bit Definitions
+#define EIE_INTIE 0x80
+#define EIE_PKTIE 0x40
+#define EIE_DMAIE 0x20
+#define EIE_LINKIE 0x10
+#define EIE_TXIE 0x08
+#define EIE_WOLIE 0x04
+#define EIE_TXERIE 0x02
+#define EIE_RXERIE 0x01
+// ENC28J60 EIR Register Bit Definitions
+#define EIR_PKTIF 0x40
+#define EIR_DMAIF 0x20
+#define EIR_LINKIF 0x10
+#define EIR_TXIF 0x08
+#define EIR_WOLIF 0x04
+#define EIR_TXERIF 0x02
+#define EIR_RXERIF 0x01
+// ENC28J60 ESTAT Register Bit Definitions
+#define ESTAT_INT 0x80
+#define ESTAT_LATECOL 0x10
+#define ESTAT_RXBUSY 0x04
+#define ESTAT_TXABRT 0x02
+#define ESTAT_CLKRDY 0x01
+// ENC28J60 ECON2 Register Bit Definitions
+#define ECON2_AUTOINC 0x80
+#define ECON2_PKTDEC 0x40
+#define ECON2_PWRSV 0x20
+#define ECON2_VRPS 0x08
+// ENC28J60 ECON1 Register Bit Definitions
+#define ECON1_TXRST 0x80
+#define ECON1_RXRST 0x40
+#define ECON1_DMAST 0x20
+#define ECON1_CSUMEN 0x10
+#define ECON1_TXRTS 0x08
+#define ECON1_RXEN 0x04
+#define ECON1_BSEL1 0x02
+#define ECON1_BSEL0 0x01
+// ENC28J60 MACON1 Register Bit Definitions
+#define MACON1_LOOPBK 0x10
+#define MACON1_TXPAUS 0x08
+#define MACON1_RXPAUS 0x04
+#define MACON1_PASSALL 0x02
+#define MACON1_MARXEN 0x01
+// ENC28J60 MACON2 Register Bit Definitions
+#define MACON2_MARST 0x80
+#define MACON2_RNDRST 0x40
+#define MACON2_MARXRST 0x08
+#define MACON2_RFUNRST 0x04
+#define MACON2_MATXRST 0x02
+#define MACON2_TFUNRST 0x01
+// ENC28J60 MACON3 Register Bit Definitions
+#define MACON3_PADCFG2 0x80
+#define MACON3_PADCFG1 0x40
+#define MACON3_PADCFG0 0x20
+#define MACON3_TXCRCEN 0x10
+#define MACON3_PHDRLEN 0x08
+#define MACON3_HFRMLEN 0x04
+#define MACON3_FRMLNEN 0x02
+#define MACON3_FULDPX 0x01
+// ENC28J60 MACON4 Register Bit Definitions
+#define MACON4_DEFER (1<<6)
+#define MACON4_BPEN (1<<5)
+#define MACON4_NOBKOFF (1<<4)
+// ENC28J60 MICMD Register Bit Definitions
+#define MICMD_MIISCAN 0x02
+#define MICMD_MIIRD 0x01
+// ENC28J60 MISTAT Register Bit Definitions
+#define MISTAT_NVALID 0x04
+#define MISTAT_SCAN 0x02
+#define MISTAT_BUSY 0x01
+// ENC28J60 PHY PHCON1 Register Bit Definitions
+#define PHCON1_PRST 0x8000
+#define PHCON1_PLOOPBK 0x4000
+#define PHCON1_PPWRSV 0x0800
+#define PHCON1_PDPXMD 0x0100
+// ENC28J60 PHY PHSTAT1 Register Bit Definitions
+#define PHSTAT1_PFDPX 0x1000
+#define PHSTAT1_PHDPX 0x0800
+#define PHSTAT1_LLSTAT 0x0004
+#define PHSTAT1_JBSTAT 0x0002
+/* ENC28J60 PHY PHSTAT2 Register Bit Definitions */
+#define PHSTAT2_TXSTAT (1 << 13)
+#define PHSTAT2_RXSTAT (1 << 12)
+#define PHSTAT2_COLSTAT (1 << 11)
+#define PHSTAT2_LSTAT (1 << 10)
+#define PHSTAT2_DPXSTAT (1 << 9)
+#define PHSTAT2_PLRITY (1 << 5)
+// ENC28J60 PHY PHCON2 Register Bit Definitions
+#define PHCON2_FRCLINK 0x4000
+#define PHCON2_TXDIS 0x2000
+#define PHCON2_JABBER 0x0400
+#define PHCON2_HDLDIS 0x0100
+
+// ENC28J60 Packet Control Byte Bit Definitions
+#define PKTCTRL_PHUGEEN 0x08
+#define PKTCTRL_PPADEN 0x04
+#define PKTCTRL_PCRCEN 0x02
+#define PKTCTRL_POVERRIDE 0x01
+
+/* ENC28J60 Transmit Status Vector */
+#define TSV_TXBYTECNT 0
+#define TSV_TXCOLLISIONCNT 16
+#define TSV_TXCRCERROR 20
+#define TSV_TXLENCHKERROR 21
+#define TSV_TXLENOUTOFRANGE 22
+#define TSV_TXDONE 23
+#define TSV_TXMULTICAST 24
+#define TSV_TXBROADCAST 25
+#define TSV_TXPACKETDEFER 26
+#define TSV_TXEXDEFER 27
+#define TSV_TXEXCOLLISION 28
+#define TSV_TXLATECOLLISION 29
+#define TSV_TXGIANT 30
+#define TSV_TXUNDERRUN 31
+#define TSV_TOTBYTETXONWIRE 32
+#define TSV_TXCONTROLFRAME 48
+#define TSV_TXPAUSEFRAME 49
+#define TSV_BACKPRESSUREAPP 50
+#define TSV_TXVLANTAGFRAME 51
+
+#define TSV_SIZE 7
+#define TSV_BYTEOF(x) ((x) / 8)
+#define TSV_BITMASK(x) (1 << ((x) % 8))
+#define TSV_GETBIT(x, y) (((x)[TSV_BYTEOF(y)] & TSV_BITMASK(y)) ? 1 : 0)
+
+/* ENC28J60 Receive Status Vector */
+#define RSV_RXLONGEVDROPEV 16
+#define RSV_CARRIEREV 18
+#define RSV_CRCERROR 20
+#define RSV_LENCHECKERR 21
+#define RSV_LENOUTOFRANGE 22
+#define RSV_RXOK 23
+#define RSV_RXMULTICAST 24
+#define RSV_RXBROADCAST 25
+#define RSV_DRIBBLENIBBLE 26
+#define RSV_RXCONTROLFRAME 27
+#define RSV_RXPAUSEFRAME 28
+#define RSV_RXUNKNOWNOPCODE 29
+#define RSV_RXTYPEVLAN 30
+
+#define RSV_SIZE 6
+#define RSV_BITMASK(x) (1 << ((x) - 16))
+#define RSV_GETBIT(x, y) (((x) & RSV_BITMASK(y)) ? 1 : 0)
+
+// SPI operation codes
+#define ENC28J60_READ_CTRL_REG 0x00
+#define ENC28J60_READ_BUF_MEM 0x3A
+#define ENC28J60_WRITE_CTRL_REG 0x40
+#define ENC28J60_WRITE_BUF_MEM 0x7A
+#define ENC28J60_BIT_FIELD_SET 0x80
+#define ENC28J60_BIT_FIELD_CLR 0xA0
+#define ENC28J60_SOFT_RESET 0xFF
+
+// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
+// buffer boundaries applied to internal 8K ram
+// the entire available packet buffer space is allocated
+//
+
+#define MAX_TX_PACKAGE_SIZE (1536)
+
+// start with recbuf at 0/
+#define RXSTART_INIT 0x0
+// receive buffer end
+#define RXSTOP_INIT (0x1FFF - MAX_TX_PACKAGE_SIZE*2) - 1
+// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
+
+#define TXSTART_INIT (0x1FFF - MAX_TX_PACKAGE_SIZE*2)
+// stp TX buffer at end of mem
+#define TXSTOP_INIT 0x1FFF
+
+// max frame length which the conroller will accept:
+#define MAX_FRAMELEN 1518
+
+#define MAX_ADDR_LEN 6
+
+struct net_device
+{
+ /* inherit from ethernet device */
+ struct eth_device parent;
+
+ /* interface address info. */
+ rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
+
+ rt_uint8_t emac_rev;
+ rt_uint8_t phy_rev;
+ rt_uint8_t phy_pn;
+ rt_uint32_t phy_id;
+
+ /* spi device */
+ struct rt_spi_device * spi_device;
+ struct rt_mutex lock;
+};
+
+/* export function */
+extern rt_err_t enc28j60_attach(const char * spi_device_name);
+extern void enc28j60_isr(void);
+
+#endif // EN28J60_H_INCLUDED
diff --git a/components/drivers/spi/spi_dev.c b/components/drivers/spi/spi_dev.c
index b1f6e41a86..375a5e0fa1 100644
--- a/components/drivers/spi/spi_dev.c
+++ b/components/drivers/spi/spi_dev.c
@@ -25,16 +25,6 @@
#include <drivers/spi.h>
/* SPI bus device interface, compatible with RT-Thread 0.3.x/1.0.x */
-static rt_err_t _spi_bus_device_init(rt_device_t dev)
-{
- struct rt_spi_bus *bus;
-
- bus = (struct rt_spi_bus *)dev;
- RT_ASSERT(bus != RT_NULL);
-
- return RT_EOK;
-}
-
static rt_size_t _spi_bus_device_read(rt_device_t dev,
rt_off_t pos,
void *buffer,
@@ -67,11 +57,7 @@ static rt_err_t _spi_bus_device_control(rt_device_t dev,
rt_uint8_t cmd,
void *args)
{
- struct rt_spi_bus *bus;
-
- bus = (struct rt_spi_bus *)dev;
- RT_ASSERT(bus != RT_NULL);
-
+ /* TODO: add control command handle */
switch (cmd)
{
case 0: /* set device */
@@ -93,7 +79,7 @@ rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name)
/* set device type */
device->type = RT_Device_Class_SPIBUS;
/* initialize device interface */
- device->init = _spi_bus_device_init;
+ device->init = RT_NULL;
device->open = RT_NULL;
device->close = RT_NULL;
device->read = _spi_bus_device_read;
@@ -105,16 +91,6 @@ rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name)
}
/* SPI Dev device interface, compatible with RT-Thread 0.3.x/1.0.x */
-static rt_err_t _spidev_device_init(rt_device_t dev)
-{
- struct rt_spi_device *device;
-
- device = (struct rt_spi_device *)dev;
- RT_ASSERT(device != RT_NULL);
-
- return RT_EOK;
-}
-
static rt_size_t _spidev_device_read(rt_device_t dev,
rt_off_t pos,
void *buffer,
@@ -147,11 +123,6 @@ static rt_err_t _spidev_device_control(rt_device_t dev,
rt_uint8_t cmd,
void *args)
{
- struct rt_spi_device *device;
-
- device = (struct rt_spi_device *)dev;
- RT_ASSERT(device != RT_NULL);
-
switch (cmd)
{
case 0: /* set device */
@@ -172,7 +143,7 @@ rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name)
/* set device type */
device->type = RT_Device_Class_SPIDevice;
- device->init = _spidev_device_init;
+ device->init = RT_NULL;
device->open = RT_NULL;
device->close = RT_NULL;
device->read = _spidev_device_read;
diff --git a/components/drivers/spi/spi_flash_at45dbxx.c b/components/drivers/spi/spi_flash_at45dbxx.c
new file mode 100644
index 0000000000..be474f7c65
--- /dev/null
+++ b/components/drivers/spi/spi_flash_at45dbxx.c
@@ -0,0 +1,437 @@
+/*
+ * File : rtdef.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-16 aozima the first version
+ */
+
+#include <stdint.h>
+#include "spi_flash_at45dbxx.h"
+
+#define FLASH_DEBUG
+#define DMA_BUFFER_SIZE 512
+
+#ifdef FLASH_DEBUG
+#define FLASH_TRACE rt_kprintf
+#else
+#define FLASH_TRACE(...)
+#endif /**< #ifdef FLASH_DEBUG */
+
+/* JEDEC Manufacturer��s ID */
+#define MF_ID (0x1F) /* atmel */
+#define DENSITY_CODE_011D (0x02) /* AT45DB011D Density Code : 00010 = 1-Mbit */
+#define DENSITY_CODE_021D (0x03) /* AT45DB021D Density Code : 00011 = 2-Mbit */
+#define DENSITY_CODE_041D (0x04) /* AT45DB041D Density Code : 00100 = 4-Mbit */
+#define DENSITY_CODE_081D (0x05) /* AT45DB081D Density Code : 00101 = 8-Mbit */
+#define DENSITY_CODE_161D (0x06) /* AT45DB161D Density Code : 00110 = 16-Mbit */
+#define DENSITY_CODE_321D (0x07) /* AT45DB321D Density Code : 00111 = 32-Mbit */
+#define DENSITY_CODE_642D (0x08) /* AT45DB642D Density Code : 01000 = 64-Mbit */
+
+struct JEDEC_ID
+{
+ uint8_t manufacturer_id; /* Manufacturer ID */
+ uint8_t density_code:5; /* Density Code */
+ uint8_t family_code:3; /* Family Code */
+ uint8_t version_code:5; /* Product Version Code */
+ uint8_t mlc_code:3; /* MLC Code */
+ uint8_t byte_count; /* Byte Count */
+};
+
+#define AT45DB_BUFFER_1_WRITE 0x84
+#define AT45DB_BUFFER_2_WRITE 0x87
+#define AT45DB_BUFFER_1_READ 0xD4
+#define AT45DB_BUFFER_2_READ 0xD6
+#define AT45DB_B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83
+#define AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86
+#define AT45DB_MM_PAGE_TO_B1_XFER 0x53
+#define AT45DB_MM_PAGE_TO_B2_XFER 0x55
+#define AT45DB_PAGE_ERASE 0x81
+#define AT45DB_SECTOR_ERASE 0x7C
+#define AT45DB_READ_STATE_REGISTER 0xD7
+#define AT45DB_MM_PAGE_READ 0xD2
+#define AT45DB_MM_PAGE_PROG_THRU_BUFFER1 0x82
+#define AT45DB_CMD_JEDEC_ID 0x9F
+
+static struct spi_flash_at45dbxx spi_flash_at45dbxx;
+
+/*****************************************************************************/
+/*Status Register Format: */
+/* ------------------------------------------------------------------------- */
+/* | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | */
+/* |--------|--------|--------|--------|--------|--------|--------|--------| */
+/* |RDY/BUSY| COMP | device density | X | X | */
+/* ------------------------------------------------------------------------- */
+/* 0:busy | | AT45DB041:0111 | protect|page size */
+/* 1:ready | | AT45DB161:1011 | */
+/* --------------------------------------------------------------------------*/
+/*****************************************************************************/
+static uint8_t AT45DB_StatusRegisterRead(void)
+{
+ return rt_spi_sendrecv8(spi_flash_at45dbxx.rt_spi_device, AT45DB_READ_STATE_REGISTER);
+}
+
+static void wait_busy(void)
+{
+ uint16_t i = 0;
+ while (i++ < 10000)
+ {
+ if (AT45DB_StatusRegisterRead() & 0x80)
+ {
+ return;
+ }
+ }
+ FLASH_TRACE("\r\nSPI_FLASH timeout!!!\r\n");
+}
+
+/* RT-Thread Device Driver Interface */
+static rt_err_t AT45DB_flash_init(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t AT45DB_flash_open(rt_device_t dev, rt_uint16_t oflag)
+{
+
+ return RT_EOK;
+}
+
+static rt_err_t AT45DB_flash_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t AT45DB_flash_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+ RT_ASSERT(dev != RT_NULL);
+
+ if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
+ {
+ struct rt_device_blk_geometry *geometry;
+
+ geometry = (struct rt_device_blk_geometry *)args;
+ if (geometry == RT_NULL) return -RT_ERROR;
+
+ geometry->bytes_per_sector = 512;
+ geometry->sector_count = 4096;
+ geometry->block_size = 4096; /* block erase: 4k */
+ }
+
+ return RT_EOK;
+}
+
+static rt_size_t AT45DB_flash_read_page_256(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ uint32_t index, nr;
+ uint8_t * read_buffer = buffer;
+
+ nr = size;
+
+ for (index = 0; index < nr; index++)
+ {
+ uint32_t page = pos;
+ uint8_t send_buffer[8];
+ uint32_t i;
+
+ for(i=0; i<sizeof(send_buffer); i++)
+ {
+ send_buffer[i] = 0;
+ }
+
+ send_buffer[0] = AT45DB_MM_PAGE_READ;
+ send_buffer[1] = (uint8_t)(page >> 7);
+ send_buffer[2] = (uint8_t)(page << 1);
+
+ rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 256);
+ read_buffer += 256;
+ page++;
+ }
+
+ return size;
+}
+
+static rt_size_t AT45DB_flash_read_page_512(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ uint32_t index, nr;
+ uint8_t * read_buffer = buffer;
+
+ nr = size;
+
+ for (index = 0; index < nr; index++)
+ {
+ uint32_t page = pos;
+ uint8_t send_buffer[8];
+ uint32_t i;
+
+ for(i=0; i<sizeof(send_buffer); i++)
+ {
+ send_buffer[i] = 0;
+ }
+
+ send_buffer[0] = AT45DB_MM_PAGE_READ;
+ send_buffer[1] = (uint8_t)(page >> 6);
+ send_buffer[2] = (uint8_t)(page << 2);
+
+ rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 512);
+ read_buffer += 512;
+ page++;
+ }
+
+ return size;
+}
+
+static rt_size_t AT45DB_flash_read_page_1024(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ uint32_t index, nr;
+ uint8_t * read_buffer = buffer;
+
+ nr = size;
+
+ for (index = 0; index < nr; index++)
+ {
+ uint32_t page = pos;
+ uint8_t send_buffer[8];
+ uint32_t i;
+
+ for(i=0; i<sizeof(send_buffer); i++)
+ {
+ send_buffer[i] = 0;
+ }
+
+ send_buffer[0] = AT45DB_MM_PAGE_READ;
+ send_buffer[1] = (uint8_t)(page >> 5);
+ send_buffer[2] = (uint8_t)(page << 3);
+
+ rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 1024);
+ read_buffer += 1024;
+ page++;
+ }
+
+ return size;
+}
+
+static rt_size_t AT45DB_flash_write_page_256(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ rt_uint32_t index, nr;
+ const uint8_t * write_buffer = buffer;
+
+ 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;
+ send_buffer[1] = (uint8_t) (page >> 7);
+ send_buffer[2] = (uint8_t) (page << 1);
+ send_buffer[3] = 0;
+
+ rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 256);
+
+ write_buffer += 256;
+ page++;
+
+ wait_busy();
+ }
+
+ return size;
+}
+
+static rt_size_t AT45DB_flash_write_page_512(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ rt_uint32_t index, nr;
+ const uint8_t * write_buffer = buffer;
+
+ 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;
+ send_buffer[1] = (uint8_t) (page >> 6);
+ send_buffer[2] = (uint8_t) (page << 2);
+ send_buffer[3] = 0;
+
+ rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 512);
+
+ write_buffer += 512;
+ page++;
+
+ wait_busy();
+ }
+
+ return size;
+}
+
+static rt_size_t AT45DB_flash_write_page_1024(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ rt_uint32_t index, nr;
+ const uint8_t * write_buffer = buffer;
+
+ 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;
+ send_buffer[1] = (uint8_t) (page >> 5);
+ send_buffer[2] = (uint8_t) (page << 3);
+ send_buffer[3] = 0;
+
+ rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 1024);
+
+ write_buffer += 1024;
+ page++;
+
+ wait_busy();
+ }
+
+ return size;
+}
+
+rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name)
+{
+ struct rt_spi_device * rt_spi_device;
+ struct JEDEC_ID * JEDEC_ID;
+
+ rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
+ if(rt_spi_device == RT_NULL)
+ {
+ FLASH_TRACE("spi device %s not found!\r\n", spi_device_name);
+ return -RT_ENOSYS;
+ }
+ spi_flash_at45dbxx.rt_spi_device = rt_spi_device;
+
+ /* config spi */
+ {
+ struct rt_spi_configuration cfg;
+ cfg.data_width = 8;
+ cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 and 3 */
+ cfg.max_hz = 66000000; /* Atmel RapidS Serial Interface: 66MHz Maximum Clock Frequency */
+ rt_spi_configure(spi_flash_at45dbxx.rt_spi_device, &cfg);
+ }
+
+ /* read JEDEC ID */
+ {
+ uint8_t cmd;
+ uint8_t id_recv[6];
+ JEDEC_ID = (struct JEDEC_ID *)id_recv;
+
+ cmd = AT45DB_CMD_JEDEC_ID;
+ rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, &cmd, 1, id_recv, 6);
+
+ /**< 1FH = Atmel */
+ /**< 001 = Atmel DataFlash */
+ if(JEDEC_ID->manufacturer_id != 0x1F || JEDEC_ID->family_code != 0x01)
+ {
+ FLASH_TRACE("Manufacturer��s ID or Memory Type error!\r\n");
+ FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]);
+ return -RT_ENOSYS;
+ }
+
+ if(JEDEC_ID->density_code == DENSITY_CODE_011D)
+ {
+ /**< AT45DB011D Density Code : 00010 = 1-Mbit */
+ FLASH_TRACE("AT45DB011D detection\r\n");
+ spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */
+ spi_flash_at45dbxx.geometry.sector_count = 512; /* 1-Mbit / 8 / 256 = 512 */
+ spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */
+ }
+ else if(JEDEC_ID->density_code == DENSITY_CODE_021D)
+ {
+ /**< AT45DB021D Density Code : 00011 = 2-Mbit */
+ FLASH_TRACE("AT45DB021D detection\r\n");
+ spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */
+ spi_flash_at45dbxx.geometry.sector_count = 512*2; /* 2-Mbit / 8 / 256 = 1024 */
+ spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */
+ }
+ else if(JEDEC_ID->density_code == DENSITY_CODE_041D)
+ {
+ /**< AT45DB041D Density Code : 00100 = 4-Mbit */
+ FLASH_TRACE("AT45DB041D detection\r\n");
+ spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */
+ spi_flash_at45dbxx.geometry.sector_count = 512*4; /* 4-Mbit / 8 / 256 = 2048 */
+ spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */
+ }
+ else if(JEDEC_ID->density_code == DENSITY_CODE_081D)
+ {
+ /**< AT45DB081D Density Code : 00101 = 8-Mbit */
+ FLASH_TRACE("AT45DB081D detection\r\n");
+ spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */
+ spi_flash_at45dbxx.geometry.sector_count = 512*8; /* 8-Mbit / 8 / 256 = 4096 */
+ spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */
+ }
+ else if(JEDEC_ID->density_code == DENSITY_CODE_161D)
+ {
+ /**< AT45DB161D Density Code : 00110 = 16-Mbit */
+ FLASH_TRACE("AT45DB161D detection\r\n");
+ spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */
+ spi_flash_at45dbxx.geometry.sector_count = 256*16; /* 16-Mbit / 8 / 512 = 4096 */
+ spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */
+ }
+ else if(JEDEC_ID->density_code == DENSITY_CODE_321D)
+ {
+ /**< AT45DB321D Density Code : 00111 = 32-Mbit */
+ FLASH_TRACE("AT45DB321D detection\r\n");
+ spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */
+ spi_flash_at45dbxx.geometry.sector_count = 256*32; /* 32-Mbit / 8 / 512 = 8192 */
+ spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */
+ }
+ else if(JEDEC_ID->density_code == DENSITY_CODE_642D)
+ {
+ /**< AT45DB642D Density Code : 01000 = 64-Mbit */
+ FLASH_TRACE("AT45DB642D detection\r\n");
+ spi_flash_at45dbxx.geometry.bytes_per_sector = 1024; /* Page Erase (1 Kbyte) */
+ spi_flash_at45dbxx.geometry.sector_count = 128*64; /* 64-Mbit / 8 / 1024 = 8192 */
+ spi_flash_at45dbxx.geometry.block_size = 1024*8; /* Block Erase (8 Kbytes) */
+ }
+ else
+ {
+ FLASH_TRACE("Memory Capacity error!\r\n");
+ return -RT_ENOSYS;
+ }
+ }
+
+ /* register device */
+ spi_flash_at45dbxx.flash_device.type = RT_Device_Class_Block;
+ spi_flash_at45dbxx.flash_device.init = AT45DB_flash_init;
+ spi_flash_at45dbxx.flash_device.open = AT45DB_flash_open;
+ spi_flash_at45dbxx.flash_device.close = AT45DB_flash_close;
+ spi_flash_at45dbxx.flash_device.control = AT45DB_flash_control;
+
+ if(JEDEC_ID->density_code == DENSITY_CODE_642D)
+ {
+ spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_1024;
+ spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_1024;
+ }
+ else if(JEDEC_ID->density_code == DENSITY_CODE_161D
+ || JEDEC_ID->density_code == DENSITY_CODE_321D )
+ {
+ spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_512;
+ spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_512;
+ }
+ else
+ {
+ spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_256;
+ spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_256;
+ }
+
+ /* no private */
+ spi_flash_at45dbxx.flash_device.user_data = RT_NULL;
+
+ rt_device_register(&spi_flash_at45dbxx.flash_device, flash_device_name,
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
+
+ return RT_EOK;
+}
diff --git a/components/drivers/spi/spi_flash_at45dbxx.h b/components/drivers/spi/spi_flash_at45dbxx.h
new file mode 100644
index 0000000000..9b72cf0a0f
--- /dev/null
+++ b/components/drivers/spi/spi_flash_at45dbxx.h
@@ -0,0 +1,17 @@
+#ifndef SPI_FLASH_AT45DBXX_H_INCLUDED
+#define SPI_FLASH_AT45DBXX_H_INCLUDED
+
+#include <rtthread.h>
+#include <drivers/spi.h>
+
+struct spi_flash_at45dbxx
+{
+ struct rt_device flash_device;
+ struct rt_device_blk_geometry geometry;
+ struct rt_spi_device * rt_spi_device;
+};
+
+extern rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name);
+
+
+#endif // SPI_FLASH_AT45DBXX_H_INCLUDED
diff --git a/components/drivers/spi/spi_flash_sst25vfxx.c b/components/drivers/spi/spi_flash_sst25vfxx.c
new file mode 100644
index 0000000000..f0e28b5584
--- /dev/null
+++ b/components/drivers/spi/spi_flash_sst25vfxx.c
@@ -0,0 +1,346 @@
+/*
+ * File : rtdef.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-16 aozima the first version
+ */
+
+#include <stdint.h>
+#include "spi_flash_sst25vfxx.h"
+
+#define FLASH_DEBUG
+
+#ifdef FLASH_DEBUG
+#define FLASH_TRACE rt_kprintf
+#else
+#define FLASH_TRACE(...)
+#endif /* #ifdef FLASH_DEBUG */
+
+/* JEDEC Manufacturer��s ID */
+#define MF_ID (0xBF)
+/* JEDEC Device ID : Memory Type */
+#define MT_ID (0x25)
+/* JEDEC Device ID: Memory Capacity */
+#define MC_ID_SST25VF020B (0x8C) /* 2Mbit */
+#define MC_ID_SST25VF040B (0x8D) /* 4Mbit */
+#define MC_ID_SST25VF080B (0x8E) /* 8Mbit */
+#define MC_ID_SST25VF016B (0x41) /* 16Mbit */
+#define MC_ID_SST25VF032B (0x4A) /* 32Mbit */
+#define MC_ID_SST25VF064C (0x4B) /* 64Mbit */
+
+/* command list */
+#define CMD_RDSR (0x05)
+#define CMD_WRSR (0x01)
+#define CMD_EWSR (0x50)
+#define CMD_WRDI (0x04)
+#define CMD_WREN (0x06)
+#define CMD_READ (0x03)
+#define CMD_FAST_READ (0x0B)
+#define CMD_BP (0x02)
+#define CMD_AAIP (0xAD)
+#define CMD_ERASE_4K (0x20)
+#define CMD_ERASE_32K (0x52)
+#define CMD_ERASE_64K (0xD8)
+#define CMD_ERASE_full (0xC7)
+#define CMD_JEDEC_ID (0x9F)
+#define CMD_EBSY (0x70)
+#define CMD_DBSY (0x80)
+
+#define DUMMY (0xFF)
+
+static struct spi_flash_sst25vfxx spi_flash_sst25vfxx;
+
+static uint8_t sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash)
+{
+ return rt_spi_sendrecv8(spi_flash->rt_spi_device, CMD_RDSR);
+}
+
+static void sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash)
+{
+ while( sst25vfxx_read_status(spi_flash) & (0x01));
+}
+
+/** \brief write N page on [page]
+ *
+ * \param page uint32_t unit : byte (4096 * N,1 page = 4096byte)
+ * \param buffer const uint8_t*
+ * \param size uint32_t unit : byte ( 4096*N )
+ * \return uint32_t
+ *
+ */
+static uint32_t sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash, uint32_t page, const uint8_t * buffer, uint32_t size)
+{
+ uint32_t index;
+ uint32_t need_wirte = size;
+ uint8_t send_buffer[6];
+
+ page &= ~0xFFF; // page size = 4096byte
+
+ send_buffer[0] = CMD_WREN;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_ERASE_4K;
+ send_buffer[1] = (page >> 16);
+ send_buffer[2] = (page >> 8);
+ send_buffer[3] = (page);
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 4);
+
+ sst25vfxx_wait_busy(spi_flash); // wait erase done.
+
+ send_buffer[0] = CMD_WREN;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_AAIP;
+ send_buffer[1] = (uint8_t)(page >> 16);
+ send_buffer[2] = (uint8_t)(page >> 8);
+ send_buffer[3] = (uint8_t)(page);
+ send_buffer[4] = *buffer++;
+ send_buffer[5] = *buffer++;
+ need_wirte -= 2;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 6);
+
+ sst25vfxx_wait_busy(spi_flash);
+
+ for(index=0; index < need_wirte/2; index++)
+ {
+ send_buffer[0] = CMD_AAIP;
+ send_buffer[1] = *buffer++;
+ send_buffer[2] = *buffer++;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 3);
+ sst25vfxx_wait_busy(spi_flash);
+ }
+
+ send_buffer[0] = CMD_WRDI;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
+
+ return size;
+}
+
+/* RT-Thread device interface */
+static rt_err_t sst25vfxx_flash_init(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t sst25vfxx_flash_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ rt_err_t result;
+ uint8_t send_buffer[2];
+ struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
+
+ /* lock spi flash */
+ result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
+ if(result != RT_EOK)
+ {
+ return result;
+ }
+
+ send_buffer[0] = CMD_DBSY;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_EWSR;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_WRSR;
+ send_buffer[1] = 0;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 2);
+
+ /* release lock */
+ rt_mutex_release(&(spi_flash->lock));
+
+ return RT_EOK;
+}
+
+static rt_err_t sst25vfxx_flash_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t sst25vfxx_flash_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+ struct spi_flash_sst25vfxx * spi_flash;
+
+ spi_flash = (struct spi_flash_sst25vfxx *)dev;
+
+ RT_ASSERT(dev != RT_NULL);
+
+ if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
+ {
+ struct rt_device_blk_geometry *geometry;
+
+ geometry = (struct rt_device_blk_geometry *)args;
+ if (geometry == RT_NULL) return -RT_ERROR;
+
+ geometry->bytes_per_sector = spi_flash->geometry.bytes_per_sector;
+ geometry->sector_count = spi_flash->geometry.sector_count;
+ geometry->block_size = spi_flash->geometry.block_size;
+ }
+
+ return RT_EOK;
+}
+
+static rt_size_t sst25vfxx_flash_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ rt_err_t result;
+ uint8_t send_buffer[4];
+ struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
+ uint32_t offset = pos * spi_flash->geometry.bytes_per_sector;
+
+ /* lock spi flash */
+ result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
+ if(result != RT_EOK)
+ {
+ return 0;
+ }
+
+ send_buffer[0] = CMD_WRDI;
+ rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_READ;
+ send_buffer[1] = (uint8_t)(offset>>16);
+ send_buffer[2] = (uint8_t)(offset>>8);
+ send_buffer[3] = (uint8_t)(offset);
+ rt_spi_send_then_recv(spi_flash->rt_spi_device, send_buffer, 4, buffer, size * spi_flash->geometry.bytes_per_sector);
+
+ /* release lock */
+ rt_mutex_release(&(spi_flash->lock));
+
+ return size;
+}
+
+static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ uint32_t i;
+ rt_err_t result;
+ const uint8_t * write_buffer = buffer;
+ struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
+
+ /* lock spi flash */
+ result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
+ if(result != RT_EOK)
+ {
+ return 0;
+ }
+
+ for(i=0; i<size; i++)
+ {
+ sst25vfxx_page_write(spi_flash,
+ (pos + i) * spi_flash->geometry.bytes_per_sector,
+ write_buffer,
+ spi_flash->geometry.bytes_per_sector);
+ write_buffer += spi_flash->geometry.bytes_per_sector;
+ }
+
+ /* release lock */
+ rt_mutex_release(&(spi_flash->lock));
+
+ return size;
+}
+
+rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name)
+{
+ struct rt_spi_device * rt_spi_device;
+ struct spi_flash_sst25vfxx * spi_flash = &spi_flash_sst25vfxx;
+
+ rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
+ if(rt_spi_device == RT_NULL)
+ {
+ FLASH_TRACE("spi device %s not found!\r\n", spi_device_name);
+ return -RT_ENOSYS;
+ }
+ spi_flash->rt_spi_device = rt_spi_device;
+
+ /* config spi */
+ {
+ struct rt_spi_configuration cfg;
+ cfg.data_width = 8;
+ cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
+ cfg.max_hz = 50000000; /* 50M */
+ rt_spi_configure(spi_flash->rt_spi_device, &cfg);
+ }
+
+ /* init flash */
+ {
+ rt_uint8_t cmd;
+ rt_uint8_t id_recv[3];
+
+ cmd = CMD_WRDI;
+ rt_spi_send(spi_flash->rt_spi_device, &cmd, 1);
+
+ /* read flash id */
+ cmd = CMD_JEDEC_ID;
+ rt_spi_send_then_recv(spi_flash->rt_spi_device, &cmd, 1, id_recv, 3);
+
+ if(id_recv[0] != MF_ID || id_recv[1] != MT_ID)
+ {
+ FLASH_TRACE("Manufacturer��s ID or Memory Type error!\r\n");
+ FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]);
+ return -RT_ENOSYS;
+ }
+
+ spi_flash->geometry.bytes_per_sector = 4096;
+ spi_flash->geometry.block_size = 4096; /* block erase: 4k */
+
+ if(id_recv[2] == MC_ID_SST25VF020B)
+ {
+ FLASH_TRACE("SST25VF020B detection\r\n");
+ spi_flash->geometry.sector_count = 64;
+ }
+ else if(id_recv[2] == MC_ID_SST25VF040B)
+ {
+ FLASH_TRACE("SST25VF040B detection\r\n");
+ spi_flash->geometry.sector_count = 128;
+ }
+ else if(id_recv[2] == MC_ID_SST25VF080B)
+ {
+ FLASH_TRACE("SST25VF080B detection\r\n");
+ spi_flash->geometry.sector_count = 256;
+ }
+ else if(id_recv[2] == MC_ID_SST25VF016B)
+ {
+ FLASH_TRACE("SST25VF016B detection\r\n");
+ spi_flash->geometry.sector_count = 512;
+ }
+ else if(id_recv[2] == MC_ID_SST25VF032B)
+ {
+ FLASH_TRACE("SST25VF032B detection\r\n");
+ spi_flash->geometry.sector_count = 1024;
+ }
+ else if(id_recv[2] == MC_ID_SST25VF064C)
+ {
+ FLASH_TRACE("SST25VF064C detection\r\n");
+ spi_flash->geometry.sector_count = 2048;
+ }
+ else
+ {
+ FLASH_TRACE("Memory Capacity error!\r\n");
+ return -RT_ENOSYS;
+ }
+ }
+
+ /* initialize mutex lock */
+ rt_mutex_init(&spi_flash->lock, flash_device_name, RT_IPC_FLAG_PRIO);
+
+ /* register device */
+ spi_flash->flash_device.type = RT_Device_Class_Block;
+ spi_flash->flash_device.init = sst25vfxx_flash_init;
+ spi_flash->flash_device.open = sst25vfxx_flash_open;
+ spi_flash->flash_device.close = sst25vfxx_flash_close;
+ spi_flash->flash_device.read = sst25vfxx_flash_read;
+ spi_flash->flash_device.write = sst25vfxx_flash_write;
+ spi_flash->flash_device.control = sst25vfxx_flash_control;
+ /* no private */
+ spi_flash->flash_device.user_data = RT_NULL;
+
+ rt_device_register(&spi_flash->flash_device, flash_device_name,
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
+
+ return RT_EOK;
+}
diff --git a/components/drivers/spi/spi_flash_sst25vfxx.h b/components/drivers/spi/spi_flash_sst25vfxx.h
new file mode 100644
index 0000000000..b4575c2b68
--- /dev/null
+++ b/components/drivers/spi/spi_flash_sst25vfxx.h
@@ -0,0 +1,32 @@
+/*
+ * File : rtdef.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-16 aozima the first version
+ */
+
+#ifndef SPI_FLASH_SST25VFXX_H_INCLUDED
+#define SPI_FLASH_SST25VFXX_H_INCLUDED
+
+#include <rtthread.h>
+#include <drivers/spi.h>
+
+struct spi_flash_sst25vfxx
+{
+ struct rt_device flash_device;
+ struct rt_device_blk_geometry geometry;
+ struct rt_spi_device * rt_spi_device;
+ struct rt_mutex lock;
+};
+
+extern rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name);
+
+
+#endif // SPI_FLASH_SST25VFXX_H_INCLUDED
diff --git a/components/drivers/spi/spi_flash_w25qxx.c b/components/drivers/spi/spi_flash_w25qxx.c
new file mode 100644
index 0000000000..bdcdbd83c1
--- /dev/null
+++ b/components/drivers/spi/spi_flash_w25qxx.c
@@ -0,0 +1,371 @@
+/*
+ * File : spi_flash_w25qxx.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-16 aozima the first version
+ * 2012-05-06 aozima can page write.
+ * 2012-08-23 aozima add flash lock.
+ * 2012-08-24 aozima fixed write status register BUG.
+ */
+
+#include <stdint.h>
+#include "spi_flash_w25qxx.h"
+
+#define FLASH_DEBUG
+
+#ifdef FLASH_DEBUG
+#define FLASH_TRACE rt_kprintf
+#else
+#define FLASH_TRACE(...)
+#endif /* #ifdef FLASH_DEBUG */
+
+#define PAGE_SIZE 4096
+
+/* JEDEC Manufacturer��s ID */
+#define MF_ID (0xEF)
+/* JEDEC Device ID: Memory type and Capacity */
+#define MTC_W25Q16_BV_CL_CV (0x4015) /* W25Q16BV W25Q16CL W25Q16CV */
+#define MTC_W25Q16_DW (0x6015) /* W25Q16DW */
+#define MTC_W25Q32_BV (0x4016) /* W25Q32BV */
+#define MTC_W25Q32_DW (0x6016) /* W25Q32DW */
+#define MTC_W25Q64_BV_CV (0x4017) /* W25Q64BV W25Q64CV */
+#define MTC_W25Q64_DW (0x4017) /* W25Q64DW */
+#define MTC_W25Q128_BV (0x4018) /* W25Q128BV */
+#define MTC_W25Q256_FV (TBD) /* W25Q256FV */
+
+/* command list */
+#define CMD_WRSR (0x01) /* Write Status Register */
+#define CMD_PP (0x02) /* Page Program */
+#define CMD_READ (0x03) /* Read Data */
+#define CMD_WRDI (0x04) /* Write Disable */
+#define CMD_RDSR1 (0x05) /* Read Status Register-1 */
+#define CMD_WREN (0x06) /* Write Enable */
+#define CMD_FAST_READ (0x0B) /* Fast Read */
+#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */
+#define CMD_RDSR2 (0x35) /* Read Status Register-2 */
+#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */
+#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */
+#define CMD_ERASE_full (0xC7) /* Chip Erase */
+#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */
+
+#define DUMMY (0xFF)
+
+static struct spi_flash_device spi_flash_device;
+
+static void flash_lock(struct spi_flash_device * flash_device)
+{
+ rt_mutex_take(&flash_device->lock, RT_WAITING_FOREVER);
+}
+
+static void flash_unlock(struct spi_flash_device * flash_device)
+{
+ rt_mutex_release(&flash_device->lock);
+}
+
+static uint8_t w25qxx_read_status(void)
+{
+ return rt_spi_sendrecv8(spi_flash_device.rt_spi_device, CMD_RDSR1);
+}
+
+static void w25qxx_wait_busy(void)
+{
+ while( w25qxx_read_status() & (0x01));
+}
+
+/** \brief read [size] byte from [offset] to [buffer]
+ *
+ * \param offset uint32_t unit : byte
+ * \param buffer uint8_t*
+ * \param size uint32_t unit : byte
+ * \return uint32_t byte for read
+ *
+ */
+static uint32_t w25qxx_read(uint32_t offset, uint8_t * buffer, uint32_t size)
+{
+ uint8_t send_buffer[4];
+
+ send_buffer[0] = CMD_WRDI;
+ rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_READ;
+ send_buffer[1] = (uint8_t)(offset>>16);
+ send_buffer[2] = (uint8_t)(offset>>8);
+ send_buffer[3] = (uint8_t)(offset);
+
+ rt_spi_send_then_recv(spi_flash_device.rt_spi_device,
+ send_buffer, 4,
+ buffer, size);
+
+ return size;
+}
+
+/** \brief write N page on [page]
+ *
+ * \param page_addr uint32_t unit : byte (4096 * N,1 page = 4096byte)
+ * \param buffer const uint8_t*
+ * \return uint32_t
+ *
+ */
+uint32_t w25qxx_page_write(uint32_t page_addr, const uint8_t* buffer)
+{
+ uint32_t index;
+ uint8_t send_buffer[4];
+
+ RT_ASSERT((page_addr&0xFF) == 0); /* page addr must align to 256byte. */
+
+ send_buffer[0] = CMD_WREN;
+ rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_ERASE_4K;
+ send_buffer[1] = (page_addr >> 16);
+ send_buffer[2] = (page_addr >> 8);
+ send_buffer[3] = (page_addr);
+ rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 4);
+
+ w25qxx_wait_busy(); // wait erase done.
+
+ for(index=0; index < (PAGE_SIZE / 256); index++)
+ {
+ send_buffer[0] = CMD_WREN;
+ rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_PP;
+ send_buffer[1] = (uint8_t)(page_addr >> 16);
+ send_buffer[2] = (uint8_t)(page_addr >> 8);
+ send_buffer[3] = (uint8_t)(page_addr);
+
+ rt_spi_send_then_send(spi_flash_device.rt_spi_device,
+ send_buffer,
+ 4,
+ buffer,
+ 256);
+
+ buffer += 256;
+ page_addr += 256;
+ w25qxx_wait_busy();
+ }
+
+ send_buffer[0] = CMD_WRDI;
+ rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1);
+
+ return PAGE_SIZE;
+}
+
+/* RT-Thread device interface */
+static rt_err_t w25qxx_flash_init(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t w25qxx_flash_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ uint8_t send_buffer[3];
+
+ flash_lock((struct spi_flash_device *)dev);
+
+ send_buffer[0] = CMD_WREN;
+ rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1);
+
+ send_buffer[0] = CMD_WRSR;
+ send_buffer[1] = 0;
+ send_buffer[2] = 0;
+ rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 3);
+
+ w25qxx_wait_busy();
+
+ flash_unlock((struct spi_flash_device *)dev);
+
+ return RT_EOK;
+}
+
+static rt_err_t w25qxx_flash_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t w25qxx_flash_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+ RT_ASSERT(dev != RT_NULL);
+
+ if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
+ {
+ struct rt_device_blk_geometry *geometry;
+
+ geometry = (struct rt_device_blk_geometry *)args;
+ if (geometry == RT_NULL) return -RT_ERROR;
+
+ geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector;
+ geometry->sector_count = spi_flash_device.geometry.sector_count;
+ geometry->block_size = spi_flash_device.geometry.block_size;
+ }
+
+ return RT_EOK;
+}
+
+static rt_size_t w25qxx_flash_read(rt_device_t dev,
+ rt_off_t pos,
+ void* buffer,
+ rt_size_t size)
+{
+ flash_lock((struct spi_flash_device *)dev);
+
+ w25qxx_read(pos*spi_flash_device.geometry.bytes_per_sector,
+ buffer,
+ size*spi_flash_device.geometry.bytes_per_sector);
+
+ flash_unlock((struct spi_flash_device *)dev);
+
+ return size;
+}
+
+static rt_size_t w25qxx_flash_write(rt_device_t dev,
+ rt_off_t pos,
+ const void* buffer,
+ rt_size_t size)
+{
+ rt_size_t i = 0;
+ rt_size_t block = size;
+ const uint8_t * ptr = buffer;
+
+ flash_lock((struct spi_flash_device *)dev);
+
+ while(block--)
+ {
+ w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector,
+ ptr);
+ ptr += PAGE_SIZE;
+ i++;
+ }
+
+ flash_unlock((struct spi_flash_device *)dev);
+
+ return size;
+}
+
+rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_name)
+{
+ struct rt_spi_device * rt_spi_device;
+
+ /* initialize mutex */
+ if (rt_mutex_init(&spi_flash_device.lock, spi_device_name, RT_IPC_FLAG_FIFO) != RT_EOK)
+ {
+ rt_kprintf("init sd lock mutex failed\n");
+ return -RT_ENOSYS;
+ }
+
+ rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
+ if(rt_spi_device == RT_NULL)
+ {
+ FLASH_TRACE("spi device %s not found!\r\n", spi_device_name);
+ return -RT_ENOSYS;
+ }
+ spi_flash_device.rt_spi_device = rt_spi_device;
+
+ /* config spi */
+ {
+ struct rt_spi_configuration cfg;
+ cfg.data_width = 8;
+ cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
+ cfg.max_hz = 50 * 1000 * 1000; /* 50M */
+ rt_spi_configure(spi_flash_device.rt_spi_device, &cfg);
+ }
+
+ /* init flash */
+ {
+ rt_uint8_t cmd;
+ rt_uint8_t id_recv[3];
+ uint16_t memory_type_capacity;
+
+ flash_lock(&spi_flash_device);
+
+ cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */
+ rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1);
+
+ cmd = CMD_WRDI;
+ rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1);
+
+ /* read flash id */
+ cmd = CMD_JEDEC_ID;
+ rt_spi_send_then_recv(spi_flash_device.rt_spi_device, &cmd, 1, id_recv, 3);
+
+ flash_unlock(&spi_flash_device);
+
+ if(id_recv[0] != MF_ID)
+ {
+ FLASH_TRACE("Manufacturers ID error!\r\n");
+ FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]);
+ return -RT_ENOSYS;
+ }
+
+ spi_flash_device.geometry.bytes_per_sector = 4096;
+ spi_flash_device.geometry.block_size = 4096; /* block erase: 4k */
+
+ /* get memory type and capacity */
+ memory_type_capacity = id_recv[1];
+ memory_type_capacity = (memory_type_capacity << 8) | id_recv[2];
+
+ if(memory_type_capacity == MTC_W25Q128_BV)
+ {
+ FLASH_TRACE("W25Q128BV detection\r\n");
+ spi_flash_device.geometry.sector_count = 4096;
+ }
+ else if(memory_type_capacity == MTC_W25Q64_BV_CV)
+ {
+ FLASH_TRACE("W25Q64BV or W25Q64CV detection\r\n");
+ spi_flash_device.geometry.sector_count = 2048;
+ }
+ else if(memory_type_capacity == MTC_W25Q64_DW)
+ {
+ FLASH_TRACE("W25Q64DW detection\r\n");
+ spi_flash_device.geometry.sector_count = 2048;
+ }
+ else if(memory_type_capacity == MTC_W25Q32_BV)
+ {
+ FLASH_TRACE("W25Q32BV detection\r\n");
+ spi_flash_device.geometry.sector_count = 1024;
+ }
+ else if(memory_type_capacity == MTC_W25Q32_DW)
+ {
+ FLASH_TRACE("W25Q32DW detection\r\n");
+ spi_flash_device.geometry.sector_count = 1024;
+ }
+ else if(memory_type_capacity == MTC_W25Q16_BV_CL_CV)
+ {
+ FLASH_TRACE("W25Q16BV or W25Q16CL or W25Q16CV detection\r\n");
+ spi_flash_device.geometry.sector_count = 512;
+ }
+ else if(memory_type_capacity == MTC_W25Q16_DW)
+ {
+ FLASH_TRACE("W25Q16DW detection\r\n");
+ spi_flash_device.geometry.sector_count = 512;
+ }
+ else
+ {
+ FLASH_TRACE("Memory Capacity error!\r\n");
+ return -RT_ENOSYS;
+ }
+ }
+
+ /* register device */
+ spi_flash_device.flash_device.type = RT_Device_Class_Block;
+ spi_flash_device.flash_device.init = w25qxx_flash_init;
+ spi_flash_device.flash_device.open = w25qxx_flash_open;
+ spi_flash_device.flash_device.close = w25qxx_flash_close;
+ spi_flash_device.flash_device.read = w25qxx_flash_read;
+ spi_flash_device.flash_device.write = w25qxx_flash_write;
+ spi_flash_device.flash_device.control = w25qxx_flash_control;
+ /* no private */
+ spi_flash_device.flash_device.user_data = RT_NULL;
+
+ rt_device_register(&spi_flash_device.flash_device, flash_device_name,
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
+
+ return RT_EOK;
+}
diff --git a/components/drivers/spi/spi_flash_w25qxx.h b/components/drivers/spi/spi_flash_w25qxx.h
new file mode 100644
index 0000000000..ebab35da33
--- /dev/null
+++ b/components/drivers/spi/spi_flash_w25qxx.h
@@ -0,0 +1,34 @@
+/*
+ * File : spi_flash_w25qxx.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-16 aozima the first version
+ * 2012-08-23 aozima add flash lock.
+ */
+
+#ifndef SPI_FLASH_W25QXX_H_INCLUDED
+#define SPI_FLASH_W25QXX_H_INCLUDED
+
+#include <rtthread.h>
+#include <drivers/spi.h>
+
+struct spi_flash_device
+{
+ struct rt_device flash_device;
+ struct rt_device_blk_geometry geometry;
+ struct rt_spi_device * rt_spi_device;
+ struct rt_mutex lock;
+};
+
+extern rt_err_t w25qxx_init(const char * flash_device_name,
+ const char * spi_device_name);
+
+
+#endif // SPI_FLASH_W25QXX_H_INCLUDED
diff --git a/components/drivers/spi/spi_wifi_rw009.c b/components/drivers/spi/spi_wifi_rw009.c
new file mode 100644
index 0000000000..f45d493717
--- /dev/null
+++ b/components/drivers/spi/spi_wifi_rw009.c
@@ -0,0 +1,590 @@
+/*
+ * File : spi_wifi_rw009.c
+ * This file is part of RT-Thread RTOS
+ * Copyright by Shanghai Real-Thread Electronic Technology Co.,Ltd
+ *
+ * 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
+ * 2014-07-31 aozima the first version
+ */
+
+#include <rtthread.h>
+#include <drivers/spi.h>
+
+#include <netif/ethernetif.h>
+#include <netif/etharp.h>
+#include <lwip/icmp.h>
+#include "lwipopts.h"
+
+#include "spi_wifi_rw009.h"
+
+#define SSID_NAME "AP_SSID"
+#define SSID_PASSWORD "AP_passwd"
+
+//#define WIFI_DEBUG_ON
+// #define ETH_RX_DUMP
+// #define ETH_TX_DUMP
+
+#ifdef WIFI_DEBUG_ON
+#define WIFI_DEBUG rt_kprintf("[WIFI] ");rt_kprintf
+#else
+#define WIFI_DEBUG(...)
+#endif /* #ifdef WIFI_DEBUG_ON */
+
+#define MAX_BUFFER_SIZE (sizeof(struct response) + MAX_DATA_LEN)
+#define MAX_ADDR_LEN 6
+struct spi_wifi_eth
+{
+ /* inherit from ethernet device */
+ struct eth_device parent;
+
+ struct rt_spi_device *rt_spi_device;
+
+ /* interface address info. */
+ rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
+ rt_uint8_t active;
+
+ struct rt_mempool spi_tx_mp;
+ struct rt_mempool spi_rx_mp;
+
+ struct rt_mailbox spi_tx_mb;
+ struct rt_mailbox eth_rx_mb;
+
+ int spi_tx_mb_pool[SPI_TX_POOL_SIZE];
+ int eth_rx_mb_pool[SPI_TX_POOL_SIZE];
+
+ int spi_wifi_cmd_mb_pool[3];
+ struct rt_mailbox spi_wifi_cmd_mb;
+
+ ALIGN(4)
+ rt_uint8_t spi_tx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_TX_POOL_SIZE];
+ ALIGN(4)
+ rt_uint8_t spi_rx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_TX_POOL_SIZE];
+
+ ALIGN(4)
+ uint8_t spi_hw_rx_buffer[MAX_BUFFER_SIZE];
+};
+static struct spi_wifi_eth spi_wifi_device;
+static struct rt_event spi_wifi_data_event;
+
+static void resp_handler(struct spi_wifi_eth *wifi_device, struct spi_wifi_resp *resp)
+{
+ struct spi_wifi_resp *resp_return;
+
+ switch (resp->cmd)
+ {
+ case SPI_WIFI_CMD_INIT:
+ WIFI_DEBUG("resp_handler SPI_WIFI_CMD_INIT\n");
+ resp_return = (struct spi_wifi_resp *)rt_malloc(sizeof(struct spi_wifi_resp)); //TODO:
+ memcpy(resp_return, resp, 10);
+ rt_mb_send(&wifi_device->spi_wifi_cmd_mb, (rt_uint32_t)resp_return);
+ break;
+
+ case SPI_WIFI_CMD_SCAN:
+ WIFI_DEBUG("resp_handler SPI_WIFI_CMD_SCAN\n");
+ break;
+
+ case SPI_WIFI_CMD_JOIN:
+ WIFI_DEBUG("resp_handler SPI_WIFI_CMD_JOIN\n");
+ wifi_device->active = 1;
+ eth_device_linkchange(&wifi_device->parent, RT_TRUE);
+ break;
+
+ default:
+ WIFI_DEBUG("resp_handler %d\n", resp->cmd);
+ break;
+ }
+
+}
+
+static rt_err_t spi_wifi_transfer(struct spi_wifi_eth *dev)
+{
+ struct pbuf *p = RT_NULL;
+ struct cmd_request cmd;
+ struct response resp;
+
+ rt_err_t result;
+ const struct spi_data_packet *data_packet = RT_NULL;
+
+ struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
+ struct rt_spi_device *rt_spi_device = wifi_device->rt_spi_device;
+
+ spi_wifi_int_cmd(0);
+ while (spi_wifi_is_busy());
+ WIFI_DEBUG("sequence start!\n");
+
+ memset(&cmd, 0, sizeof(struct cmd_request));
+ cmd.magic1 = CMD_MAGIC1;
+ cmd.magic2 = CMD_MAGIC2;
+
+ cmd.flag |= CMD_FLAG_MRDY;
+
+ result = rt_mb_recv(&wifi_device->spi_tx_mb,
+ (rt_uint32_t *)&data_packet,
+ 0);
+ if ((result == RT_EOK) && (data_packet != RT_NULL) && (data_packet->data_len > 0))
+ {
+ cmd.M2S_len = data_packet->data_len + member_offset(struct spi_data_packet, buffer);
+ //WIFI_DEBUG("cmd.M2S_len = %d\n", cmd.M2S_len);
+ }
+
+ rt_spi_send(rt_spi_device, &cmd, sizeof(cmd));
+ while (spi_wifi_is_busy());
+
+ {
+ struct rt_spi_message message;
+ uint32_t max_data_len = 0;
+
+ /* setup message */
+ message.send_buf = RT_NULL;
+ message.recv_buf = &resp;
+ message.length = sizeof(resp);
+ message.cs_take = 1;
+ message.cs_release = 0;
+
+ rt_spi_take_bus(rt_spi_device);
+
+ /* transfer message */
+ rt_spi_device->bus->ops->xfer(rt_spi_device, &message);
+
+ if ((resp.magic1 != RESP_MAGIC1) || (resp.magic2 != RESP_MAGIC2))
+ {
+ WIFI_DEBUG("bad resp magic, abort!\n");
+ goto _bad_resp_magic;
+ }
+
+ if (resp.flag & RESP_FLAG_SRDY)
+ {
+ WIFI_DEBUG("RESP_FLAG_SRDY\n");
+ max_data_len = cmd.M2S_len;
+ }
+
+ if (resp.S2M_len)
+ {
+ WIFI_DEBUG("resp.S2M_len: %d\n", resp.S2M_len);
+ if (resp.S2M_len > sizeof(struct spi_data_packet))
+ {
+ WIFI_DEBUG("resp.S2M_len > sizeof(struct spi_data_packet), drop!\n");
+ resp.S2M_len = 0;//drop
+ }
+
+ if (resp.S2M_len > max_data_len)
+ max_data_len = resp.S2M_len;
+ }
+
+ if (max_data_len == 0)
+ {
+ WIFI_DEBUG("no rx or tx data!\n");
+ }
+
+ //WIFI_DEBUG("max_data_len = %d\n", max_data_len);
+
+_bad_resp_magic:
+ /* setup message */
+ message.send_buf = data_packet;//&tx_buffer;
+ message.recv_buf = wifi_device->spi_hw_rx_buffer;//&rx_buffer;
+ message.length = max_data_len;
+ message.cs_take = 0;
+ message.cs_release = 1;
+
+ /* transfer message */
+ rt_spi_device->bus->ops->xfer(rt_spi_device, &message);
+
+ rt_spi_release_bus(rt_spi_device);
+
+ if (cmd.M2S_len && (resp.flag & RESP_FLAG_SRDY))
+ {
+ rt_mp_free((void *)data_packet);
+ }
+
+ if ((resp.S2M_len) && (resp.S2M_len <= MAX_DATA_LEN))
+ {
+ data_packet = (struct spi_data_packet *)wifi_device->spi_hw_rx_buffer;
+ if (data_packet->data_type == data_type_eth_data)
+ {
+
+ if (wifi_device->active)
+ {
+ p = pbuf_alloc(PBUF_LINK, data_packet->data_len, PBUF_RAM);
+ pbuf_take(p, (rt_uint8_t *)data_packet->buffer, data_packet->data_len);
+
+ rt_mb_send(&wifi_device->eth_rx_mb, (rt_uint32_t)p);
+ eth_device_ready((struct eth_device *)dev);
+ }
+ else
+ {
+ WIFI_DEBUG("!active, RX drop.\n");
+ }
+ }
+ else if (data_packet->data_type == data_type_resp)
+ {
+ WIFI_DEBUG("data_type_resp\n");
+ resp_handler(dev, (struct spi_wifi_resp *)data_packet->buffer);
+ }
+ else
+ {
+ WIFI_DEBUG("data_type: %d, %dbyte\n",
+ data_packet->data_type,
+ data_packet->data_len);
+ }
+ }
+ }
+ spi_wifi_int_cmd(1);
+
+ WIFI_DEBUG("sequence finish!\n\n");
+
+ if ((cmd.M2S_len == 0) && (resp.S2M_len == 0))
+ {
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+
+#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
+static void packet_dump(const char *msg, const struct pbuf *p)
+{
+ rt_uint32_t i;
+ rt_uint8_t *ptr = p->payload;
+
+ rt_kprintf("%s %d byte\n", msg, p->tot_len);
+
+ for (i = 0; i < p->tot_len; i++)
+ {
+ if ((i % 8) == 0)
+ {
+ rt_kprintf(" ");
+ }
+ if ((i % 16) == 0)
+ {
+ rt_kprintf("\r\n");
+ }
+ rt_kprintf("%02x ", *ptr);
+ ptr++;
+ }
+ rt_kprintf("\n\n");
+}
+#endif /* dump */
+
+/* initialize the interface */
+static rt_err_t spi_wifi_eth_init(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t spi_wifi_eth_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ return RT_EOK;
+}
+
+static rt_err_t spi_wifi_eth_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_size_t spi_wifi_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+static rt_size_t spi_wifi_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+
+static rt_err_t spi_wifi_eth_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+ struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
+ struct spi_data_packet *data_packet;
+ struct spi_wifi_cmd *wifi_cmd;
+ struct spi_wifi_resp *resp;
+
+ switch (cmd)
+ {
+ case NIOCTL_GADDR:
+ memcpy(args, wifi_device->dev_addr, 6);
+ break;
+
+ case SPI_WIFI_CMD_INIT:
+ /* get mac address */
+ if (args)
+ {
+ rt_err_t result;
+
+ data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
+ // TODO: check result.
+
+ wifi_cmd = (struct spi_wifi_cmd *)data_packet->buffer;
+ wifi_cmd->cmd = SPI_WIFI_CMD_INIT;
+
+ data_packet->data_type = data_type_cmd;
+ data_packet->data_len = member_offset(struct spi_wifi_cmd, buffer) + 0;
+
+ rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
+ rt_event_send(&spi_wifi_data_event, 1);
+
+ result = rt_mb_recv(&wifi_device->spi_wifi_cmd_mb,
+ (rt_uint32_t *)&resp,
+ RT_WAITING_FOREVER);
+
+ if ((result == RT_EOK) && (resp != RT_NULL))
+ {
+ WIFI_DEBUG("resp cmd: %d\n", resp->cmd);
+
+ rt_memcpy(args, resp->buffer, 6);
+ }
+ }
+ else return -RT_ERROR;
+ break;
+
+
+ case SPI_WIFI_CMD_SCAN:
+
+ case SPI_WIFI_CMD_JOIN:
+ if (args)
+ {
+ struct cmd_join *cmd_join;
+
+ data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
+
+ wifi_cmd = (struct spi_wifi_cmd *)data_packet->buffer;
+ wifi_cmd->cmd = SPI_WIFI_CMD_JOIN;
+ cmd_join = (struct cmd_join *)wifi_cmd->buffer;
+
+#define WPA_SECURITY 0x00200000
+#define WPA2_SECURITY 0x00400000
+
+#define TKIP_ENABLED 0x0002
+#define AES_ENABLED 0x0004
+
+
+ strncpy(cmd_join->ssid, SSID_NAME, SSID_NAME_LENGTH_MAX);
+ strncpy(cmd_join->passwd, SSID_PASSWORD, PASSWORD_LENGTH_MAX);
+ cmd_join->security = WPA2_SECURITY | TKIP_ENABLED | AES_ENABLED;
+ // cmd_join->security = WPA_SECURITY | TKIP_ENABLED;
+ data_packet->data_type = data_type_cmd;
+ data_packet->data_len = sizeof(struct cmd_join) + member_offset(struct spi_wifi_cmd, buffer);
+
+ rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
+ rt_event_send(&spi_wifi_data_event, 1);
+ }
+ else return -RT_ERROR;
+ break;
+
+ default :
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/* transmit packet. */
+rt_err_t spi_wifi_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+ rt_err_t result = RT_EOK;
+ struct spi_data_packet *data_packet;
+ struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
+
+ if (!wifi_device->active)
+ {
+ WIFI_DEBUG("!active, TX drop!\n");
+ return RT_EOK;
+ }
+
+ /* get free tx buffer */
+ data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
+ if (data_packet != RT_NULL)
+ {
+ data_packet->data_type = data_type_eth_data;
+ data_packet->data_len = p->tot_len;
+
+ pbuf_copy_partial(p, data_packet->buffer, data_packet->data_len, 0);
+
+ rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
+ eth_device_ready((struct eth_device *)dev);
+ }
+ else
+ return -RT_ERROR;
+
+#ifdef ETH_TX_DUMP
+ packet_dump("TX dump", p);
+#endif /* ETH_TX_DUMP */
+
+ /* Return SUCCESS */
+ return result;
+}
+
+/* reception packet. */
+struct pbuf *spi_wifi_eth_rx(rt_device_t dev)
+{
+ struct pbuf *p = RT_NULL;
+ struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
+
+ if (rt_mb_recv(&wifi_device->eth_rx_mb, (rt_uint32_t *)&p, 0) != RT_EOK)
+ {
+ return RT_NULL;
+ }
+
+
+
+ return p;
+}
+
+static void spi_wifi_data_thread_entry(void *parameter)
+{
+ rt_uint32_t e;
+ rt_err_t result;
+
+ while (1)
+ {
+ /* receive first event */
+ if (rt_event_recv(&spi_wifi_data_event,
+ 1,
+ RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
+ RT_WAITING_FOREVER,
+ &e) != RT_EOK)
+ {
+ continue;
+ }
+
+ result = spi_wifi_transfer(&spi_wifi_device);
+
+ if (result == RT_EOK)
+ {
+ rt_event_send(&spi_wifi_data_event, 1);
+ }
+ }
+}
+
+rt_err_t rt_hw_wifi_init(const char *spi_device_name)
+{
+ memset(&spi_wifi_device, 0, sizeof(struct spi_wifi_eth));
+
+ spi_wifi_device.rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
+
+ if (spi_wifi_device.rt_spi_device == RT_NULL)
+ {
+ WIFI_DEBUG("spi device %s not found!\r\n", spi_device_name);
+ return -RT_ENOSYS;
+ }
+
+ /* config spi */
+ {
+ struct rt_spi_configuration cfg;
+ cfg.data_width = 8;
+ cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
+ cfg.max_hz = 1000000; /* 50M */
+ rt_spi_configure(spi_wifi_device.rt_spi_device, &cfg);
+ }
+
+ spi_wifi_device.parent.parent.init = spi_wifi_eth_init;
+ spi_wifi_device.parent.parent.open = spi_wifi_eth_open;
+ spi_wifi_device.parent.parent.close = spi_wifi_eth_close;
+ spi_wifi_device.parent.parent.read = spi_wifi_eth_read;
+ spi_wifi_device.parent.parent.write = spi_wifi_eth_write;
+ spi_wifi_device.parent.parent.control = spi_wifi_eth_control;
+ spi_wifi_device.parent.parent.user_data = RT_NULL;
+
+ spi_wifi_device.parent.eth_rx = spi_wifi_eth_rx;
+ spi_wifi_device.parent.eth_tx = spi_wifi_eth_tx;
+
+ rt_mp_init(&spi_wifi_device.spi_tx_mp,
+ "spi_tx",
+ &spi_wifi_device.spi_tx_mempool[0],
+ sizeof(spi_wifi_device.spi_tx_mempool),
+ sizeof(struct spi_data_packet));
+
+ rt_mp_init(&spi_wifi_device.spi_rx_mp,
+ "spi_rx",
+ &spi_wifi_device.spi_rx_mempool[0],
+ sizeof(spi_wifi_device.spi_rx_mempool),
+ sizeof(struct spi_data_packet));
+
+ rt_mb_init(&spi_wifi_device.spi_tx_mb,
+ "spi_tx",
+ &spi_wifi_device.spi_tx_mb_pool[0],
+ SPI_TX_POOL_SIZE,
+ RT_IPC_FLAG_PRIO);
+
+ rt_mb_init(&spi_wifi_device.eth_rx_mb,
+ "eth_rx",
+ &spi_wifi_device.eth_rx_mb_pool[0],
+ SPI_TX_POOL_SIZE,
+ RT_IPC_FLAG_PRIO);
+
+ rt_mb_init(&spi_wifi_device.spi_wifi_cmd_mb,
+ "wifi_cmd",
+ &spi_wifi_device.spi_wifi_cmd_mb_pool[0],
+ sizeof(spi_wifi_device.spi_wifi_cmd_mb_pool) / 4,
+ RT_IPC_FLAG_PRIO);
+ rt_event_init(&spi_wifi_data_event, "wifi", RT_IPC_FLAG_FIFO);
+
+ spi_wifi_hw_init();
+
+ {
+ rt_thread_t tid;
+
+
+ tid = rt_thread_create("wifi",
+ spi_wifi_data_thread_entry,
+ RT_NULL,
+ 2048,
+ RT_THREAD_PRIORITY_MAX - 2,
+ 20);
+
+ if (tid != RT_NULL)
+ rt_thread_startup(tid);
+ }
+
+ /* init: get mac address */
+ {
+ WIFI_DEBUG("wifi_control SPI_WIFI_CMD_INIT\n");
+ spi_wifi_eth_control((rt_device_t)&spi_wifi_device,
+ SPI_WIFI_CMD_INIT,
+ (void *)&spi_wifi_device.dev_addr[0]);
+
+ }
+ /* register eth device */
+ eth_device_init(&(spi_wifi_device.parent), "w0");
+ eth_device_linkchange(&spi_wifi_device.parent, RT_FALSE);
+
+ {
+ WIFI_DEBUG("wifi_control SPI_WIFI_CMD_JOIN\n");
+ spi_wifi_eth_control((rt_device_t)&spi_wifi_device,
+ SPI_WIFI_CMD_JOIN,
+ (void *)&spi_wifi_device.dev_addr[0]);
+
+ WIFI_DEBUG("wifi_control exit\n");
+ }
+
+ return RT_EOK;
+}
+
+void spi_wifi_isr(int vector)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ WIFI_DEBUG("spi_wifi_isr\n");
+ rt_event_send(&spi_wifi_data_event, 1);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
diff --git a/components/drivers/spi/spi_wifi_rw009.h b/components/drivers/spi/spi_wifi_rw009.h
new file mode 100644
index 0000000000..b609e7cb13
--- /dev/null
+++ b/components/drivers/spi/spi_wifi_rw009.h
@@ -0,0 +1,123 @@
+/*
+ * File : spi_wifi_rw009.h
+ * This file is part of RT-Thread RTOS
+ * Copyright by Shanghai Real-Thread Electronic Technology Co.,Ltd
+ *
+ * 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
+ * 2014-07-31 aozima the first version
+ */
+
+#ifndef SPI_WIFI_H_INCLUDED
+#define SPI_WIFI_H_INCLUDED
+
+#include <stdint.h>
+
+// little-endian
+struct cmd_request
+{
+ uint32_t flag;
+ uint32_t M2S_len; // master to slave data len.
+ uint32_t magic1;
+ uint32_t magic2;
+};
+
+#define CMD_MAGIC1 (0x67452301)
+#define CMD_MAGIC2 (0xEFCDAB89)
+
+#define CMD_FLAG_MRDY (0x01)
+
+// little-endian
+struct response
+{
+ uint32_t flag;
+ uint32_t S2M_len; // slave to master data len.
+ uint32_t magic1;
+ uint32_t magic2;
+};
+
+#define RESP_FLAG_SRDY (0x01)
+#define RESP_MAGIC1 (0x98BADCFE)
+#define RESP_MAGIC2 (0x10325476)
+
+/* spi slave configure. */
+#define MAX_DATA_LEN 1520
+#define SPI_TX_POOL_SIZE 2
+
+// align check
+#if (MAX_DATA_LEN & 0x03) != 0
+#error MAX_DATA_LEN must ALIGN to 4byte!
+#endif
+
+typedef enum
+{
+ data_type_eth_data = 0,
+ data_type_cmd,
+ data_type_resp,
+}
+app_data_type_typedef;
+
+struct spi_data_packet
+{
+ uint32_t data_len;
+ uint32_t data_type;
+ char buffer[MAX_DATA_LEN];
+};
+
+struct spi_wifi_cmd
+{
+ uint32_t cmd;
+ char buffer[128];
+};
+
+struct spi_wifi_resp
+{
+ uint32_t cmd;
+ char buffer[128];
+};
+
+#define SPI_WIFI_CMD_INIT 128 //wait
+#define SPI_WIFI_CMD_SCAN 129 //no wait
+#define SPI_WIFI_CMD_JOIN 130 //no wait
+
+/* porting */
+extern void spi_wifi_hw_init(void);
+extern void spi_wifi_int_cmd(rt_bool_t cmd);
+extern rt_bool_t spi_wifi_is_busy(void);
+
+/* tools */
+#define node_entry(node, type, member) \
+ ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
+#define member_offset(type, member) \
+ ((unsigned long)(&((type *)0)->member))
+
+#define SSID_NAME_LENGTH_MAX (32)
+#define PASSWORD_LENGTH_MAX (32)
+
+struct cmd_join
+{
+ char ssid[SSID_NAME_LENGTH_MAX];
+ char passwd[PASSWORD_LENGTH_MAX];
+
+ uint8_t bssid[8]; // 6byte + 2byte PAD.
+
+ uint32_t channel;
+ uint32_t security;
+};
+
+
+#endif // SPI_WIFI_H_INCLUDED
diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c
new file mode 100644
index 0000000000..d9062e6cdb
--- /dev/null
+++ b/components/drivers/src/workqueue.c
@@ -0,0 +1,102 @@
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#ifdef RT_USING_HEAP
+static void _workqueue_thread_entry(void* parameter)
+{
+ struct rt_work* work;
+ struct rt_workqueue* queue;
+
+ queue = (struct rt_workqueue*) parameter;
+ RT_ASSERT(queue != RT_NULL);
+
+ while (1)
+ {
+ if (rt_list_isempty(&(queue->work_list)))
+ {
+ /* no software timer exist, suspend self. */
+ rt_thread_suspend(rt_thread_self());
+ rt_schedule();
+ }
+
+ /* we have work to do with. */
+ rt_enter_critical();
+ work = rt_list_entry(queue->work_list.next, struct rt_work, list);
+ rt_list_remove(&(work->list));
+ rt_exit_critical();
+
+ /* do work */
+ work->work_func(work, work->work_data);
+ }
+}
+
+struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_size, rt_uint8_t priority)
+{
+ struct rt_workqueue *queue = RT_NULL;
+
+ queue = (struct rt_workqueue*)RT_KERNEL_MALLOC(sizeof(struct rt_workqueue));
+ if (queue != RT_NULL)
+ {
+ /* initialize work list */
+ rt_list_init(&(queue->work_list));
+
+ /* create the work thread */
+ queue->work_thread = rt_thread_create(name, _workqueue_thread_entry, queue, stack_size, priority, 10);
+ if (queue->work_thread == RT_NULL)
+ {
+ RT_KERNEL_FREE(queue);
+ return RT_NULL;
+ }
+
+ rt_thread_startup(queue->work_thread);
+ }
+
+ return queue;
+}
+
+rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue)
+{
+ RT_ASSERT(queue != RT_NULL);
+
+ rt_thread_delete(queue->work_thread);
+ RT_KERNEL_FREE(queue);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_workqueue_dowork(struct rt_workqueue* queue, struct rt_work* work)
+{
+ RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(work != RT_NULL);
+
+ rt_enter_critical();
+ /* NOTE: the work MUST be initialized firstly */
+ rt_list_remove(&(work->list));
+
+ rt_list_insert_after(queue->work_list.prev, &(work->list));
+ if (queue->work_thread->stat != RT_THREAD_READY)
+ {
+ rt_exit_critical();
+ /* resume work thread */
+ rt_thread_resume(queue->work_thread);
+ rt_schedule();
+ }
+ else rt_exit_critical();
+
+ return RT_EOK;
+}
+
+rt_err_t rt_workqueue_cancel_work(struct rt_workqueue* queue, struct rt_work* work)
+{
+ RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(work != RT_NULL);
+
+ rt_enter_critical();
+ rt_list_remove(&(work->list));
+ rt_exit_critical();
+
+ return RT_EOK;
+}
+
+#endif
+
diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c
index 33f9f7abef..8916f3a084 100644
--- a/components/drivers/usb/usbdevice/class/cdc_vcom.c
+++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c
@@ -280,7 +280,7 @@ static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
data->ep_out->request.buffer = data->ep_out->buffer;
data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
- data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_MOST;
rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
return RT_EOK;
@@ -435,7 +435,7 @@ static rt_err_t _function_enable(ufunction_t func)
data->ep_out->request.buffer = data->ep_out->buffer;
data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
- data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_MOST;
rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
return RT_EOK;
diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c
index dadd81352b..b845b27c4c 100644
--- a/components/drivers/usb/usbdevice/core/core.c
+++ b/components/drivers/usb/usbdevice/core/core.c
@@ -772,10 +772,18 @@ static rt_err_t _data_notify(udevice_t device, struct ep_msg* ep_msg)
size = dcd_ep_read(device->dcd, EP_ADDRESS(ep),
ep->request.buffer);
}
- ep->request.remain_size -= size;
- ep->request.buffer += size;
- if(ep->request.req_type == UIO_REQUEST_READ_BEST)
+ if(size > ep->request.remain_size)
+ {
+ ep->request.remain_size = 0;
+ }
+ else
+ {
+ ep->request.remain_size -= size;
+ ep->request.buffer += size;
+ }
+
+ if(ep->request.req_type == UIO_REQUEST_READ_MOST)
{
EP_HANDLER(ep, func, size);
}
@@ -881,6 +889,7 @@ static rt_err_t _stop_notify(udevice_t device)
static rt_size_t rt_usbd_ep_write(udevice_t device, uep_t ep, void *buffer, rt_size_t size)
{
rt_uint16_t maxpacket;
+ rt_size_t sent_size;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->dcd != RT_NULL);
@@ -889,18 +898,18 @@ static rt_size_t rt_usbd_ep_write(udevice_t device, uep_t ep, void *buffer, rt_s
maxpacket = EP_MAXPACKET(ep);
if(ep->request.remain_size >= maxpacket)
{
- dcd_ep_write(device->dcd, EP_ADDRESS(ep), ep->request.buffer, maxpacket);
- ep->request.remain_size -= maxpacket;
+ sent_size = dcd_ep_write(device->dcd, EP_ADDRESS(ep), ep->request.buffer, maxpacket);
+ ep->request.remain_size -= sent_size;
ep->request.buffer += maxpacket;
}
else
{
- dcd_ep_write(device->dcd, EP_ADDRESS(ep), ep->request.buffer,
+ sent_size = dcd_ep_write(device->dcd, EP_ADDRESS(ep), ep->request.buffer,
ep->request.remain_size);
- ep->request.remain_size = 0;
+ ep->request.remain_size -= sent_size;
}
- return size;
+ return sent_size;
}
static rt_size_t rt_usbd_ep_read_prepare(udevice_t device, uep_t ep, void *buffer, rt_size_t size)
@@ -1623,7 +1632,7 @@ rt_size_t rt_usbd_io_request(udevice_t device, uep_t ep, uio_request_t req)
{
switch(req->req_type)
{
- case UIO_REQUEST_READ_BEST:
+ case UIO_REQUEST_READ_MOST:
case UIO_REQUEST_READ_FULL:
ep->request.remain_size = ep->request.size;
size = rt_usbd_ep_read_prepare(device, ep, req->buffer, req->size);
@@ -1757,7 +1766,8 @@ static rt_err_t rt_usbd_ep_assign(udevice_t device, uep_t ep)
while(device->dcd->ep_pool[i].addr != 0xFF)
{
if(device->dcd->ep_pool[i].status == ID_UNASSIGNED &&
- ep->ep_desc->bmAttributes == device->dcd->ep_pool[i].type)
+ ep->ep_desc->bmAttributes == device->dcd->ep_pool[i].type &&
+ ep->ep_desc->bEndpointAddress == device->dcd->ep_pool[i].dir)
{
EP_ADDRESS(ep) |= device->dcd->ep_pool[i].addr;
ep->id = &device->dcd->ep_pool[i];
@@ -1786,7 +1796,7 @@ static rt_err_t rt_usbd_ep_unassign(udevice_t device, uep_t ep)
return RT_EOK;
}
-rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct ureqest* setup)
+rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct urequest* setup)
{
struct udev_msg msg;
rt_size_t size;
@@ -1796,7 +1806,7 @@ rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct ureqest* setup)
if(setup == RT_NULL)
{
size = dcd_ep_read(dcd, EP0_OUT_ADDR, (void*)&msg.content.setup);
- if(size != sizeof(struct ureqest))
+ if(size != sizeof(struct urequest))
{
rt_kprintf("read setup packet error\n");
return -RT_ERROR;
@@ -1804,7 +1814,7 @@ rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct ureqest* setup)
}
else
{
- rt_memcpy((void*)&msg.content.setup, (void*)setup, sizeof(struct ureqest));
+ rt_memcpy((void*)&msg.content.setup, (void*)setup, sizeof(struct urequest));
}
msg.type = USB_MSG_SETUP_NOTIFY;
@@ -1935,6 +1945,7 @@ rt_err_t rt_usbd_sof_handler(udcd_t dcd)
rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size)
{
uep_t ep0;
+ rt_size_t sent_size = 0;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->dcd != RT_NULL);
@@ -1947,17 +1958,17 @@ rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size)
ep0->request.remain_size = size;
if(ep0->request.remain_size >= ep0->id->maxpacket)
{
- dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, ep0->id->maxpacket);
- ep0->request.remain_size -= ep0->id->maxpacket;
+ sent_size = dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, ep0->id->maxpacket);
+ ep0->request.remain_size -= sent_size;
ep0->request.buffer += ep0->id->maxpacket;
}
else
{
- dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, ep0->request.remain_size);
- ep0->request.remain_size = 0;
+ sent_size = dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, ep0->request.remain_size);
+ ep0->request.remain_size -= sent_size;
}
- return size;
+ return sent_size;
}
rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size,
diff --git a/components/external/libpng/pngconf.h b/components/external/libpng/pngconf.h
index bb0a189f9d..cca0657e4c 100644
--- a/components/external/libpng/pngconf.h
+++ b/components/external/libpng/pngconf.h
@@ -24,10 +24,10 @@
#define PNG_MAX_MALLOC_64K
#define PNG_NO_STDIO
#define PNG_NO_ERROR_NUMBERS
+#define PNG_NO_WRITE_SUPPORTED
#define PNG_ABORT() do { rt_kprintf("libpng abort.\n"); } while (0)
#ifndef RT_USING_NEWLIB
-#define PNG_NO_WRITE_SUPPORTED
#define PNG_NO_SETJMP_SUPPORTED
#define malloc rtgui_malloc
#define free rtgui_free
diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c
index 9a79ba396b..e449e0c2dc 100644
--- a/components/finsh/cmd.c
+++ b/components/finsh/cmd.c
@@ -471,17 +471,18 @@ static long _list_device(struct rt_list_node *list)
"Unknown"
};
- rt_kprintf("device type \n");
- rt_kprintf("-------- ---------- \n");
+ rt_kprintf("device type ref count\n");
+ rt_kprintf("-------- -------------------- ----------\n");
for (node = list->next; node != list; node = node->next)
{
device = (struct rt_device *)(rt_list_entry(node, struct rt_object, list));
- rt_kprintf("%-8.*s %-8s \n",
+ rt_kprintf("%-8.*s %-20s %-8d\n",
RT_NAME_MAX,
device->parent.name,
(device->type <= RT_Device_Class_Unknown) ?
device_type_str[device->type] :
- device_type_str[RT_Device_Class_Unknown]);
+ device_type_str[RT_Device_Class_Unknown],
+ device->ref_count);
}
return 0;
diff --git a/components/finsh/finsh.h b/components/finsh/finsh.h
index cf7ee05808..0b270ddeaf 100644
--- a/components/finsh/finsh.h
+++ b/components/finsh/finsh.h
@@ -411,7 +411,6 @@ struct finsh_parser
*
* The basic data type in finsh shell
*/
-
enum finsh_type {
finsh_type_unknown = 0, /**< unknown data type */
finsh_type_void, /**< void */
diff --git a/components/finsh/msh_cmd.c b/components/finsh/msh_cmd.c
index 3bbd46958f..7c67681833 100644
--- a/components/finsh/msh_cmd.c
+++ b/components/finsh/msh_cmd.c
@@ -88,8 +88,50 @@ int cmd_mv(int argc, char** argv)
}
else
{
+ int fd;
+ char *dest = RT_NULL;
+
rt_kprintf("%s => %s\n", argv[1], argv[2]);
- rename(argv[1], argv[2]);
+
+ fd = open(argv[2], O_DIRECTORY, 0);
+ if (fd >= 0)
+ {
+ char *src;
+
+ close(fd);
+
+ /* it's a directory */
+ dest = (char*)rt_malloc(DFS_PATH_MAX);
+ if (dest == RT_NULL)
+ {
+ rt_kprintf("out of memory\n");
+ return -RT_ENOMEM;
+ }
+
+ src = argv[1] + rt_strlen(argv[1]);
+ while (src != argv[1])
+ {
+ if (*src == '/') break;
+ src --;
+ }
+
+ rt_snprintf(dest, DFS_PATH_MAX - 1, "%s/%s", argv[2], src);
+ }
+ else
+ {
+ fd = open(argv[2], O_RDONLY, 0);
+ if (fd >= 0)
+ {
+ close(fd);
+
+ unlink(argv[2]);
+ }
+
+ dest = argv[2];
+ }
+
+ rename(argv[1], dest);
+ if (dest != RT_NULL && dest != argv[2]) rt_free(dest);
}
return 0;
diff --git a/components/finsh/shell.c b/components/finsh/shell.c
index 393d68713c..a9559954e6 100644
--- a/components/finsh/shell.c
+++ b/components/finsh/shell.c
@@ -112,7 +112,7 @@ void finsh_set_device(const char* device_name)
/* check whether it's a same device */
if (dev == shell->device) return;
/* open this device and set the new device in finsh shell */
- if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) == RT_EOK)
+ if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX) == RT_EOK)
{
if (shell->device != RT_NULL)
{
@@ -306,8 +306,8 @@ void finsh_thread_entry(void* parameter)
#ifdef RT_USING_CONSOLE
shell->device = rt_console_get_device();
RT_ASSERT(shell->device);
- rt_device_open(shell->device, RT_DEVICE_OFLAG_RDWR);
rt_device_set_rx_indicate(shell->device, finsh_rx_ind);
+ rt_device_open(shell->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#else
RT_ASSERT(shell->device);
#endif
@@ -530,6 +530,12 @@ void finsh_thread_entry(void* parameter)
ch = 0;
shell->line_position ++;
shell->line_curpos++;
+ if (shell->line_position >= 80)
+ {
+ /* clear command line */
+ shell->line_position = 0;
+ shell->line_curpos = 0;
+ }
} /* end of device read */
}
}
diff --git a/components/libc/armlibc/mem_std.c b/components/libc/armlibc/mem_std.c
index 017ed77fef..6faf86555f 100644
--- a/components/libc/armlibc/mem_std.c
+++ b/components/libc/armlibc/mem_std.c
@@ -1,7 +1,16 @@
/*
- * File: mem_std.c
- * Brief: Replace memory management functions of arm standard c library
+ * File : mem_std.c
+ * Brief : implement standard memory routins.
*
+ * This file is part of Device File System in RT-Thread RTOS
+ * COPYRIGHT (C) 2014, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE.
+ *
+ * Change Logs:
+ * 2014-08-03 bernard Add file header.
*/
#include "rtthread.h"
@@ -9,16 +18,21 @@
/* avoid the heap and heap-using library functions supplied by arm */
#pragma import(__use_no_heap)
-void * malloc(int n)
+void *malloc(int n)
{
return rt_malloc(n);
}
-void * realloc(void *rmem, rt_size_t newsize)
+void *realloc(void *rmem, rt_size_t newsize)
{
return rt_realloc(rmem, newsize);
}
+void *calloc(rt_size_t nelem, rt_size_t elsize)
+{
+ return rt_calloc(nelem, elsize);
+}
+
void free(void *rmem)
{
rt_free(rmem);
diff --git a/components/libc/armlibc/stubs.c b/components/libc/armlibc/stubs.c
index 301f654182..1f9e01ba3c 100644
--- a/components/libc/armlibc/stubs.c
+++ b/components/libc/armlibc/stubs.c
@@ -13,6 +13,8 @@
* Date Author Notes
* 2012-11-23 Yihui The first version
* 2013-11-24 aozima fixed _sys_read()/_sys_write() issues.
+ * 2014-08-03 bernard If using msh, use system() implementation
+ * in msh.
*/
#include <string.h>
@@ -46,8 +48,10 @@ const char __stderr_name[] = "STDERR";
*/
FILEHANDLE _sys_open(const char *name, int openmode)
{
+#ifdef RT_USING_DFS
int fd;
-
+#endif
+
/* Register standard Input Output devices. */
if (strcmp(name, __stdin_name) == 0)
return (STDIN);
@@ -91,12 +95,13 @@ int _sys_close(FILEHANDLE fh)
*/
int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode)
{
+#ifdef RT_USING_DFS
int size;
-
+#endif
+
if (fh == STDIN)
{
/* TODO */
-
return 0;
}
@@ -125,8 +130,10 @@ int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode)
*/
int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode)
{
+#ifdef RT_USING_DFS
int size;
-
+#endif
+
if ((fh == STDOUT) || (fh == STDERR))
{
#ifndef RT_USING_CONSOLE
@@ -189,9 +196,13 @@ char *_sys_command_string(char *cmd, int len)
return cmd;
}
+/* This function writes a character to the console. */
void _ttywrch(int ch)
{
- /* TODO */
+ char c;
+
+ c = (char)ch;
+ rt_kprintf(&c);
}
void _sys_exit(int return_code)
@@ -226,18 +237,12 @@ int remove(const char *filename)
#endif
}
-/* rename() is defined in dfs_posix.c instead */
-#if 0
-int rename(const char *old, const char *new)
-{
- return -1;
-}
-#endif
-
+#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) && defined(RT_USING_MODULE) && defined(RT_USING_DFS)
+/* use system implementation in the msh */
+#else
int system(const char *string)
{
RT_ASSERT(0);
for(;;);
}
-
-
+#endif
diff --git a/components/libc/minilibc/sys/types.h b/components/libc/minilibc/sys/types.h
index 6d92d80826..a6860f2aee 100644
--- a/components/libc/minilibc/sys/types.h
+++ b/components/libc/minilibc/sys/types.h
@@ -4,7 +4,7 @@
#include <rtthread.h>
typedef long off_t;
-typedef rt_size_t size_t;
+typedef __SIZE_TYPE__ size_t;
typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */
typedef rt_uint8_t u_char;
diff --git a/components/libc/newlib/syscalls.c b/components/libc/newlib/syscalls.c
index 5b829f4753..388d240c94 100644
--- a/components/libc/newlib/syscalls.c
+++ b/components/libc/newlib/syscalls.c
@@ -3,6 +3,14 @@
#include <sys/time.h>
#include <rtthread.h>
+#ifdef RT_USING_DFS
+#include <dfs_posix.h>
+#endif
+
+#ifdef RT_USING_PTHREADS
+#include <pthread.h>
+#endif
+
/* Reentrant versions of system calls. */
int
diff --git a/components/net/lwip-1.3.2/apps/ping.c b/components/net/lwip-1.3.2/apps/ping.c
index d3c3dd399b..1e595dce61 100644
--- a/components/net/lwip-1.3.2/apps/ping.c
+++ b/components/net/lwip-1.3.2/apps/ping.c
@@ -39,135 +39,140 @@
static u16_t ping_seq_num;
struct _ip_addr
{
- rt_uint8_t addr0, addr1, addr2, addr3;
+ rt_uint8_t addr0, addr1, addr2, addr3;
};
/** Prepare a echo ICMP request */
static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
{
- size_t i;
- size_t data_len = len - sizeof(struct icmp_echo_hdr);
+ size_t i;
+ size_t data_len = len - sizeof(struct icmp_echo_hdr);
- ICMPH_TYPE_SET(iecho, ICMP_ECHO);
- ICMPH_CODE_SET(iecho, 0);
- iecho->chksum = 0;
- iecho->id = PING_ID;
- iecho->seqno = htons(++ping_seq_num);
+ ICMPH_TYPE_SET(iecho, ICMP_ECHO);
+ ICMPH_CODE_SET(iecho, 0);
+ iecho->chksum = 0;
+ iecho->id = PING_ID;
+ iecho->seqno = htons(++ping_seq_num);
- /* fill the additional data buffer with some data */
- for(i = 0; i < data_len; i++)
- {
- ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
- }
+ /* fill the additional data buffer with some data */
+ for(i = 0; i < data_len; i++)
+ {
+ ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
+ }
- iecho->chksum = inet_chksum(iecho, len);
+ iecho->chksum = inet_chksum(iecho, len);
}
/* Ping using the socket ip */
-static err_t ping_send(int s, struct ip_addr *addr)
+static err_t ping_send(int s, struct ip_addr *addr, int size)
{
- int err;
- struct icmp_echo_hdr *iecho;
- struct sockaddr_in to;
- size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
- LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
+ int err;
+ struct icmp_echo_hdr *iecho;
+ struct sockaddr_in to;
+ size_t ping_size = sizeof(struct icmp_echo_hdr) + size;
+ LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
- iecho = rt_malloc(ping_size);
- if (iecho == RT_NULL)
- {
- return ERR_MEM;
- }
+ iecho = rt_malloc(ping_size);
+ if (iecho == RT_NULL)
+ {
+ return ERR_MEM;
+ }
- ping_prepare_echo(iecho, (u16_t)ping_size);
+ ping_prepare_echo(iecho, (u16_t)ping_size);
- to.sin_len = sizeof(to);
- to.sin_family = AF_INET;
- to.sin_addr.s_addr = addr->addr;
+ to.sin_len = sizeof(to);
+ to.sin_family = AF_INET;
+ to.sin_addr.s_addr = addr->addr;
- err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
- rt_free(iecho);
+ err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
+ rt_free(iecho);
- return (err ? ERR_OK : ERR_VAL);
+ return (err ? ERR_OK : ERR_VAL);
}
static void ping_recv(int s)
{
- char buf[64];
- int fromlen, len;
- struct sockaddr_in from;
- struct ip_hdr *iphdr;
- struct icmp_echo_hdr *iecho;
- struct _ip_addr *addr;
+ char buf[64];
+ int fromlen, len;
+ struct sockaddr_in from;
+ struct ip_hdr *iphdr;
+ struct icmp_echo_hdr *iecho;
+ struct _ip_addr *addr;
- while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0)
- {
- if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr)))
- {
- addr = (struct _ip_addr *)&(from.sin_addr);
- rt_kprintf("ping: recv %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0)
+ {
+ if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr)))
+ {
+ addr = (struct _ip_addr *)&(from.sin_addr);
+ rt_kprintf("ping: recv %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
- iphdr = (struct ip_hdr *)buf;
- iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4));
- if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num)))
- {
- return;
- }
- else
- {
- rt_kprintf("ping: drop\n");
- }
- }
- }
+ iphdr = (struct ip_hdr *)buf;
+ iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4));
+ if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num)))
+ {
+ return;
+ }
+ else
+ {
+ rt_kprintf("ping: drop\n");
+ }
+ }
+ }
- if (len <= 0)
- {
- rt_kprintf("ping: timeout\n");
- }
+ if (len <= 0)
+ {
+ rt_kprintf("ping: timeout\n");
+ }
}
rt_err_t ping(char* target, rt_uint32_t time, rt_size_t size)
{
- int s;
- int timeout = PING_RCV_TIMEO;
- struct ip_addr ping_target;
- rt_uint32_t send_time;
- struct _ip_addr
- {
- rt_uint8_t addr0, addr1, addr2, addr3;
- } *addr;
+ int s;
+ int timeout = PING_RCV_TIMEO;
+ struct ip_addr ping_target;
+ rt_uint32_t send_time;
+ struct _ip_addr
+ {
+ rt_uint8_t addr0, addr1, addr2, addr3;
+ } *addr;
send_time = 0;
- if (inet_aton(target, (struct in_addr*)&ping_target) == 0) return -RT_ERROR;
- addr = (struct _ip_addr*)&ping_target;
+ if(size == 0)
+ size = PING_DATA_SIZE;
- if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0)
- {
- rt_kprintf("create socket failled\n");
- return -RT_ERROR;
- }
+ if (inet_aton(target, (struct in_addr*)&ping_target) == 0) return -RT_ERROR;
+ addr = (struct _ip_addr*)&ping_target;
- lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+ if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0)
+ {
+ rt_kprintf("create socket failled\n");
+ return -RT_ERROR;
+ }
- while (1)
- {
- if (ping_send(s, &ping_target) == ERR_OK)
- {
- rt_kprintf("ping: send %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
- ping_recv(s);
- }
- else
- {
- rt_kprintf("ping: send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
- }
+ lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
- send_time ++;
- if (send_time >= time) break; /* send ping times reached, stop */
+ while (1)
+ {
+ if (ping_send(s, &ping_target, size) == ERR_OK)
+ {
+ rt_kprintf("ping: send %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ ping_recv(s);
+ }
+ else
+ {
+ rt_kprintf("ping: send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ }
- rt_thread_delay(PING_DELAY); /* take a delay */
- }
+ send_time ++;
+ if (send_time >= time) break; /* send ping times reached, stop */
- return RT_EOK;
+ rt_thread_delay(PING_DELAY); /* take a delay */
+ }
+
+ lwip_close(s);
+
+ return RT_EOK;
}
#ifdef RT_USING_FINSH
#include <finsh.h>
diff --git a/components/net/lwip-1.4.1/src/arch/sys_arch.c b/components/net/lwip-1.4.1/src/arch/sys_arch.c
index ee1d952410..287c861f04 100644
--- a/components/net/lwip-1.4.1/src/arch/sys_arch.c
+++ b/components/net/lwip-1.4.1/src/arch/sys_arch.c
@@ -29,6 +29,11 @@
#include <string.h>
+/*
+ * Initialize the network interface device
+ *
+ * @return the operation status, ERR_OK on OK, ERR_IF on error
+ */
static err_t netif_device_init(struct netif *netif)
{
struct eth_device *ethif;
@@ -53,7 +58,9 @@ static err_t netif_device_init(struct netif *netif)
return ERR_IF;
}
-
+/*
+ * Initialize the ethernetif layer and set network interface device up
+ */
static void tcpip_init_done_callback(void *arg)
{
rt_device_t device;
@@ -108,7 +115,7 @@ static void tcpip_init_done_callback(void *arg)
netif_set_up(ethif->netif);
}
-#ifdef LWIP_NETIF_LINK_CALLBACK
+#if LWIP_NETIF_LINK_CALLBACK
netif_set_link_up(ethif->netif);
#endif
@@ -182,6 +189,11 @@ void lwip_sys_init(void)
lwip_system_init();
}
+/*
+ * Create a new semaphore
+ *
+ * @return the operation status, ERR_OK on OK; others on error
+ */
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{
static unsigned short counter = 0;
@@ -204,17 +216,31 @@ err_t sys_sem_new(sys_sem_t *sem, u8_t count)
}
}
+/*
+ * Deallocate a semaphore
+ */
void sys_sem_free(sys_sem_t *sem)
{
RT_DEBUG_NOT_IN_INTERRUPT;
rt_sem_delete(*sem);
}
+/*
+ * Signal a semaphore
+ */
void sys_sem_signal(sys_sem_t *sem)
{
rt_sem_release(*sem);
}
+/*
+ * Block the thread while waiting for the semaphore to be signaled
+ *
+ * @return If the timeout argument is non-zero, it will return the number of milliseconds
+ * spent waiting for the semaphore to be signaled; If the semaphore isn't signaled
+ * within the specified time, it will return SYS_ARCH_TIMEOUT; If the thread doesn't
+ * wait for the semaphore, it will return zero
+ */
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{
rt_err_t ret;
@@ -354,6 +380,11 @@ void sys_mutex_set_invalid(sys_mutex_t *mutex)
/* ====================== Mailbox ====================== */
+/*
+ * Create an empty mailbox for maximum "size" elements
+ *
+ * @return the operation status, ERR_OK on OK; others on error
+ */
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{
static unsigned short counter = 0;
@@ -376,6 +407,9 @@ err_t sys_mbox_new(sys_mbox_t *mbox, int size)
return ERR_MEM;
}
+/*
+ * Deallocate a mailbox
+ */
void sys_mbox_free(sys_mbox_t *mbox)
{
RT_DEBUG_NOT_IN_INTERRUPT;
@@ -399,6 +433,11 @@ void sys_mbox_post(sys_mbox_t *mbox, void *msg)
return;
}
+/*
+ * Try to post the "msg" to the mailbox
+ *
+ * @return return ERR_OK if the "msg" is posted, ERR_MEM if the mailbox is full
+ */
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
{
if (rt_mb_send(*mbox, (rt_uint32_t)msg) == RT_EOK)
@@ -502,6 +541,11 @@ void sys_mbox_set_invalid(sys_mbox_t *mbox)
/* ====================== System ====================== */
+/*
+ * Start a new thread named "name" with priority "prio" that will begin
+ * its execution in the function "thread()". The "arg" argument will be
+ * passed as an argument to the thread() function
+ */
sys_thread_t sys_thread_new(const char *name,
lwip_thread_fn thread,
void *arg,
diff --git a/components/net/lwip-1.4.1/src/include/netif/ethernetif.h b/components/net/lwip-1.4.1/src/include/netif/ethernetif.h
index 53dacf2270..2019df7017 100644
--- a/components/net/lwip-1.4.1/src/include/netif/ethernetif.h
+++ b/components/net/lwip-1.4.1/src/include/netif/ethernetif.h
@@ -5,7 +5,11 @@
#include <rtthread.h>
#define NIOCTL_GADDR 0x01
+#ifndef RT_LWIP_ETH_MTU
#define ETHERNET_MTU 1500
+#else
+#define ETHERNET_MTU RT_LWIP_ETH_MTU
+#endif
struct eth_device
{
diff --git a/components/net/lwip-1.4.1/src/lwipopts.h b/components/net/lwip-1.4.1/src/lwipopts.h
index 10cb7893a7..bff172e280 100644
--- a/components/net/lwip-1.4.1/src/lwipopts.h
+++ b/components/net/lwip-1.4.1/src/lwipopts.h
@@ -38,8 +38,9 @@
#define LWIP_PLATFORM_BYTESWAP 0
#define BYTE_ORDER LITTLE_ENDIAN
-/* Enable SO_RCVTIMEO processing. */
+/* Enable SO_RCVTIMEO/LWIP_SO_SNDTIMEO processing. */
#define LWIP_SO_RCVTIMEO 1
+#define LWIP_SO_SNDTIMEO 1
/* #define RT_LWIP_DEBUG */
@@ -117,6 +118,8 @@
/* the number of simultaneously queued TCP */
#ifdef RT_LWIP_TCP_SEG_NUM
+#define MEMP_NUM_TCP_SEG RT_LWIP_TCP_SEG_NUM
+#else
#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN
#endif
@@ -135,12 +138,12 @@
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#ifdef RT_LWIP_PBUF_NUM
-#define PBUF_POOL_SIZE RT_LWIP_PBUF_NUM
+#define PBUF_POOL_SIZE RT_LWIP_PBUF_NUM
#endif
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#ifdef RT_LWIP_PBUF_POOL_BUFSIZE
-#define PBUF_POOL_BUFSIZE RT_LWIP_PBUF_POOL_BUFSIZE
+#define PBUF_POOL_BUFSIZE RT_LWIP_PBUF_POOL_BUFSIZE
#endif
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
@@ -176,7 +179,7 @@
/* TCP sender buffer space (bytes). */
#ifdef RT_LWIP_TCP_SND_BUF
-#define TCP_SND_BUF RT_LWIP_TCP_SND_BUF
+#define TCP_SND_BUF RT_LWIP_TCP_SND_BUF
#else
#define TCP_SND_BUF (TCP_MSS * 2)
#endif
@@ -230,10 +233,15 @@
/* IP reassembly and segmentation.These are orthogonal even
* if they both deal with IP fragments */
-#define IP_REASSEMBLY 0
+#ifdef RT_LWIP_REASSEMBLY_FRAG
+#define IP_REASSEMBLY 1
+#define IP_FRAG 1
#define IP_REASS_MAX_PBUFS 10
#define MEMP_NUM_REASSDATA 10
+#else
+#define IP_REASSEMBLY 0
#define IP_FRAG 0
+#endif
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
@@ -307,7 +315,7 @@
* in this file.
*/
#ifdef RT_LWIP_PPPOE
-#define PPPOE_SUPPORT 1
+#define PPPOE_SUPPORT 1
#else
#define PPPOE_SUPPORT 0
#endif
@@ -315,7 +323,7 @@
#ifdef RT_LWIP_PPPOS
#define PPPOS_SUPPORT 1
#else
-#define PPPOS_SUPPORT 0
+#define PPPOS_SUPPORT 0
#endif
#define PAP_SUPPORT 1 /* Set > 0 for PAP. */
diff --git a/components/net/lwip-1.4.1/src/netif/ethernetif.c b/components/net/lwip-1.4.1/src/netif/ethernetif.c
index 2853fdcd7c..ab7743290a 100644
--- a/components/net/lwip-1.4.1/src/netif/ethernetif.c
+++ b/components/net/lwip-1.4.1/src/netif/ethernetif.c
@@ -67,6 +67,7 @@
#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL)
#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL)
+#ifndef LWIP_NO_TX_THREAD
/**
* Tx message structure for Ethernet interface
*/
@@ -85,7 +86,9 @@ static char eth_tx_thread_stack[512];
static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4];
static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE];
#endif
+#endif
+#ifndef LWIP_NO_RX_THREAD
static struct rt_mailbox eth_rx_thread_mb;
static struct rt_thread eth_rx_thread;
#ifndef RT_LWIP_ETHTHREAD_PRIORITY
@@ -97,12 +100,15 @@ static char eth_rx_thread_stack[1024];
static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4];
static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE];
#endif
+#endif
static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
{
+#ifndef LWIP_NO_TX_THREAD
struct eth_tx_msg msg;
struct eth_device* enetif;
+ RT_ASSERT(netif != RT_NULL);
enetif = (struct eth_device*)netif->state;
/* send a message to eth tx thread */
@@ -113,7 +119,17 @@ static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
/* waiting for ack */
rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER);
}
+#else
+ struct eth_device* enetif;
+ RT_ASSERT(netif != RT_NULL);
+ enetif = (struct eth_device*)netif->state;
+
+ if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK)
+ {
+ return ERR_IF;
+ }
+#endif
return ERR_OK;
}
@@ -241,6 +257,7 @@ rt_err_t eth_device_init(struct eth_device * dev, char *name)
return eth_device_init_with_flag(dev, name, flags);
}
+#ifndef LWIP_NO_RX_THREAD
rt_err_t eth_device_ready(struct eth_device* dev)
{
if (dev->netif)
@@ -267,7 +284,20 @@ rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up)
/* post message to ethernet thread */
return rt_mb_send(&eth_rx_thread_mb, (rt_uint32_t)dev);
}
+#else
+/* NOTE: please not use it in interrupt when no RxThread exist */
+rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up)
+{
+ if (up == RT_TRUE)
+ netifapi_netif_set_link_up(dev->netif);
+ else
+ netifapi_netif_set_link_down(dev->netif);
+
+ return RT_EOK;
+}
+#endif
+#ifndef LWIP_NO_TX_THREAD
/* Ethernet Tx Thread */
static void eth_tx_thread_entry(void* parameter)
{
@@ -297,7 +327,9 @@ static void eth_tx_thread_entry(void* parameter)
}
}
}
+#endif
+#ifndef LWIP_NO_RX_THREAD
/* Ethernet Rx Thread */
static void eth_rx_thread_entry(void* parameter)
{
@@ -349,13 +381,15 @@ static void eth_rx_thread_entry(void* parameter)
}
}
}
+#endif
int eth_system_device_init(void)
{
rt_err_t result = RT_EOK;
- /* initialize Rx thread.
- * initialize mailbox and create Ethernet Rx thread */
+ /* initialize Rx thread. */
+#ifndef LWIP_NO_RX_THREAD
+ /* initialize mailbox and create Ethernet Rx thread */
result = rt_mb_init(&eth_rx_thread_mb, "erxmb",
&eth_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/4,
RT_IPC_FLAG_FIFO);
@@ -367,8 +401,10 @@ int eth_system_device_init(void)
RT_ASSERT(result == RT_EOK);
result = rt_thread_startup(&eth_rx_thread);
RT_ASSERT(result == RT_EOK);
+#endif
/* initialize Tx thread */
+#ifndef LWIP_NO_TX_THREAD
/* initialize mailbox and create Ethernet Tx thread */
result = rt_mb_init(&eth_tx_thread_mb, "etxmb",
&eth_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/4,
@@ -382,8 +418,9 @@ int eth_system_device_init(void)
result = rt_thread_startup(&eth_tx_thread);
RT_ASSERT(result == RT_EOK);
-
- return 0;
+#endif
+
+ return (int)result;
}
INIT_DEVICE_EXPORT(eth_system_device_init);
diff --git a/components/net/lwip/apps/ping.c b/components/net/lwip/apps/ping.c
index d3c3dd399b..1e595dce61 100644
--- a/components/net/lwip/apps/ping.c
+++ b/components/net/lwip/apps/ping.c
@@ -39,135 +39,140 @@
static u16_t ping_seq_num;
struct _ip_addr
{
- rt_uint8_t addr0, addr1, addr2, addr3;
+ rt_uint8_t addr0, addr1, addr2, addr3;
};
/** Prepare a echo ICMP request */
static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
{
- size_t i;
- size_t data_len = len - sizeof(struct icmp_echo_hdr);
+ size_t i;
+ size_t data_len = len - sizeof(struct icmp_echo_hdr);
- ICMPH_TYPE_SET(iecho, ICMP_ECHO);
- ICMPH_CODE_SET(iecho, 0);
- iecho->chksum = 0;
- iecho->id = PING_ID;
- iecho->seqno = htons(++ping_seq_num);
+ ICMPH_TYPE_SET(iecho, ICMP_ECHO);
+ ICMPH_CODE_SET(iecho, 0);
+ iecho->chksum = 0;
+ iecho->id = PING_ID;
+ iecho->seqno = htons(++ping_seq_num);
- /* fill the additional data buffer with some data */
- for(i = 0; i < data_len; i++)
- {
- ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
- }
+ /* fill the additional data buffer with some data */
+ for(i = 0; i < data_len; i++)
+ {
+ ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
+ }
- iecho->chksum = inet_chksum(iecho, len);
+ iecho->chksum = inet_chksum(iecho, len);
}
/* Ping using the socket ip */
-static err_t ping_send(int s, struct ip_addr *addr)
+static err_t ping_send(int s, struct ip_addr *addr, int size)
{
- int err;
- struct icmp_echo_hdr *iecho;
- struct sockaddr_in to;
- size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
- LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
+ int err;
+ struct icmp_echo_hdr *iecho;
+ struct sockaddr_in to;
+ size_t ping_size = sizeof(struct icmp_echo_hdr) + size;
+ LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
- iecho = rt_malloc(ping_size);
- if (iecho == RT_NULL)
- {
- return ERR_MEM;
- }
+ iecho = rt_malloc(ping_size);
+ if (iecho == RT_NULL)
+ {
+ return ERR_MEM;
+ }
- ping_prepare_echo(iecho, (u16_t)ping_size);
+ ping_prepare_echo(iecho, (u16_t)ping_size);
- to.sin_len = sizeof(to);
- to.sin_family = AF_INET;
- to.sin_addr.s_addr = addr->addr;
+ to.sin_len = sizeof(to);
+ to.sin_family = AF_INET;
+ to.sin_addr.s_addr = addr->addr;
- err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
- rt_free(iecho);
+ err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
+ rt_free(iecho);
- return (err ? ERR_OK : ERR_VAL);
+ return (err ? ERR_OK : ERR_VAL);
}
static void ping_recv(int s)
{
- char buf[64];
- int fromlen, len;
- struct sockaddr_in from;
- struct ip_hdr *iphdr;
- struct icmp_echo_hdr *iecho;
- struct _ip_addr *addr;
+ char buf[64];
+ int fromlen, len;
+ struct sockaddr_in from;
+ struct ip_hdr *iphdr;
+ struct icmp_echo_hdr *iecho;
+ struct _ip_addr *addr;
- while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0)
- {
- if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr)))
- {
- addr = (struct _ip_addr *)&(from.sin_addr);
- rt_kprintf("ping: recv %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0)
+ {
+ if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr)))
+ {
+ addr = (struct _ip_addr *)&(from.sin_addr);
+ rt_kprintf("ping: recv %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
- iphdr = (struct ip_hdr *)buf;
- iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4));
- if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num)))
- {
- return;
- }
- else
- {
- rt_kprintf("ping: drop\n");
- }
- }
- }
+ iphdr = (struct ip_hdr *)buf;
+ iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4));
+ if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num)))
+ {
+ return;
+ }
+ else
+ {
+ rt_kprintf("ping: drop\n");
+ }
+ }
+ }
- if (len <= 0)
- {
- rt_kprintf("ping: timeout\n");
- }
+ if (len <= 0)
+ {
+ rt_kprintf("ping: timeout\n");
+ }
}
rt_err_t ping(char* target, rt_uint32_t time, rt_size_t size)
{
- int s;
- int timeout = PING_RCV_TIMEO;
- struct ip_addr ping_target;
- rt_uint32_t send_time;
- struct _ip_addr
- {
- rt_uint8_t addr0, addr1, addr2, addr3;
- } *addr;
+ int s;
+ int timeout = PING_RCV_TIMEO;
+ struct ip_addr ping_target;
+ rt_uint32_t send_time;
+ struct _ip_addr
+ {
+ rt_uint8_t addr0, addr1, addr2, addr3;
+ } *addr;
send_time = 0;
- if (inet_aton(target, (struct in_addr*)&ping_target) == 0) return -RT_ERROR;
- addr = (struct _ip_addr*)&ping_target;
+ if(size == 0)
+ size = PING_DATA_SIZE;
- if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0)
- {
- rt_kprintf("create socket failled\n");
- return -RT_ERROR;
- }
+ if (inet_aton(target, (struct in_addr*)&ping_target) == 0) return -RT_ERROR;
+ addr = (struct _ip_addr*)&ping_target;
- lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+ if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0)
+ {
+ rt_kprintf("create socket failled\n");
+ return -RT_ERROR;
+ }
- while (1)
- {
- if (ping_send(s, &ping_target) == ERR_OK)
- {
- rt_kprintf("ping: send %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
- ping_recv(s);
- }
- else
- {
- rt_kprintf("ping: send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
- }
+ lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
- send_time ++;
- if (send_time >= time) break; /* send ping times reached, stop */
+ while (1)
+ {
+ if (ping_send(s, &ping_target, size) == ERR_OK)
+ {
+ rt_kprintf("ping: send %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ ping_recv(s);
+ }
+ else
+ {
+ rt_kprintf("ping: send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ }
- rt_thread_delay(PING_DELAY); /* take a delay */
- }
+ send_time ++;
+ if (send_time >= time) break; /* send ping times reached, stop */
- return RT_EOK;
+ rt_thread_delay(PING_DELAY); /* take a delay */
+ }
+
+ lwip_close(s);
+
+ return RT_EOK;
}
#ifdef RT_USING_FINSH
#include <finsh.h>
diff --git a/components/pthreads/mqueue.c b/components/pthreads/mqueue.c
index c1303ae6b1..7b669dc367 100644
--- a/components/pthreads/mqueue.c
+++ b/components/pthreads/mqueue.c
@@ -119,6 +119,7 @@ mqd_t mq_open(const char *name, int oflag, ...)
{
mqd_t mqdes;
va_list arg;
+ mode_t mode;
struct mq_attr *attr = RT_NULL;
/* lock posix mqueue list */
@@ -128,6 +129,8 @@ mqd_t mq_open(const char *name, int oflag, ...)
if (oflag & O_CREAT)
{
va_start(arg, oflag);
+ mode = (mode_t)va_arg(arg, unsigned int);
+ mode = mode;
attr = (struct mq_attr *)va_arg(arg, struct mq_attr *);
va_end(arg);
diff --git a/components/pthreads/pthread_cond.c b/components/pthreads/pthread_cond.c
index e5342dd775..25628fc2b3 100644
--- a/components/pthreads/pthread_cond.c
+++ b/components/pthreads/pthread_cond.c
@@ -98,7 +98,11 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
rt_snprintf(cond_name, sizeof(cond_name), "cond%02d", cond_num++);
- cond->attr = *attr;
+ if (attr == RT_NULL) /* use default value */
+ cond->attr = PTHREAD_PROCESS_PRIVATE;
+ else
+ cond->attr = *attr;
+
result = rt_sem_init(&cond->sem, cond_name, 0, RT_IPC_FLAG_FIFO);
if (result != RT_EOK)
return EINVAL;
diff --git a/components/pthreads/semaphore.c b/components/pthreads/semaphore.c
index 726246c95f..ae69e0d1bc 100644
--- a/components/pthreads/semaphore.c
+++ b/components/pthreads/semaphore.c
@@ -224,6 +224,7 @@ sem_t *sem_open(const char *name, int oflag, ...)
{
sem_t* sem;
va_list arg;
+ mode_t mode;
unsigned int value;
sem = RT_NULL;
@@ -233,6 +234,7 @@ sem_t *sem_open(const char *name, int oflag, ...)
if (oflag & O_CREAT)
{
va_start(arg, oflag);
+ mode = (mode_t) va_arg( arg, unsigned int); mode = mode;
value = va_arg( arg, unsigned int);
va_end(arg);
diff --git a/components/utilities/ymodem/ymodem.c b/components/utilities/ymodem/ymodem.c
index fdd1950cc0..f5ebeab832 100644
--- a/components/utilities/ymodem/ymodem.c
+++ b/components/utilities/ymodem/ymodem.c
@@ -70,18 +70,23 @@ static enum rym_code _rym_read_code(
struct rym_ctx *ctx,
rt_tick_t timeout)
{
- /* consume the available sem and read the data in buffer if possible */
- while (rt_sem_trytake(&ctx->sem) == RT_EOK)
- ;
+ /* Fast path */
if (rt_device_read(ctx->dev, 0, ctx->buf, 1) == 1)
return *ctx->buf;
- /* no data yet, wait for one */
- if (rt_sem_take(&ctx->sem, timeout) != RT_EOK)
- return RYM_CODE_NONE;
- /* read one */
- if (rt_device_read(ctx->dev, 0, ctx->buf, 1) == 1)
- return *ctx->buf;
- return RYM_CODE_NONE;
+
+ /* Slow path */
+ do {
+ rt_size_t rsz;
+
+ /* No data yet, wait for one */
+ if (rt_sem_take(&ctx->sem, timeout) != RT_EOK)
+ return RYM_CODE_NONE;
+
+ /* Try to read one */
+ rsz = rt_device_read(ctx->dev, 0, ctx->buf, 1);
+ if (rsz == 1)
+ return *ctx->buf;
+ } while (1);
}
/* the caller should at least alloc _RYM_STX_PKG_SZ buffer */
diff --git a/components/utilities/ymodem/ymodem.h b/components/utilities/ymodem/ymodem.h
index daed61d15f..43ee6f5c10 100644
--- a/components/utilities/ymodem/ymodem.h
+++ b/components/utilities/ymodem/ymodem.h
@@ -52,7 +52,7 @@ enum rym_code {
#endif
/* how many ticks between two handshake code. */
#ifndef RYM_CHD_INTV_TICK
-#define RYM_CHD_INTV_TICK (RT_TICK_PER_SECOND / 4)
+#define RYM_CHD_INTV_TICK (RT_TICK_PER_SECOND * 3)
#endif
enum rym_stage {