Merged nuttx/nuttx into master

This commit is contained in:
ziggurat29 2016-07-13 09:35:54 -05:00
commit c46b3e869e
13 changed files with 1295 additions and 521 deletions

1
TODO
View File

@ -937,6 +937,7 @@ o Network (net/, drivers/net)
LM3S NO NO
TM4C YES YES
eZ80 NO NO
Kinetis YES YES (not tested)
LPC17xx YES YES (not tested)
LPC43xx YES YES (not tested)
DMxxx NIC NO NO

View File

@ -548,18 +548,27 @@ config KINETIS_ENETNTXBUFFERS
Number of Ethernet Tx buffers to use. The size of one buffer is
determined by NET_BUFSIZE
config KINETIS_ENETPHYADDR
int "PHY address"
default 1
---help---
MII/RMII address of the PHY
config KINETIS_ENETUSEMII
bool "Use MII interface"
default n
---help---
The the MII PHY interface. Default: Use RMII interface
config KINETIS_ENET_MDIOPULLUP
bool "MDIO pull-up"
default n
---help---
If there is no on-board pull-up resister on the MII/RMII MDIO line,
then this option may be selected in order to configure an internal
pull-up on MDIO.
config KINETIS_ENET_NORXER
bool "Suppress RXER"
default n
---help---
If selected, then the MII/RMII RXER output will be configured as a
GPIO and pulled low.
endmenu # Kinetis Ethernet Configuration
menu "Kinetis SDHC Configuration"

View File

@ -83,12 +83,12 @@
#define PIN_FTM0_CH1_1 (PIN_ALT3 | PIN_PORTA | PIN4)
#define PIN_NMI (PIN_ALT7 | PIN_PORTA | PIN4)
#define PIN_FTM0_CH2_1 (PIN_ALT3 | PIN_PORTA | PIN5)
#if 0
#ifdef CONFIG_KINETIS_ENET_NORXER
# define PIN_RMII0_RXER (GPIO_PULLDOWN | PIN_PORTA | PIN5)
# define PIN_MII0_RXER (GPIO_PULLDOWN | PIN_PORTA | PIN5)
#else
# define PIN_RMII0_RXER (PIN_ALT4 | PIN_PORTA | PIN5)
# define PIN_MII0_RXER (PIN_ALT4 | PIN_PORTA | PIN5)
#else
# define PIN_RMII0_RXER (GPIO_PULLDOWN | PIN_PORTA | PIN5)
# define PIN_MII0_RXER (GPIO_PULLDOWN | PIN_PORTA | PIN5)
#endif
#define PIN_CMP2_OUT_1 (PIN_ALT5 | PIN_PORTA | PIN5)
#define PIN_I2S0_RX_BCLK_1 (PIN_ALT6 | PIN_PORTA | PIN5)
@ -174,7 +174,11 @@
#define PIN_TSI0_CH0 (PIN_ANALOG | PIN_PORTB | PIN0)
#define PIN_I2C0_SCL_1 (PIN_ALT2 | PIN_PORTB | PIN0)
#define PIN_FTM1_CH0_3 (PIN_ALT3 | PIN_PORTB | PIN0)
#define PIN_RMII0_MDIO (PIN_ALT4 | PIN_PORTB | PIN0)
#ifdef CONFIG_KINETIS_ENET_MDIOPULLUP
# define PIN_RMII0_MDIO (PIN_ALT4_PULLUP | PIN_PORTB | PIN0)
#else
# define PIN_RMII0_MDIO (PIN_ALT4 | PIN_PORTB | PIN0)
#endif
#define PIN_MII0_MDIO (PIN_ALT4 | PIN_PORTB | PIN0)
#define PIN_FTM1_QD_PHA_3 (PIN_ALT6 | PIN_PORTB | PIN0)
#define PIN_ADC0_SE9 (PIN_ANALOG | PIN_PORTB | PIN1)

View File

@ -398,14 +398,22 @@
#define PIN_MII0_COL (PIN_ALT4 | PIN_PORTA | PIN29)
#define PIN_MII0_CRS (PIN_ALT4 | PIN_PORTA | PIN27)
#define PIN_MII0_MDC (PIN_ALT4 | PIN_PORTB | PIN1)
#define PIN_MII0_MDIO (PIN_ALT4 | PIN_PORTB | PIN0)
#ifdef CONFIG_KINETIS_ENET_MDIOPULLUP
# define PIN_MII0_MDIO (PIN_ALT4_PULLUP | PIN_PORTB | PIN0)
#else
# define PIN_MII0_MDIO (PIN_ALT4 | PIN_PORTB | PIN0)
#endif
#define PIN_MII0_RXCLK (PIN_ALT4 | PIN_PORTA | PIN11)
#define PIN_MII0_RXD0 (PIN_ALT4 | PIN_PORTA | PIN13)
#define PIN_MII0_RXD1 (PIN_ALT4 | PIN_PORTA | PIN12)
#define PIN_MII0_RXD2 (PIN_ALT4 | PIN_PORTA | PIN10)
#define PIN_MII0_RXD3 (PIN_ALT4 | PIN_PORTA | PIN9)
#define PIN_MII0_RXDV (PIN_ALT4 | PIN_PORTA | PIN14)
#define PIN_MII0_RXER (PIN_ALT4 | PIN_PORTA | PIN5)
#ifdef CONFIG_KINETIS_ENET_NORXER
# define PIN_MII0_RXER (GPIO_PULLDOWN | PIN_PORTA | PIN5)
#else
# define PIN_MII0_RXER (PIN_ALT4 | PIN_PORTA | PIN5)
#endif
#define PIN_MII0_TXCLK (PIN_ALT4 | PIN_PORTA | PIN25)
#define PIN_MII0_TXD0 (PIN_ALT4 | PIN_PORTA | PIN16)
#define PIN_MII0_TXD1 (PIN_ALT4 | PIN_PORTA | PIN17)
@ -427,10 +435,18 @@
#define PIN_RMII0_CRS_DV (PIN_ALT4 | PIN_PORTA | PIN14)
#define PIN_RMII0_MDC (PIN_ALT4 | PIN_PORTB | PIN1)
#define PIN_RMII0_MDIO (PIN_ALT4 | PIN_PORTB | PIN0)
#ifdef CONFIG_KINETIS_ENET_MDIOPULLUP
# define PIN_RMII0_MDIO (PIN_ALT4_PULLUP | PIN_PORTB | PIN0)
#else
# define PIN_RMII0_MDIO (PIN_ALT4 | PIN_PORTB | PIN0)
#endif
#define PIN_RMII0_RXD0 (PIN_ALT4 | PIN_PORTA | PIN13)
#define PIN_RMII0_RXD1 (PIN_ALT4 | PIN_PORTA | PIN12)
#define PIN_RMII0_RXER (PIN_ALT4 | PIN_PORTA | PIN5)
#ifdef CONFIG_KINETIS_ENET_NORXER
# define PIN_RMII0_RXER (GPIO_PULLDOWN | PIN_PORTA | PIN5)
#else
# define PIN_RMII0_RXER (PIN_ALT4 | PIN_PORTA | PIN5)
#endif
#define PIN_RMII0_TXD0 (PIN_ALT4 | PIN_PORTA | PIN16)
#define PIN_RMII0_TXD1 (PIN_ALT4 | PIN_PORTA | PIN17)
#define PIN_RMII0_TXEN (PIN_ALT4 | PIN_PORTA | PIN15)

View File

