diff --git a/ChangeLog b/ChangeLog index 229e496b8ac..209b0409452 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10797,10 +10797,13 @@ * arch/arm/src/samv7: Add the framework for an SPI slave drvier. This driver has a lot of missing logic on initial commit (2015-08-09). * arch/arm/src/samv7: Basic, no-DMA SPI slave driver is in place - (2015-080=-10). + (2015-08-10). * fs/vfs/epoll.c and include/sys/epoll.h: Add a very simple epoll layer just around poll calls. To satisfy build app requirements. From Anton - D. Kachalov. + D. Kachalov (2015-08-10). * drivers/mtd/ramtron.c: Update to include supportf for newer - RAMTRON parts. From David Sidrane. - + RAMTRON parts. From David Sidrane (2015-08-10). + * Networking: Allow receipt of empty UDP packets. From Max Neklyudov + (2015-08-11). + * drivers/sensors/mb7040.c and include/nuttx/sensors/mb7040.h: Add + support Added MB7040 sonar. From Paul Alexander Patience (2015-08-07). diff --git a/arch b/arch index 6190d664666..56596fd0001 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 6190d664666b19580969c4e620646ef4e54f0182 +Subproject commit 56596fd0001c1906600d7806e67e92040ed99183 diff --git a/configs b/configs index ac4035687c8..d22ff0b3ff3 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit ac4035687c824bb4a573e06feb017cb4f3ce7626 +Subproject commit d22ff0b3ff36cd5e324538b74b8064edaa3b63d8 diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 2fb7dd3762d..eb557252e6b 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -387,7 +387,44 @@ * upon it. * * A typical DMA data transfer processes as follows: - * To be provided + * To be provided -- I do not have a design in mind to support DMA on the + * Slave side. The design might be very complex because: + * + * 1) You need DMA buffers of fixed size, but you cannot know the size of a + * transfer in advance, it could be much larger than your buffer or much + * smaller. The DMA would fail in either case. + * + * 2) You cannot setup the DMA before the transfer. In most SPI protocols, + * the first word send is a command to read or write something following + * by a sequence of transfers to implement the write. So you have very, + * very limited time window to setup the correct DMA to respond to the + * command. I am not certain that it can be done reliably. + * + * Inserting dummy words into the protocol between the first command word + * and the remaining data transfer could allow time to set up the DMA. + * + * 3) I mentioned that you do not know the size of the transfer in advance. + * If you set up the DMA to terminate to soon, then you lose the last part + * of the transfer. If you set the DMA up to be too large, then you will + * get no indication when the transfer completes. + * + * The chip select going high would be one possibility to detect the end + * of a transfer. You could cancel a DMA in progress if the CS changes, + * but I do not know if that would work. If there is only one device on + * the SPI bus, then most board designs will save a pin and simply tie CS + * to ground. So the CS is not always a reliable indicator of when the + * transfer completes. + * + * 4) The option is to use a timer but that would really slow down the + * transfers if each DMA has to end with a timeout. It would be faster + * non-DMA transfers. + * + * If the device as a very restricted protocol, like just register reads + * and writes, then it might possible to implement DMA. However, that + * solution would not be general and probably not an appropriate part of + * a general OS. But if the interface is unpredictable, such as reading/ + * variable amounts of data from FLASH, there is more risk. A general + * solution might not be possible. */ enum spi_smode_e diff --git a/net/iob/iob_copyout.c b/net/iob/iob_copyout.c index 300b63df81f..e7b682651c2 100644 --- a/net/iob/iob_copyout.c +++ b/net/iob/iob_copyout.c @@ -101,6 +101,12 @@ int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob, { offset -= iob->io_len; iob = iob->io_flink; + if (iob == NULL) + { + /* We have no requested data in iob chain */ + + return 0; + } } /* Then loop until all of the I/O data is copied to the user buffer */ diff --git a/net/socket/recvfrom.c b/net/socket/recvfrom.c index cf26072ac98..32b2067ffc0 100644 --- a/net/socket/recvfrom.c +++ b/net/socket/recvfrom.c @@ -101,7 +101,7 @@ struct recvfrom_s uint8_t *rf_buffer; /* Pointer to receive buffer */ FAR struct sockaddr *rf_from; /* Address of sender */ FAR socklen_t *rf_fromlen; /* Number of bytes allocated for address of sender */ - size_t rf_recvlen; /* The received length */ + ssize_t rf_recvlen; /* The received length */ int rf_result; /* Success:OK, failure:negated errno */ }; #endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ @@ -404,8 +404,9 @@ static inline void recvfrom_udpreadahead(struct recvfrom_s *pstate) * buffer. */ - if ((iob = iob_peek_queue(&conn->readahead)) != NULL && - pstate->rf_buflen > 0) + pstate->rf_recvlen = -1; + + if ((iob = iob_peek_queue(&conn->readahead)) != NULL) { FAR struct iob_s *tmp; uint8_t src_addr_size; @@ -445,16 +446,23 @@ static inline void recvfrom_udpreadahead(struct recvfrom_s *pstate) } } - recvlen = iob_copyout(pstate->rf_buffer, iob, pstate->rf_buflen, - src_addr_size + sizeof(uint8_t)); + if (pstate->rf_buflen > 0) + { + recvlen = iob_copyout(pstate->rf_buffer, iob, pstate->rf_buflen, + src_addr_size + sizeof(uint8_t)); - nllvdbg("Received %d bytes (of %d)\n", recvlen, iob->io_pktlen); + nllvdbg("Received %d bytes (of %d)\n", recvlen, iob->io_pktlen); - /* Update the accumulated size of the data read */ + /* Update the accumulated size of the data read */ - pstate->rf_recvlen += recvlen; - pstate->rf_buffer += recvlen; - pstate->rf_buflen -= recvlen; + pstate->rf_recvlen = recvlen; + pstate->rf_buffer += recvlen; + pstate->rf_buflen -= recvlen; + } + else + { + pstate->rf_recvlen = 0; + } out: /* Remove the I/O buffer chain from the head of the read-ahead @@ -1482,7 +1490,7 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, * something was received (already in 'ret'); EAGAIN if not. */ - if (ret <= 0) + if (ret < 0) { /* Nothing was received */ diff --git a/net/udp/udp_callback.c b/net/udp/udp_callback.c index f99aa2eac1d..1f09ede3138 100644 --- a/net/udp/udp_callback.c +++ b/net/udp/udp_callback.c @@ -200,19 +200,23 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev, FAR struct udp_con return 0; } - /* Copy the new appdata into the I/O buffer chain */ - - ret = iob_trycopyin(iob, buffer, buflen, src_addr_size + sizeof(uint8_t), - true); - if (ret < 0) + if (buflen > 0) { - /* On a failure, iob_trycopyin return a negated error value but does - * not free any I/O buffers. - */ + /* Copy the new appdata into the I/O buffer chain */ - nlldbg("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret); - (void)iob_free_chain(iob); - return 0; + ret = iob_trycopyin(iob, buffer, buflen, + src_addr_size + sizeof(uint8_t), true); + if (ret < 0) + { + /* On a failure, iob_trycopyin return a negated error value but + * does not free any I/O buffers. + */ + + nlldbg("ERROR: Failed to add data to the I/O buffer chain: %d\n", + ret); + (void)iob_free_chain(iob); + return 0; + } } /* Add the new I/O buffer chain to the tail of the read-ahead queue */ @@ -243,6 +247,11 @@ net_dataevent(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, uint16_t flags) { uint16_t ret; +#ifdef CONFIG_NET_UDP_READAHEAD + uint8_t *buffer = dev->d_appdata; + int buflen = dev->d_len; + uint16_t recvlen; +#endif ret = (flags & ~UDP_NEWDATA); @@ -250,35 +259,26 @@ net_dataevent(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, * can have zero-length with UDP_NEWDATA set just to cause an ACK). */ - if (dev->d_len > 0) - { + nllvdbg("No receive on connection\n"); + #ifdef CONFIG_NET_UDP_READAHEAD - uint8_t *buffer = dev->d_appdata; - int buflen = dev->d_len; - uint16_t recvlen; + /* Save as the packet data as in the read-ahead buffer. NOTE that + * partial packets will not be buffered. + */ + + recvlen = udp_datahandler(dev, conn, buffer, buflen); + if (recvlen < buflen) #endif - - nllvdbg("No receive on connection\n"); - -#ifdef CONFIG_NET_UDP_READAHEAD - /* Save as the packet data as in the read-ahead buffer. NOTE that - * partial packets will not be buffered. + { + /* There is no handler to receive new data and there are no free + * read-ahead buffers to retain the data -- drop the packet. */ - recvlen = udp_datahandler(dev, conn, buffer, buflen); - if (recvlen < buflen) -#endif - { - /* There is no handler to receive new data and there are no free - * read-ahead buffers to retain the data -- drop the packet. - */ + nllvdbg("Dropped %d bytes\n", dev->d_len); - nllvdbg("Dropped %d bytes\n", dev->d_len); - - #ifdef CONFIG_NET_STATISTICS - g_netstats.udp.drop++; +#ifdef CONFIG_NET_STATISTICS + g_netstats.udp.drop++; #endif - } } /* In any event, the new data has now been handled */ diff --git a/tools/configure.sh b/tools/configure.sh index 2de790506e3..3ee734d6e9f 100755 --- a/tools/configure.sh +++ b/tools/configure.sh @@ -144,7 +144,7 @@ winnative=`grep CONFIG_WINDOWS_NATIVE= "${src_config}" | cut -d'=' -f2` defappdir=y if [ -z "${appdir}" ]; then quoted=`grep "^CONFIG_APPS_DIR=" "${src_config}" | cut -d'=' -f2` - if [ ! -z "${appdir}" ]; then + if [ ! -z "${quoted}" ]; then appdir=`echo ${quoted} | sed -e "s/\"//g"` defappdir=n fi @@ -165,7 +165,6 @@ if [ -z "${appdir}" ]; then if [ -d "${TOPDIR}/../apps" ]; then appdir="../apps" - else # Check for a versioned apps/ directory