@ -57,6 +57,10 @@
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#ifdef CONFIG_NET_PKT
# include <nuttx/net/pkt.h>
#endif
@ -76,6 +80,14 @@
* Pre-processor Definitions
****************************************************************************/
/* If processing is not done at the interrupt level, then high priority
* work queue support is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_HPWORK)
# error High priority work queue support is required
#endif
/* CONFIG_KINETIS_ENETNETHIFS determines the number of physical interfaces
* that will be supported.
*/
@ -92,13 +104,16 @@
# error "Need at least one RX buffer"
#endif
#define NENET_NBUFFERS (CONFIG_KINETIS_ENETNTXBUFFERS+CONFIG_KINETIS_ENETNRXBUFFERS)
#define NENET_NBUFFERS \
(CONFIG_KINETIS_ENETNTXBUFFERS+CONFIG_KINETIS_ENETNRXBUFFERS)
#ifndef CONFIG_NET_MULTIBUFFER
# error "CONFIG_NET_MULTIBUFFER is required in the configuration"
#endif
/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */
/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per
* second.
*/
#define KINETIS_WDDELAY (1*CLK_TCK)
@ -193,8 +208,12 @@ struct kinetis_driver_s
uint8_t txtail; /* The oldest busy TX descriptor */
uint8_t txhead; /* The next TX descriptor to use */
uint8_t rxtail; /* The next RX descriptor to use */
uint8_t phyaddr; /* Selected PHY address */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
struct enet_desc_s *txdesc; /* A pointer to the list of TX descriptor */
struct enet_desc_s *rxdesc; /* A pointer to the list of RX descriptors */
@ -251,22 +270,43 @@ static int kinetis_txpoll(struct net_driver_s *dev);
static void kinetis_receive(FAR struct kinetis_driver_s *priv);
static void kinetis_txdone(FAR struct kinetis_driver_s *priv);
static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_interrupt_work(FAR void *arg);
#endif
static int kinetis_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static void kinetis_txtimeout(int argc, uint32_t arg, ...);
static void kinetis_polltimer(int argc, uint32_t arg, ...);
static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_txtimeout_work(FAR void *arg);
#endif
static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_poll_work(FAR void *arg);
#endif
static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
static int kinetis_ifup(struct net_driver_s *dev);
static int kinetis_ifdown(struct net_driver_s *dev);
static inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_txavail_work(FAR void *arg);
#endif
static int kinetis_txavail(struct net_driver_s *dev);
#ifdef CONFIG_NET_IGMP
static int kinetis_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
static int kinetis_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
#endif
#ifdef CONFIG_NETDEV_PHY_IOCTL
static int kinetis_ioctl(struct net_driver_s *dev, int cmd, long arg);
#endif
@ -278,7 +318,7 @@ static int kinetis_writemii(struct kinetis_driver_s *priv, uint8_t phyaddr,
uint8_t regaddr, uint16_t data);
static int kinetis_readmii(struct kinetis_driver_s *priv, uint8_t phyaddr,
uint8_t regaddr, uint16_t *data);
static inline void kinetis_initphy(struct kinetis_driver_s *priv);
static inline int kinetis_initphy(struct kinetis_driver_s *priv);
/* Initialization */
@ -463,8 +503,8 @@ static int kinetis_transmit(FAR struct kinetis_driver_s *priv)
/* Setup the TX timeout watchdog (perhaps restarting the timer) */
(void)wd_start(priv->txtimeout, KINETIS_TXTIMEOUT, kinetis_txtimeout, 1,
(uint32_t)priv);
(void)wd_start(priv->txtimeout, KINETIS_TXTIMEOUT, kinetis_txtimeout_expiry, 1,
(wdparm_t)priv);
return OK;
}
@ -776,28 +816,25 @@ static void kinetis_txdone(FAR struct kinetis_driver_s *priv)
}
/****************************************************************************
* Function: kinetis_interrupt
* Function: kinetis_interrupt_process
*
* Description:
* Three interrupt sources will vector this this function:
* 1. Ethernet MAC transmit interrupt handler
* 2. Ethernet MAC receive interrupt handler
* 3.
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
*
* Parameters:
* irq - Number of the IRQ that generated the interrupt
* context - Interrupt register state save info (architecture-specific)
* priv - Reference to the driver state structure
*
* Returned Value:
* OK on success
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static int kinetis_interrupt(int irq, FAR void *context)
static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv)
{
register FAR struct kinetis_driver_s *priv = &g_enet[0];
uint32_t pending;
/* Get the set of unmasked, pending interrupt. */
@ -847,33 +884,130 @@ static int kinetis_interrupt(int irq, FAR void *context)
putreg32(ENET_RDAR, KINETIS_ENET_RDAR);
}
}
/****************************************************************************
* Function: kinetis_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_interrupt_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
kinetis_interrupt_process(priv);
net_unlock(state);
/* Re-enable Ethernet interrupts */
#if 0
up_enable_irq(KINETIS_IRQ_EMACTMR);
#endif
up_enable_irq(KINETIS_IRQ_EMACTX);
up_enable_irq(KINETIS_IRQ_EMACRX);
up_enable_irq(KINETIS_IRQ_EMACMISC);
}
#endif
/****************************************************************************
* Function: kinetis_interrupt
*
* Description:
* Three interrupt sources will vector this this function:
* 1. Ethernet MAC transmit interrupt handler
* 2. Ethernet MAC receive interrupt handler
* 3.
*
* Parameters:
* irq - Number of the IRQ that generated the interrupt
* context - Interrupt register state save info (architecture-specific)
*
* Returned Value:
* OK on success
*
* Assumptions:
*
****************************************************************************/
static int kinetis_interrupt(int irq, FAR void *context)
{
register FAR struct kinetis_driver_s *priv = &g_enet[0];
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
*/
up_disable_irq(KINETIS_IRQ_EMACTMR);
up_disable_irq(KINETIS_IRQ_EMACTX);
up_disable_irq(KINETIS_IRQ_EMACRX);
up_disable_irq(KINETIS_IRQ_EMACMISC);
/* TODO: Determine if a TX transfer just completed */
{
/* If a TX transfer just completed, then cancel the TX timeout so
* there will be do race condition between any subsequent timeout
* expiration and the deferred interrupt processing.
*/
wd_cancel(priv->txtimeout);
}
/* Cancel any pending poll work */
work_cancel(HPWORK, &priv->work);
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(HPWORK, &priv->work, kinetis_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
kinetis_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: kinetis_txtimeout
* Function: kinetis_txtimeout_process
*
* Description:
* Our TX watchdog timed out. Called from the timer interrupt handler.
* The last TX never completed. Reset the hardware and start again.
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* argc - The number of available arguments
* arg - The first argument
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static void kinetis_txtimeout(int argc, uint32_t arg, ...)
static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
/* Increment statistics and dump debug info */
NETDEV_TXTIMEOUTS(&priv->dev);
@ -891,10 +1025,42 @@ static void kinetis_txtimeout(int argc, uint32_t arg, ...)
}
/****************************************************************************
* Function: kinetis_polltimer
* Function: kinetis_txtimeout_work
*
* Description:
* Periodic timer handler. Called from the timer interrupt handler.
* Perform TX timeout related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_txtimeout_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
kinetis_txtimeout_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: kinetis_txtimeout_expiry
*
* Description:
* Our TX watchdog timed out. Called from the timer interrupt handler.
* The last TX never completed. Reset the hardware and start again.
*
* Parameters:
* argc - The number of available arguments
@ -908,10 +1074,56 @@ static void kinetis_txtimeout(int argc, uint32_t arg, ...)
*
****************************************************************************/
static void kinetis_polltimer(int argc, uint32_t arg, ...)
static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. This will prevent some race
* conditions with interrupt work. There is still a potential race
* condition with interrupt work that is already queued and in progress.
*/
up_disable_irq(KINETIS_IRQ_EMACTMR);
up_disable_irq(KINETIS_IRQ_EMACTX);
up_disable_irq(KINETIS_IRQ_EMACRX);
up_disable_irq(KINETIS_IRQ_EMACMISC);
/* Cancel any pending poll or interrupt work. This will have no effect
* on work that has already been started.
*/
work_cancel(HPWORK, &priv->work);
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(HPWORK, &priv->work, kinetis_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
kinetis_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: kinetis_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv)
{
/* Check if there is there is a transmission in progress. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
@ -928,7 +1140,89 @@ static void kinetis_polltimer(int argc, uint32_t arg, ...)
/* Setup the watchdog poll timer again in any case */
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer, 1, arg);
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)priv);
}
/****************************************************************************
* Function: kinetis_poll_work
*
* Description:
* Perform periodic polling from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_poll_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
kinetis_poll_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: kinetis_polltimer_expiry
*
* Description:
* Periodic timer handler. Called from the timer interrupt handler.
*
* Parameters:
* argc - The number of available arguments
* arg - The first argument
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
if (work_available(&priv->work))
{
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(HPWORK, &priv->work, kinetis_poll_work, priv, 0);
}
else
{
/* No.. Just re-start the watchdog poll timer, missing one polling
* cycle.
*/
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)arg);
}
#else
/* Process the interrupt now */
kinetis_poll_process(priv);
#endif
}
/****************************************************************************
@ -954,6 +1248,7 @@ static int kinetis_ifup(struct net_driver_s *dev)
(FAR struct kinetis_driver_s *)dev->d_private;
uint8_t *mac = dev->d_mac.ether_addr_octet;
uint32_t regval;
int ret;
ninfo("Bringing up: %d.%d.%d.%d\n",
dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,
@ -986,7 +1281,12 @@ static int kinetis_ifup(struct net_driver_s *dev)
/* Configure the PHY */
kinetis_initphy(priv);
ret = kinetis_initphy(priv);
if (ret < 0)
{
nerr("ERROR: Failed to configure the PHY: %d\n", ret);
return ret;
}
/* Handle promiscuous mode */
@ -1032,8 +1332,8 @@ static int kinetis_ifup(struct net_driver_s *dev)
/* Set and activate a timer process */
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer, 1,
(uint32_t)priv);
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry, 1,
(wdparm_t)priv);
/* Clear all pending ENET interrupt */
@ -1108,6 +1408,77 @@ static int kinetis_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: kinetis_txavail_process
*
* Description:
* Perform an out-of-cycle poll.
*
* Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called in normal user mode
*
****************************************************************************/
static inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv)
{
net_lock_t state;
/* Ignore the notification if the interface is not yet up */
state = net_lock();
if (priv->bifup)
{
/* Check if there is room in the hardware to hold another outgoing
* packet.
*/
if (!kinetics_txringfull(priv))
{
/* No, there is space for another transfer. Poll the network for new
* XMIT data.
*/
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
}
net_unlock(state);
}
/****************************************************************************
* Function: kinetis_txavail_work
*
* Description:
* Perform an out-of-cycle poll on the worker thread.
*
* Parameters:
* arg - Reference to the NuttX driver state structure (cast to void*)
*
* Returned Value:
* None
*
* Assumptions:
* Called on the higher priority worker thread.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_txavail_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
/* Perform the poll */
kinetis_txavail_process(priv);
}
#endif
/****************************************************************************
* Function: kinetis_txavail
*
@ -1131,33 +1502,26 @@ static int kinetis_txavail(struct net_driver_s *dev)
{
FAR struct kinetis_driver_s *priv =
(FAR struct kinetis_driver_s *)dev->d_private;
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions and we will have to ignore the Tx
* availability action.
*/
flags = enter_critical_section();
/* Ignore the notification if the interface is not yet up */
if (priv->bifup)
if (work_available(&priv->work))
{
/* Check if there is room in the hardware to hold another outgoing
* packet.
*/
/* Schedule to serialize the poll on the worker thread. */
if (!kinetics_txringfull(priv))
{
/* No, there is space for another transfer. Poll the network for new
* XMIT data.
*/
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
work_queue(HPWORK, &priv->work, kinetis_txavail_work, priv, 0);
}
leave_critical_section(flags);
#else
/* Perform the out-of-cycle poll now */
kinetis_txavail_process(priv);
#endif
return OK;
}
@ -1253,7 +1617,7 @@ static int kinetis_ioctl(struct net_driver_s *dev, int cmd, long arg)
{
struct mii_ioctl_data_s *req =
(struct mii_ioctl_data_s *)((uintptr_t)arg);
req->phy_id = CONFIG_KINETIS_ENETPHYADDR;
req->phy_id = priv->phyaddr;
ret = OK;
}
break;
@ -1418,6 +1782,7 @@ static int kinetis_readmii(struct kinetis_driver_s *priv, uint8_t phyaddr,
if (timeout >= MII_MAXPOLLS)
{
nerr("ERROR: Timed out waiting for transfer to complete\n");
return -ETIMEDOUT;
}
@ -1441,31 +1806,59 @@ static int kinetis_readmii(struct kinetis_driver_s *priv, uint8_t phyaddr,
* priv - Reference to the private ENET driver state structure
*
* Returned Value:
* None
* Zero (OK) returned on success; a negated errno value is returned on any
* failure;
*
* Assumptions:
*
****************************************************************************/
static inline void kinetis_initphy(struct kinetis_driver_s *priv)
static inline int kinetis_initphy(struct kinetis_driver_s *priv)
{
uint32_t rcr;
uint32_t tcr;
uint16_t phydata;
uint8_t phyaddr;
int retries;
int ret;
/* Loop (potentially infinitely?) until we successfully communicate with
* the PHY.
*/
do
for (phyaddr = 0; phyaddr < 32; phyaddr++)
{
usleep(LINK_WAITUS);
phydata = 0xffff;
kinetis_readmii(priv, CONFIG_KINETIS_ENETPHYADDR, MII_PHYID1, &phydata);
}
while (phydata == 0xffff);
ninfo("%s: Try phyaddr: %u\n", BOARD_PHY_NAME, phyaddr);
/* Try to read PHYID1 few times using this address */
retries = 0;
do
{
usleep(LINK_WAITUS);
ninfo("%s: Read PHYID1, retries=%d\n", BOARD_PHY_NAME, retries + 1);
phydata = 0xffff;
ret = kinetis_readmii(priv, phyaddr, MII_PHYID1, &phydata);
}
while ((ret < 0 || phydata == 0xffff) && ++retries < 3);
/* If we successfully read anything then break out, using this PHY address */
if (retries < 3)
{
break;
}
}
if (phyaddr >= 32)
{
nerr("ERROR: Failed to read %s PHYID1 at any address\n");
return -ENOENT;
}
ninfo("%s: Using PHY address %u\n", BOARD_PHY_NAME, phyaddr);
priv->phyaddr = phyaddr;
#if CONFIG_DEBUG_NET_ERROR
/* Verify PHYID1. Compare OUI bits 3-18 */
ninfo("%s: PHYID1: %04x\n", BOARD_PHY_NAME, phydata);
@ -1473,29 +1866,35 @@ static inline void kinetis_initphy(struct kinetis_driver_s *priv)
{
nerr("ERROR: PHYID1=%04x incorrect for %s. Expected %04x\n",
phydata, BOARD_PHY_NAME, BOARD_PHYID1);
return -ENXIO;
}
else
/* Read PHYID2 */
ret = kinetis_readmii(priv, phyaddr, MII_PHYID2, &phydata);
if (ret < 0)
{
/* Read PHYID2 */
kinetis_readmii(priv, CONFIG_KINETIS_ENETPHYADDR, MII_PHYID2, &phydata);
ninfo("%s: PHYID2: %04x\n", BOARD_PHY_NAME, phydata);
/* Verify PHYID2: Compare OUI bits 19-24 and the 6-bit model number
* (ignoring the 4-bit revision number).
*/
if ((phydata & 0xfff0) != (BOARD_PHYID2 & 0xfff0))
{
nerr("ERROR: PHYID2=%04x incorrect for %s. Expected %04x\n",
(phydata & 0xfff0), BOARD_PHY_NAME, (BOARD_PHYID2 & 0xfff0));
}
nerr("ERROR: Failed to read %s PHYID2: %d\n", BOARD_PHY_NAME, ret);
return ret;
}
ninfo("%s: PHYID2: %04x\n", BOARD_PHY_NAME, phydata);
/* Verify PHYID2: Compare OUI bits 19-24 and the 6-bit model number
* (ignoring the 4-bit revision number).
*/
if ((phydata & 0xfff0) != (BOARD_PHYID2 & 0xfff0))
{
nerr("ERROR: PHYID2=%04x incorrect for %s. Expected %04x\n",
(phydata & 0xfff0), BOARD_PHY_NAME, (BOARD_PHYID2 & 0xfff0));
return -ENXIO;
}
#endif
/* Start auto negotiation */
kinetis_writemii(priv, CONFIG_KINETIS_ENETPHYADDR, MII_MCR,
ninfo("%s: Start autonegotiation...\n", BOARD_PHY_NAME);
kinetis_writemii(priv, phyaddr, MII_MCR,
(MII_MCR_ANRESTART | MII_MCR_ANENABLE));
/* Wait (potentially forever) for auto negotiation to complete */
@ -1503,16 +1902,30 @@ static inline void kinetis_initphy(struct kinetis_driver_s *priv)
do
{
usleep(LINK_WAITUS);
kinetis_readmii(priv, CONFIG_KINETIS_ENETPHYADDR, MII_MSR, &phydata);
ret = kinetis_readmii(priv, phyaddr, MII_MSR, &phydata);
if (ret < 0)
{
nerr("ERROR: Failed to read %s MII_MSR: %d\n",
BOARD_PHY_NAME, ret);
return ret;
}
}
while ((phydata & MII_MSR_ANEGCOMPLETE) == 0);
ninfo("%s: Autonegotiation complete\n", BOARD_PHY_NAME);
ninfo("%s: MII_MSR: %04x\n", BOARD_PHY_NAME, phydata);
/* When we get here we have a link - Find the negotiated speed and duplex. */
phydata = 0;
kinetis_readmii(priv, CONFIG_KINETIS_ENETPHYADDR, BOARD_PHY_STATUS, &phydata);
ret = kinetis_readmii(priv, phyaddr, BOARD_PHY_STATUS, &phydata);
if (ret < 0)
{
nerr("ERROR: Failed to read %s BOARD_PHY_STATUS{%02x]: %d\n",
BOARD_PHY_NAME, BOARD_PHY_STATUS, ret);
return ret;
}
ninfo("%s: BOARD_PHY_STATUS: %04x\n", BOARD_PHY_NAME, phydata);
@ -1540,29 +1953,42 @@ static inline void kinetis_initphy(struct kinetis_driver_s *priv)
{
/* Full duplex */
ninfo("%s: Full duplex\n", BOARD_PHY_NAME);
tcr |= ENET_TCR_FDEN;
}
else
{
/* Half duplex */
ninfo("%s: Half duplex\n", BOARD_PHY_NAME);
rcr |= ENET_RCR_DRT;
}
if (BOARD_PHY_10BASET(phydata))
{
/* 10Mbps */
/* 10 Mbps */
ninfo("%s: 10 Base-T\n", BOARD_PHY_NAME);
rcr |= ENET_RCR_RMII_10T;
}
else if (!BOARD_PHY_100BASET(phydata))
{
/* 100 Mbps */
ninfo("%s: 100 Base-T\n", BOARD_PHY_NAME);
}
else
{
/* This might happen if autonegotiation did not complete(?) */
nerr("ERROR: Neither 10- nor 100-BaseT reported: PHY STATUS=%04x\n",
phydata);
return -EIO;
}
putreg32(rcr, KINETIS_ENET_RCR);
putreg32(tcr, KINETIS_ENET_TCR);
return OK;
}
/****************************************************************************

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ Contents
o Freedom K64F Features
o Serial Console
o LEDs and Buttons
o Ethernet
o Networking Support
o Development Environment
o GNU Toolchain Options
o Freedom K64F Configuration Options
@ -129,40 +129,286 @@ LEDs and Buttons
SW2 PTC6/SPI0_SOUT/PD0_EXTRG/I2S0_RX_BCLK/FB_AD9/I2S0_MCLK/LLWU_P10
SW3 PTA4/FTM0_CH1/NMI_b/LLWU_P3
Ethernet
========
Networking Support
==================
Ethernet MAC/KSZ8081 PHY
------------------------
------------ ----------------- --------------------------------------------
KSZ8081 Board Signal(s) K64F Pin
Pin Signal Function
Pin Signal Function pinmux Name
--- -------- ----------------- --------------------------------------------
1 VDD_1V2 VDDPLL_1.2V ---
2 VDDA_3V3 VDDA_ENET ---
3 RXM ENET1_RX- ---
4 RXP ENET1_RX+ ---
5 TXM ENET1_TX- ---
6 TXP ENET1_TX+ ---
7 X0 RMII_XTAL0 ---
8 XI RMII_XTAL1 ---
9 REXT --- ---, Apparently not connected
10 MDIO RMII0_MDIO PTB0/RMII0_MDIO
11 MDC RMII0_MDC PTB1/RMII0_MDC
12 RXD1 RMII0_RXD_1 PTA12/RMII0_RXD1
13 RXD0 RMII0_RXD_0 PTA13/RMII0_RXD0
14 VDDIO VDDIO_ENET ---
15 CRS_DIV PTA14/RMII0_CRS_DV
16 REF_CLK RMII_RXCLK PTA18/EXTAL0, PHY clock input
17 RXER RMII0_RXER PTA5/RMII0_RXER
18 INTRP RMII0_INT_B, J14 Pin 2, Apparently not available unless jumpered
PHY_INT_1
19 TXEN RMII0_TXEN PTA15/RMII0_TXEN
20 TXD0 RMII0_TXD_0 PTA16/RMII0_TXD0
21 TXD1 RMII0_TXD_1 PTA17/RMII0_TXD1
22 GND1 --- ---
24 nRST PHY_RST_B ---
25 GND2 --- ---
1 VDD_1V2 VDDPLL_1.2V --- ---
2 VDDA_3V3 VDDA_ENET --- ---
3 RXM ENET1_RX- --- ---
4 RXP ENET1_RX+ --- ---
5 TXM ENET1_TX- --- ---
6 TXP ENET1_TX+ --- ---
7 X0 RMII_XTAL0 --- ---
8 XI RMII_XTAL1 --- ---
9 REXT --- ---, Apparently not connected ---
10 MDIO RMII0_MDIO PTB0/RMII0_MDIO PIN_RMII0_MDIO
11 MDC RMII0_MDC PTB1/RMII0_MDC PIN_RMII0_MDC
12 RXD1 RMII0_RXD_1 PTA12/RMII0_RXD1 PIN_RMII0_RXD1
13 RXD0 RMII0_RXD_0 PTA13/RMII0_RXD0 PIN_RMII0_RXD0
14 VDDIO VDDIO_ENET --- ---
15 CRS_DIV PTA14/RMII0_CRS_DV PIN_RMII0_CRS_DV
16 REF_CLK RMII_RXCLK PTA18/EXTAL0, PHY clock input ---
17 RXER RMII0_RXER PTA5/RMII0_RXER PIN_RMII0_RXER
18 INTRP RMII0_INT_B, J14 Pin 2, Apparently not ---
PHY_INT_1 available unless jumpered
19 TXEN RMII0_TXEN PTA15/RMII0_TXEN PIN_RMII0_TXEN
20 TXD0 RMII0_TXD_0 PTA16/RMII0_TXD0 PIN_RMII0_TXD0
21 TXD1 RMII0_TXD_1 PTA17/RMII0_TXD1 PIN_RMII0_TXD1
22 GND1 --- --- ---
24 nRST PHY_RST_B --- ---
25 GND2 --- --- ---
--- -------- ----------------- --------------------------------------------
No external pullup is available on MDIO signal when MK64FN1M0VLL12 MCU is
requests status of the Ethernet link connection. Internal pullup is required
when port configuration for MDIO signal is enabled:
CONFIG_KINETIS_ENET_MDIOPULLUP=y
Networking support via the can be added to NSH by selecting the following
configuration options.
Selecting the EMAC peripheral
-----------------------------
System Type -> Kinetis Peripheral Support
CONFIG_KINETIS_ENET=y : Enable the EThernet MAC peripheral
System Type -> Ethernet Configuration
CONFIG_KINETIS_ENETNETHIFS=1
CONFIG_KINETIS_ENETNRXBUFFERS=6
CONFIG_KINETIS_ENETNTXBUFFERS=2
CONFIG_KINETIS_ENET_MDIOPULLUP=y
Networking Support
CONFIG_NET=y : Enable Neworking
CONFIG_NET_ETHERNET=y : Support Ethernet data link
CONFIG_NET_NOINTS=y : Should operative at non-interrupt level
CONFIG_NET_SOCKOPTS=y : Enable socket operations
CONFIG_NET_MULTIBUFFER=y : Multi-packet buffer option required
CONFIG_NET_ETH_MTU=590 : Maximum packet size (MTU) 1518 is more standard
CONFIG_NET_ETH_TCP_RECVWNDO=536 : Should be the same as CONFIG_NET_ETH_MTU
CONFIG_NET_ARP=y : Enable ARP
CONFIG_NET_ARPTAB_SIZE=16 : ARP table size
CONFIG_NET_ARP_IPIN=y : Enable ARP address harvesting
CONFIG_NET_ARP_SEND=y : Send ARP request before sending data
CONFIG_NET_TCP=y : Enable TCP/IP networking
CONFIG_NET_TCP_READAHEAD=y : Support TCP read-ahead
CONFIG_NET_TCP_WRITE_BUFFERS=y : Support TCP write-buffering
CONFIG_NET_TCPBACKLOG=y : Support TCP/IP backlog
CONFIG_NET_MAX_LISTENPORTS=20 :
CONFIG_NET_TCP_READAHEAD_BUFSIZE=536 Read-ahead buffer size
CONFIG_NET_UDP=y : Enable UDP networking
CONFIG_NET_BROADCAST=y : Needed for DNS name resolution
CONFIG_NET_ICMP=y : Enable ICMP networking
CONFIG_NET_ICMP_PING=y : Needed for NSH ping command
: Defaults should be okay for other options
f Application Configuration -> Network Utilities
CONFIG_NETDB_DNSCLIENT=y : Enable host address resolution
CONFIG_NETUTILS_TELNETD=y : Enable the Telnet daemon
CONFIG_NETUTILS_TFTPC=y : Enable TFTP data file transfers for get and put commands
CONFIG_NETUTILS_NETLIB=y : Network library support is needed
CONFIG_NETUTILS_WEBCLIENT=y : Needed for wget support
: Defaults should be okay for other options
Application Configuration -> NSH Library
CONFIG_NSH_TELNET=y : Enable NSH session via Telnet
CONFIG_NSH_IPADDR=0x0a000002 : Select a fixed IP address
CONFIG_NSH_DRIPADDR=0x0a000001 : IP address of gateway/host PC
CONFIG_NSH_NETMASK=0xffffff00 : Netmask
CONFIG_NSH_NOMAC=y : Need to make up a bogus MAC address
: Defaults should be okay for other options
You can also enable enable the DHCPC client for networks that use
dynamically assigned address:
Application Configuration -> Network Utilities
CONFIG_NETUTILS_DHCPC=y : Enables the DHCP client
Networking Support
CONFIG_NET_UDP=y : Depends on broadcast UDP
Application Configuration -> NSH Library
CONFIG_NET_BROADCAST=y
CONFIG_NSH_DHCPC=y : Tells NSH to use DHCPC, not
: the fixed addresses
Using the network with NSH
--------------------------
So what can you do with this networking support? First you see that
NSH has several new network related commands:
ifconfig, ifdown, ifup: Commands to help manage your network
get and put: TFTP file transfers
wget: HTML file transfers
ping: Check for access to peers on the network
Telnet console: You can access the NSH remotely via telnet.
You can also enable other add on features like full FTP or a Web
Server or XML RPC and others. There are also other features that
you can enable like DHCP client (or server) or network name
resolution.
By default, the IP address of the DK-TM4C129X will be 10.0.0.2 and
it will assume that your host is the gateway and has the IP address
10.0.0.1.
nsh> ifconfig
eth0 HWaddr 00:e0:de:ad:be:ef at UP
IPaddr:10.0.0.2 DRaddr:10.0.0.1 Mask:255.255.255.0
You can use ping to test for connectivity to the host (Careful,
Window firewalls usually block ping-related ICMP traffic). On the
target side, you can:
nsh> ping 10.0.0.1
PING 10.0.0.1 56 bytes of data
56 bytes from 10.0.0.1: icmp_seq=1 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=2 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=3 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=4 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=5 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=6 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=7 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=8 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=9 time=0 ms
56 bytes from 10.0.0.1: icmp_seq=10 time=0 ms
10 packets transmitted, 10 received, 0% packet loss, time 10100 ms
NOTE: In this configuration is is normal to have packet loss > 0%
the first time you ping due to the default handling of the ARP
table.
On the host side, you should also be able to ping the DK-TM4C129X:
$ ping 10.0.0.2
You can also log into the NSH from the host PC like this:
$ telnet 10.0.0.2
Trying 10.0.0.2...
Connected to 10.0.0.2.
Escape character is '^]'.
sh_telnetmain: Session [3] Started
NuttShell (NSH) NuttX-6.31
nsh> help
help usage: help [-v] [<cmd>]
[ echo ifconfig mkdir mw sleep
? exec ifdown mkfatfs ping test
cat exit ifup mkfifo ps umount
cp free kill mkrd put usleep
cmp get losetup mh rm wget
dd help ls mount rmdir xd
df hexdump mb mv sh
Builtin Apps:
nsh>
NOTE: If you enable this networking as described above, you will
experience a delay on booting NSH. That is because the start-up logic
waits for the network connection to be established before starting
NuttX. In a real application, you would probably want to do the
network bringup on a separate thread so that access to the NSH prompt
is not delayed.
This delay will be especially long if the board is not connected to
a network. On the order of minutes! You will probably think that
NuttX has crashed! And then, when it finally does come up after
numerous timeouts and retries, the network will not be available --
even if the network cable is plugged in later.
The long delays can be eliminated by using a separate the network
initialization thread discussed below. Recovering after the network
becomes available requires the network monitor feature, also discussed
below.
Network Initialization Thread
-----------------------------
There is a configuration option enabled by CONFIG_NSH_NETINIT_THREAD
that will do the NSH network bring-up asynchronously in parallel on
a separate thread. This eliminates the (visible) networking delay
altogether. This current implementation, however, has some limitations:
- If no network is connected, the network bring-up will fail and
the network initialization thread will simply exit. There are no
retries and no mechanism to know if the network initialization was
successful (it could perform a network Ioctl to see if the link is
up and it now, keep trying, but it does not do that now).
- Furthermore, there is currently no support for detecting loss of
network connection and recovery of the connection (similarly, this
thread could poll periodically for network status, but does not).
Both of these shortcomings could be eliminated by enabling the network
monitor:
Network Monitor
---------------
By default the network initialization thread will bring-up the network
then exit, freeing all of the resources that it required. This is a
good behavior for systems with limited memory.
If the CONFIG_NSH_NETINIT_MONITOR option is selected, however, then the
network initialization thread will persist forever; it will monitor the
network status. In the event that the network goes down (for example, if
a cable is removed), then the thread will monitor the link status and
attempt to bring the network back up. In this case the resources
required for network initialization are never released.
Pre-requisites:
- CONFIG_NSH_NETINIT_THREAD as described above.
- The K64F EMAC block does not support PHY interrupts. The KSZ8081
PHY interrupt line is brought to a jumper block and it should be
possible to connect that some some interrupt port pin. You would
need to provide some custom logic in the Freedcom K64F
configuration to set up that PHY interrupt.
- In addtion to the PHY interrupt, the Network Monitor also requires the
following setting:
CONFIG_NETDEV_PHY_IOCTL. Enable PHY IOCTL commands in the Ethernet
device driver. Special IOCTL commands must be provided by the Ethernet
driver to support certain PHY operations that will be needed for link
management. There operations are not complex and are implemented for
the Atmel SAMA5 family.
CONFIG_ARCH_PHY_INTERRUPT. This is not a user selectable option.
Rather, it is set when you select a board that supports PHY
interrupts. For the K64F, like most other architectures, the PHY
interrupt must be provided via some board-specific GPIO. In any
event, the board-specific logic must provide support for the PHY
interrupt. To do this, the board logic must do two things: (1) It
must provide the function arch_phy_irq() as described and prototyped
in the nuttx/include/nuttx/arch.h, and (2) it must select
CONFIG_ARCH_PHY_INTERRUPT in the board configuration file to
advertise that it supports arch_phy_irq().
And a few other things: UDP support is required (CONFIG_NET_UDP) and
signals must not be disabled (CONFIG_DISABLE_SIGNALS).
Given those prerequisites, the network monitor can be selected with these
additional settings.
System Type -> Kinetis Ethernet Configuration
CONFIG_ARCH_PHY_INTERRUPT=y : (auto-selected)
CONFIG_NETDEV_PHY_IOCTL=y : (auto-selected)
Application Configuration -> NSH Library -> Networking Configuration
CONFIG_NSH_NETINIT_THREAD : Enable the network initialization thread
CONFIG_NSH_NETINIT_MONITOR=y : Enable the network monitor
CONFIG_NSH_NETINIT_RETRYMSEC=2000 : Configure the network monitor as you like
CONFIG_NSH_NETINIT_SIGNO=18
Development Environment
=======================
@ -400,6 +646,24 @@ Where <subdir> is one of the following:
CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIW=y : ARM/mbed toolcahin (arm-none-elf-gcc)
CONFIG_INTELHEX_BINARY=y : Output formats: Intel hex binary
3. No external pullup is available on MDIO signal when MK64FN1M0VLL12 MCU
is requests status of the Ethernet link connection. Internal pullup is
required when port configuration for MDIO signal is enabled:
CONFIG_KINETIS_ENET_MDIOPULLUP=y
4. Configured to use a fixed IPv4 address:
CONFIG_NSH_IPADDR=0x0a000002
CONFIG_NSH_DRIPADDR=0x0a000001
CONFIG_NSH_NETMASK=0xffffff00
And a bogus MAC address:
CONFIG_NSH_NOMAC=y
CONFIG_NSH_SWMAC=y
CONFIG_NSH_MACADDR=0x00e0deadbeef
nsh:
---
Configures the NuttShell (nsh) located at apps/examples/nsh using a
@ -455,5 +719,13 @@ Status
NSH configuration is working and LEDs are working. The only odd
behavior that I see is that pressing SW3 causes an unexpected interrupt
error.
2016-07-12: Added support for the KSZ8081 PHY and added the netnsh
configuration. Untested as of this writing.
configuration. The network is basically functional, but a lot more
testing is needed to confirm that.
In testing, I notice a strange thing. If I run at full optimization the
code runs (albeit with bugs-to-be-solved). But with no optimization or
even at -O1, the system fails to boot. This seems to be related to the
watchdog timer.

View File

@ -41,8 +41,9 @@
************************************************************************************/
#include <nuttx/config.h>
#ifndef __ASSEMBLY__
# include <stdint.h>
# include <stdint.h>
#endif
/************************************************************************************
@ -68,7 +69,7 @@
*
* PLL Input frequency: PLLIN = REFCLK / PRDIV = 50 Mhz / 20 = 2.5 MHz
* PLL Output frequency: PLLOUT = PLLIN * VDIV = 2.5 Mhz * 48 = 120 MHz
* MCG Frequency: PLLOUT = 96MHz
* MCG Frequency: PLLOUT = 120 MHz
*
* PRDIV register value is the divider minus one. So 20 -> 19
* VDIV regiser value is offset by 24. So 28 -> 24
@ -100,36 +101,37 @@
* SDCLK frequency = (base clock) / (prescaler * divisor)
*
* The SDHC module is always configure configured so that the core clock is the base
* clock.
* clock. Possible values for presscaler and divisor are:
*
* SDCLKFS: {2, 4, 8, 16, 32, 63, 128, 256}
* DVS: {1..16}
*/
/* Identification mode: 400KHz = 96MHz / ( 16 * 15) */
/* Identification mode: Optimal 400KHz, Actual 120MHz / (32 * 10) = 375 Khz */
#define BOARD_SDHC_IDMODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV16
#define BOARD_SDHC_IDMODE_DIVISOR SDHC_SYSCTL_DVS_DIV(15)
#define BOARD_SDHC_IDMODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV32
#define BOARD_SDHC_IDMODE_DIVISOR SDHC_SYSCTL_DVS_DIV(10)
/* MMC normal mode: 16MHz = 96MHz / (2 * 3) */
/* MMC normal mode: Optimal 20MHz, Actual 120MHz / (2 * 3) = 20 MHz */
#define BOARD_SDHC_MMCMODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV2
#define BOARD_SDHC_MMCMODE_DIVISOR SDHC_SYSCTL_DVS_DIV(3)
/* SD normal mode (1-bit): 16MHz = 96MHz / (2 * 3) */
/* SD normal mode (1-bit): Optimal 20MHz, Actual 120MHz / (2 * 3) = 20 MHz */
#define BOARD_SDHC_SD1MODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV2
#define BOARD_SDHC_SD1MODE_DIVISOR SDHC_SYSCTL_DVS_DIV(3)
/* SD normal mode (4-bit): 24MHz = 96MHz / (2 * 2) (with DMA)
* SD normal mode (4-bit): 16MHz = 96MHz / (2 * 3) (no DMA)
/* SD normal mode (4-bit): Optimal 25MHz, Actual 120MHz / (2 * 3) = 20 MHz (with DMA)
* SD normal mode (4-bit): Optimal 20MHz, Actual 120MHz / (2 * 3) = 20 MHz (no DMA)
*/
#ifdef CONFIG_SDIO_DMA
# define BOARD_SDHC_SD4MODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV2
# define BOARD_SDHC_SD4MODE_DIVISOR SDHC_SYSCTL_DVS_DIV(2)
# define BOARD_SDHC_SD4MODE_DIVISOR SDHC_SYSCTL_DVS_DIV(3)
#else
//# define BOARD_SDHC_SD4MODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV2
//# define BOARD_SDHC_SD4MODE_DIVISOR SDHC_SYSCTL_DVS_DIV(3)
# define BOARD_SDHC_SD4MODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV16
# define BOARD_SDHC_SD4MODE_DIVISOR SDHC_SYSCTL_DVS_DIV(15)
# define BOARD_SDHC_SD4MODE_PRESCALER SDHC_SYSCTL_SDCLKFS_DIV2
# define BOARD_SDHC_SD4MODE_DIVISOR SDHC_SYSCTL_DVS_DIV(3)
#endif
/* LED definitions ******************************************************************/

View File

@ -245,8 +245,9 @@ CONFIG_KINETIS_ENET=y
CONFIG_KINETIS_ENETNETHIFS=1
CONFIG_KINETIS_ENETNRXBUFFERS=6
CONFIG_KINETIS_ENETNTXBUFFERS=2
CONFIG_KINETIS_ENETPHYADDR=1
# CONFIG_KINETIS_ENETUSEMII is not set
CONFIG_KINETIS_ENET_MDIOPULLUP=y
# CONFIG_KINETIS_ENET_NORXER is not set
#
# Kinetis UART Configuration
@ -331,7 +332,14 @@ CONFIG_ARCH_HAVE_IRQBUTTONS=y
# Board-Specific Options
#
# CONFIG_BOARD_CRASHDUMP is not set
# CONFIG_LIB_BOARDCTL is not set
CONFIG_LIB_BOARDCTL=y
# CONFIG_BOARDCTL_RESET is not set
# CONFIG_BOARDCTL_UNIQUEID is not set
# CONFIG_BOARDCTL_TSCTEST is not set
# CONFIG_BOARDCTL_ADCTEST is not set
# CONFIG_BOARDCTL_PWMTEST is not set
# CONFIG_BOARDCTL_GRAPHICS is not set
# CONFIG_BOARDCTL_IOCTL is not set
#
# RTOS Features
@ -403,6 +411,7 @@ CONFIG_NAME_MAX=32
# CONFIG_SCHED_STARTHOOK is not set
# CONFIG_SCHED_ATEXIT is not set
# CONFIG_SCHED_ONEXIT is not set
# CONFIG_SIG_EVTHREAD is not set
#
# Signal Numbers
@ -411,6 +420,7 @@ CONFIG_SIG_SIGUSR1=1
CONFIG_SIG_SIGUSR2=2
CONFIG_SIG_SIGALARM=3
CONFIG_SIG_SIGCONDTIMEDOUT=16
CONFIG_SIG_SIGWORK=17
#
# POSIX Message Queue Options
@ -422,8 +432,11 @@ CONFIG_MQ_MAXMSGSIZE=32
#
# Work queue support
#
# CONFIG_SCHED_WORKQUEUE is not set
# CONFIG_SCHED_HPWORK is not set
CONFIG_SCHED_WORKQUEUE=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_HPWORKPRIORITY=224
CONFIG_SCHED_HPWORKPERIOD=50000
CONFIG_SCHED_HPWORKSTACKSIZE=2048
# CONFIG_SCHED_LPWORK is not set
#
@ -615,7 +628,7 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
# CONFIG_NET_NOINTS is not set
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
@ -759,7 +772,16 @@ CONFIG_FS_FAT=y
# CONFIG_FS_ROMFS is not set
# CONFIG_FS_TMPFS is not set
# CONFIG_FS_SMARTFS is not set
# CONFIG_FS_PROCFS is not set
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_REGISTER=y
#
# Exclude individual procfs entries
#
# CONFIG_FS_PROCFS_EXCLUDE_PROCESS is not set
# CONFIG_FS_PROCFS_EXCLUDE_UPTIME is not set
# CONFIG_FS_PROCFS_EXCLUDE_MOUNTS is not set
# CONFIG_FS_PROCFS_EXCLUDE_NET is not set
# CONFIG_FS_UNIONFS is not set
#
@ -918,6 +940,7 @@ CONFIG_EXAMPLES_NSH=y
# CONFIG_EXAMPLES_TOUCHSCREEN is not set
# CONFIG_EXAMPLES_UDP is not set
# CONFIG_EXAMPLES_UDPBLASTER is not set
# CONFIG_EXAMPLES_USBSERIAL is not set
# CONFIG_EXAMPLES_USBTERM is not set
# CONFIG_EXAMPLES_WATCHDOG is not set
# CONFIG_EXAMPLES_WEBSERVER is not set
@ -1057,6 +1080,7 @@ CONFIG_NSH_MMCSDMINOR=0
CONFIG_NSH_CMDOPT_DF_H=y
CONFIG_NSH_CODECS_BUFSIZE=128
CONFIG_NSH_CMDOPT_HEXDUMP=y
CONFIG_NSH_PROC_MOUNTPOINT="/proc"
CONFIG_NSH_FILEIOSIZE=512
#
@ -1070,7 +1094,7 @@ CONFIG_NSH_FILEIOSIZE=512
# Console Configuration
#
CONFIG_NSH_CONSOLE=y
# CONFIG_NSH_ARCHINIT is not set
CONFIG_NSH_ARCHINIT=y
#
# Networking Configuration

View File

@ -192,6 +192,8 @@ CONFIG_ARCH_FAMILY_K64=y
CONFIG_KINETIS_UART3=y
# CONFIG_KINETIS_UART4 is not set
# CONFIG_KINETIS_UART5 is not set
# CONFIG_KINETIS_ENET is not set
# CONFIG_KINETIS_RNGB is not set
# CONFIG_KINETIS_FLEXCAN0 is not set
# CONFIG_KINETIS_FLEXCAN1 is not set
# CONFIG_KINETIS_SPI0 is not set
@ -312,7 +314,14 @@ CONFIG_ARCH_HAVE_IRQBUTTONS=y
# Board-Specific Options
#
# CONFIG_BOARD_CRASHDUMP is not set
# CONFIG_LIB_BOARDCTL is not set
CONFIG_LIB_BOARDCTL=y
# CONFIG_BOARDCTL_RESET is not set
# CONFIG_BOARDCTL_UNIQUEID is not set
# CONFIG_BOARDCTL_TSCTEST is not set
# CONFIG_BOARDCTL_ADCTEST is not set
# CONFIG_BOARDCTL_PWMTEST is not set
# CONFIG_BOARDCTL_GRAPHICS is not set
# CONFIG_BOARDCTL_IOCTL is not set
#
# RTOS Features
@ -545,6 +554,7 @@ CONFIG_SYSLOG_SERIAL_CONSOLE=y
CONFIG_SYSLOG_CONSOLE=y
# CONFIG_SYSLOG_NONE is not set
# CONFIG_SYSLOG_FILE is not set
# CONFIG_SYSLOG_CHARDEV is not set
#
# Networking Support
@ -584,7 +594,15 @@ CONFIG_FS_FAT=y
# CONFIG_FS_ROMFS is not set
# CONFIG_FS_TMPFS is not set
# CONFIG_FS_SMARTFS is not set
# CONFIG_FS_PROCFS is not set
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_REGISTER=y
#
# Exclude individual procfs entries
#
# CONFIG_FS_PROCFS_EXCLUDE_PROCESS is not set
# CONFIG_FS_PROCFS_EXCLUDE_UPTIME is not set
# CONFIG_FS_PROCFS_EXCLUDE_MOUNTS is not set
# CONFIG_FS_UNIONFS is not set
#
@ -730,6 +748,7 @@ CONFIG_EXAMPLES_NSH=y
# CONFIG_EXAMPLES_TELNETD is not set
# CONFIG_EXAMPLES_TIFF is not set
# CONFIG_EXAMPLES_TOUCHSCREEN is not set
# CONFIG_EXAMPLES_USBSERIAL is not set
# CONFIG_EXAMPLES_USBTERM is not set
# CONFIG_EXAMPLES_WATCHDOG is not set
# CONFIG_EXAMPLES_WEBSERVER is not set
@ -829,7 +848,6 @@ CONFIG_NSH_DISABLE_LOSMART=y
# CONFIG_NSH_DISABLE_MV is not set
# CONFIG_NSH_DISABLE_MW is not set
# CONFIG_NSH_DISABLE_PS is not set
# CONFIG_NSH_DISABLE_PSSTACKUSAGE is not set
# CONFIG_NSH_DISABLE_PUT is not set
# CONFIG_NSH_DISABLE_PWD is not set
# CONFIG_NSH_DISABLE_RM is not set
@ -853,6 +871,7 @@ CONFIG_NSH_MMCSDMINOR=0
CONFIG_NSH_CMDOPT_DF_H=y
CONFIG_NSH_CODECS_BUFSIZE=128
CONFIG_NSH_CMDOPT_HEXDUMP=y
CONFIG_NSH_PROC_MOUNTPOINT="/proc"
CONFIG_NSH_FILEIOSIZE=512
#
@ -867,7 +886,7 @@ CONFIG_NSH_FILEIOSIZE=512
#
CONFIG_NSH_CONSOLE=y
# CONFIG_NSH_ALTCONDEV is not set
# CONFIG_NSH_ARCHINIT is not set
CONFIG_NSH_ARCHINIT=y
# CONFIG_NSH_LOGIN is not set
# CONFIG_NSH_CONSOLE_LOGIN is not set

View File

@ -49,6 +49,65 @@
* Pre-processor Definitions
************************************************************************************/
/* Application Configuration ********************************************************/
/* Assume we have everything */
#define HAVE_PROC 1
#define NSH_HAVEUSBDEV 1
#define NSH_HAVEMMCSD 1
/* Automount procfs */
#if !defined(CONFIG_FS_PROCFS)
# undef HAVE_PROC
#endif
#if defined(HAVE_PROC) && defined(CONFIG_DISABLE_MOUNTPOINT)
# warning Mountpoints disabled. No procfs support
# undef HAVE_PROC
#endif
#if defined(CONFIG_NSH_PROC_MOUNTPOINT)
# define PROCFS_MOUNTPOUNT CONFIG_NSH_PROC_MOUNTPOINT
#else
# define PROCFS_MOUNTPOUNT "/proc"
#endif
/* SD card support */
#define MMCSD_SLOTNO 0
/* Can't support MMC/SD features if mountpoints are disabled or if SDHC support
* is not enabled.
*/
#if defined(CONFIG_DISABLE_MOUNTPOINT) || !defined(CONFIG_KINETIS_SDHC)
# undef NSH_HAVEMMCSD
#endif
#ifdef NSH_HAVEMMCSD
# if defined(CONFIG_NSH_MMCSDSLOTNO) && CONFIG_NSH_MMCSDSLOTNO != 0
# error "Only one MMC/SD slot, slot 0"
# endif
/* We expect to receive GPIO interrupts for card insertion events */
# ifndef CONFIG_GPIO_IRQ
# error "CONFIG_GPIO_IRQ required for card detect interrupt"
# endif
# ifndef CONFIG_KINETIS_PORTEINTS
# error "CONFIG_KINETIS_PORTEINTS required for card detect interrupt"
# endif
#endif
/* Can't support USB features if USB is not enabled */
#ifndef CONFIG_USBDEV
# undef NSH_HAVEUSBDEV
#endif
/* How many SPI modules does this chip support? The LM3S6918 supports 2 SPI
* modules (others may support more -- in such case, the following must be
* expanded).

View File

@ -39,6 +39,7 @@
#include <nuttx/config.h>
#include <sys/mount.h>
#include <stdbool.h>
#include <stdio.h>
#include <syslog.h>
@ -54,58 +55,6 @@
#if defined(CONFIG_LIB_BOARDCTL) || defined(CONFIG_BOARD_INITIALIZE)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* PORT and SLOT number probably depend on the board configuration */
#ifdef CONFIG_ARCH_BOARD_FREEDOM_K64F
# define NSH_HAVEUSBDEV 1
# define NSH_HAVEMMCSD 1
# if defined(CONFIG_NSH_MMCSDSLOTNO) && CONFIG_NSH_MMCSDSLOTNO != 0
# error "Only one MMC/SD slot, slot 0"
# undef CONFIG_NSH_MMCSDSLOTNO
# endif
# ifndef CONFIG_NSH_MMCSDSLOTNO
# define CONFIG_NSH_MMCSDSLOTNO 0
# endif
#else
/* Add configuration for new Kinetis boards here */
# error "Unrecognized Kinetis board"
# undef NSH_HAVEUSBDEV
# undef NSH_HAVEMMCSD
#endif
/* Can't support USB features if USB is not enabled */
#ifndef CONFIG_USBDEV
# undef NSH_HAVEUSBDEV
#endif
/* Can't support MMC/SD features if mountpoints are disabled or if SDHC support
* is not enabled.
*/
#if defined(CONFIG_DISABLE_MOUNTPOINT) || !defined(CONFIG_KINETIS_SDHC)
# undef NSH_HAVEMMCSD
#endif
#ifndef CONFIG_NSH_MMCSDMINOR
# define CONFIG_NSH_MMCSDMINOR 0
#endif
/* We expect to receive GPIO interrupts for card insertion events */
#ifndef CONFIG_GPIO_IRQ
# error "CONFIG_GPIO_IRQ required for card detect interrupt"
#endif
#ifndef CONFIG_KINETIS_PORTEINTS
# error "CONFIG_KINETIS_PORTEINTS required for card detect interrupt"
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -199,9 +148,24 @@ static int k64_cdinterrupt(int irq, FAR void *context)
int k64_bringup(void)
{
#ifdef NSH_HAVEMMCSD
int ret;
#ifdef HAVE_PROC
/* Mount the proc filesystem */
syslog(LOG_INFO, "Mounting procfs to /proc\n");
ret = mount(NULL, PROCFS_MOUNTPOUNT, "procfs", 0, NULL);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to mount the PROC filesystem: %d (%d)\n",
ret, errno);
return ret;
}
#endif
#ifdef NSH_HAVEMMCSD
/* Configure GPIO pins */
/* Attached the card detect interrupt (but don't enable it yet) */
@ -211,19 +175,18 @@ int k64_bringup(void)
/* Configure the write protect GPIO */
kinetis_pinconfig(GPIO_SD_WRPROTECT);
//kinetis_pinconfig(GPIO_SD_WRPROTECT);
/* Mount the SDHC-based MMC/SD block driver */
/* First, get an instance of the SDHC interface */
syslog(LOG_INFO, "Initializing SDHC slot %d\n",
CONFIG_NSH_MMCSDSLOTNO);
syslog(LOG_INFO, "Initializing SDHC slot %d\n", MMCSD_SLOTNO);
g_nsh.sdhc = sdhc_initialize(CONFIG_NSH_MMCSDSLOTNO);
g_nsh.sdhc = sdhc_initialize(MMCSD_SLOTNO);
if (!g_nsh.sdhc)
{
syslog(LOG_ERR, "ERROR: Failed to initialize SDHC slot %d\n",
CONFIG_NSH_MMCSDSLOTNO);
MMCSD_SLOTNO);
return -ENODEV;
}
@ -249,6 +212,8 @@ int k64_bringup(void)
kinetis_pinirqenable(GPIO_SD_CARDDETECT);
#endif
UNUSED(ret);
return OK;
}

View File

@ -1691,6 +1691,11 @@ static int smartfs_unlink(struct inode *mountpt, const char *relpath)
ret = OK;
errout_with_semaphore:
if (entry.name != NULL)
{
kmm_free(entry.name);
}
smartfs_semgive(fs);
return ret;
}
@ -1856,6 +1861,11 @@ int smartfs_rmdir(struct inode *mountpt, const char *relpath)
ret = OK;
errout_with_semaphore:
if (entry.name != NULL)
{
kmm_free(entry.name);
}
smartfs_semgive(fs);
return ret;
}