mirror of
https://github.com/apache/nuttx.git
synced 2026-06-01 07:45:16 +08:00
Merge remote-tracking branch 'origin/master' into ieee802154
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
NuttX TODO List (Last updated April 15, 2017)
|
NuttX TODO List (Last updated May 18, 2017)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
This file summarizes known NuttX bugs, limitations, inconsistencies with
|
This file summarizes known NuttX bugs, limitations, inconsistencies with
|
||||||
@@ -25,7 +25,7 @@ nuttx/:
|
|||||||
(12) Libraries (libc/, libm/)
|
(12) Libraries (libc/, libm/)
|
||||||
(10) File system/Generic drivers (fs/, drivers/)
|
(10) File system/Generic drivers (fs/, drivers/)
|
||||||
(9) Graphics Subsystem (graphics/)
|
(9) Graphics Subsystem (graphics/)
|
||||||
(2) Build system / Toolchains
|
(3) Build system / Toolchains
|
||||||
(3) Linux/Cywgin simulation (arch/sim)
|
(3) Linux/Cywgin simulation (arch/sim)
|
||||||
(4) ARM (arch/arm/)
|
(4) ARM (arch/arm/)
|
||||||
|
|
||||||
@@ -1825,6 +1825,43 @@ o Build system
|
|||||||
Priority: Low, since I am not aware of anyone using the Windows Native build.
|
Priority: Low, since I am not aware of anyone using the Windows Native build.
|
||||||
But, of course, very high if you want to use it.
|
But, of course, very high if you want to use it.
|
||||||
|
|
||||||
|
Title: CONTROL-C CAN BREAK DEPENDENCIES
|
||||||
|
Description: If you control C out of a make, then there are things that can go
|
||||||
|
wrong. For one, you can break the dependencies in this scenario:
|
||||||
|
|
||||||
|
- The build in a given directory begins with all of the compilations.
|
||||||
|
On terminal, this the long phase with CC: on each line. As each
|
||||||
|
.o file is created, it is timestamped with the current time.
|
||||||
|
|
||||||
|
- The dependencies on each .o are such that the C file will be re-
|
||||||
|
compile if the .o file is OLDER that the corresponding .a archive
|
||||||
|
file.
|
||||||
|
|
||||||
|
- The compilation phase is followed by a single, relatively short
|
||||||
|
AR: phase that adds each of the file to the .a archive file. As
|
||||||
|
each file is added to archive, the timestamp of the of archive is
|
||||||
|
updated to the current time. After the first .o file has been
|
||||||
|
added, then archive file will have a newly timestamp than any of
|
||||||
|
the newly compiled .o file.
|
||||||
|
|
||||||
|
- If the user aborts with control-C during this AR: phase, then we
|
||||||
|
are left with: (1) not all of the files have bee added to the
|
||||||
|
archive, and (2) the archive file has a newer timestamp than any
|
||||||
|
of the .o file.
|
||||||
|
|
||||||
|
So when the make is restarted after a control, the dependencies will
|
||||||
|
see that the .a archive file has the newer time stamp and those .o
|
||||||
|
file will never be added to the archive until the directory is cleaned
|
||||||
|
or some other dependency changes.
|
||||||
|
Status Open
|
||||||
|
Priority: Medium-High. It is a rare event that control-C happens at just the
|
||||||
|
point in time. However, when it does occur the resulting code may
|
||||||
|
have binary incompatiblies in the code taken from the out-of-sync
|
||||||
|
archives and cost a lot of debug time before you realize the issue.
|
||||||
|
|
||||||
|
A work-around is to do 'make clean' if you ever decide to control-C
|
||||||
|
out of a make.
|
||||||
|
|
||||||
o Other drivers (drivers/)
|
o Other drivers (drivers/)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/wdog.h>
|
#include <nuttx/wdog.h>
|
||||||
#include <nuttx/wqueue.h>
|
#include <nuttx/wqueue.h>
|
||||||
|
#include <nuttx/net/phy.h>
|
||||||
#include <nuttx/net/mii.h>
|
#include <nuttx/net/mii.h>
|
||||||
#include <nuttx/net/arp.h>
|
#include <nuttx/net/arp.h>
|
||||||
#include <nuttx/net/netdev.h>
|
#include <nuttx/net/netdev.h>
|
||||||
@@ -189,6 +190,42 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* These definitions are used to enable the PHY interrupts */
|
||||||
|
|
||||||
|
#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
|
||||||
|
# if defined( CONFIG_ETH0_PHY_AM79C874)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_KS8721)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_KSZ8041)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_KSZ8051)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_KSZ8061)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_KSZ8081)
|
||||||
|
# define MII_INT_REG MII_KSZ8081_INT
|
||||||
|
# define MII_INT_SETEN MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN
|
||||||
|
# define MII_INT_CLREN 0
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_KSZ90x1)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_DP83848C)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_LAN8720)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_LAN8740)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_LAN8740A)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_LAN8742A)
|
||||||
|
# error missing logic
|
||||||
|
# elif defined( CONFIG_ETH0_PHY_DM9161)
|
||||||
|
# error missing logic
|
||||||
|
# else
|
||||||
|
# error unknown PHY
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_STM32_ETH_PTP
|
#ifdef CONFIG_STM32_ETH_PTP
|
||||||
# warning "CONFIG_STM32_ETH_PTP is not yet supported"
|
# warning "CONFIG_STM32_ETH_PTP is not yet supported"
|
||||||
#endif
|
#endif
|
||||||
@@ -2889,8 +2926,19 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
|
|||||||
#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
|
#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
|
||||||
static int stm32_phyintenable(struct stm32_ethmac_s *priv)
|
static int stm32_phyintenable(struct stm32_ethmac_s *priv)
|
||||||
{
|
{
|
||||||
#warning Missing logic
|
uint16_t phyval;
|
||||||
return -ENOSYS;
|
int ret;
|
||||||
|
|
||||||
|
ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_INT_REG, &phyval);
|
||||||
|
if (ret == OK)
|
||||||
|
{
|
||||||
|
/* Enable link up/down interrupts */
|
||||||
|
|
||||||
|
ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_INT_REG,
|
||||||
|
(phyval & ~MII_INT_CLREN) | MII_INT_SETEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1050,10 +1050,10 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: up_restoreusartint
|
* Name: up_setusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
static inline void up_setusartint(struct up_dev_s *priv, uint16_t ie)
|
||||||
{
|
{
|
||||||
uint32_t cr;
|
uint32_t cr;
|
||||||
|
|
||||||
@@ -1074,12 +1074,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
|||||||
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_restoreusartint
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
up_setusartint(priv, ie);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: up_disableusartint
|
* Name: up_disableusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
if (ie)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@@ -1116,7 +1135,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
up_restoreusartint(priv, 0);
|
up_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev);
|
|||||||
|
|
||||||
/* Device Structures, Instantiation */
|
/* Device Structures, Instantiation */
|
||||||
|
|
||||||
const struct i2c_ops_s stm32_i2c_ops =
|
static const struct i2c_ops_s stm32_i2c_ops =
|
||||||
{
|
{
|
||||||
.transfer = stm32_i2c_transfer
|
.transfer = stm32_i2c_transfer
|
||||||
#ifdef CONFIG_I2C_RESET
|
#ifdef CONFIG_I2C_RESET
|
||||||
@@ -340,7 +340,7 @@ static const struct stm32_i2c_config_s stm32_i2c1_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_i2c_priv_s stm32_i2c1_priv =
|
static struct stm32_i2c_priv_s stm32_i2c1_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32_i2c_ops,
|
.ops = &stm32_i2c_ops,
|
||||||
.config = &stm32_i2c1_config,
|
.config = &stm32_i2c1_config,
|
||||||
@@ -369,7 +369,7 @@ static const struct stm32_i2c_config_s stm32_i2c2_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_i2c_priv_s stm32_i2c2_priv =
|
static struct stm32_i2c_priv_s stm32_i2c2_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32_i2c_ops,
|
.ops = &stm32_i2c_ops,
|
||||||
.config = &stm32_i2c2_config,
|
.config = &stm32_i2c2_config,
|
||||||
@@ -398,7 +398,7 @@ static const struct stm32_i2c_config_s stm32_i2c3_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_i2c_priv_s stm32_i2c3_priv =
|
static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32_i2c_ops,
|
.ops = &stm32_i2c_ops,
|
||||||
.config = &stm32_i2c3_config,
|
.config = &stm32_i2c3_config,
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ static int stm32f0_i2c_reset(FAR struct i2c_master_s *dev);
|
|||||||
|
|
||||||
/* Device Structures, Instantiation */
|
/* Device Structures, Instantiation */
|
||||||
|
|
||||||
const struct i2c_ops_s stm32f0_i2c_ops =
|
static const struct i2c_ops_s stm32f0_i2c_ops =
|
||||||
{
|
{
|
||||||
.transfer = stm32f0_i2c_transfer
|
.transfer = stm32f0_i2c_transfer
|
||||||
#ifdef CONFIG_I2C_RESET
|
#ifdef CONFIG_I2C_RESET
|
||||||
@@ -328,7 +328,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c1_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32f0_i2c_priv_s stm32f0_i2c1_priv =
|
static struct stm32f0_i2c_priv_s stm32f0_i2c1_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32f0_i2c_ops,
|
.ops = &stm32f0_i2c_ops,
|
||||||
.config = &stm32f0_i2c1_config,
|
.config = &stm32f0_i2c1_config,
|
||||||
@@ -356,7 +356,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c2_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32f0_i2c_priv_s stm32f0_i2c2_priv =
|
static struct stm32f0_i2c_priv_s stm32f0_i2c2_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32f0_i2c_ops,
|
.ops = &stm32f0_i2c_ops,
|
||||||
.config = &stm32f0_i2c2_config,
|
.config = &stm32f0_i2c2_config,
|
||||||
@@ -384,7 +384,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c3_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32f0_i2c_priv_s stm32f0_i2c3_priv =
|
static struct stm32f0_i2c_priv_s stm32f0_i2c3_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32f0_i2c_ops,
|
.ops = &stm32f0_i2c_ops,
|
||||||
.config = &stm32f0_i2c3_config,
|
.config = &stm32f0_i2c3_config,
|
||||||
|
|||||||
@@ -769,10 +769,10 @@ static inline void stm32f0serial_putreg(FAR struct stm32f0_serial_s *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32f0serial_restoreusartint
|
* Name: stm32f0serial_setusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv,
|
static void stm32f0serial_setusartint(FAR struct stm32f0_serial_s *priv,
|
||||||
uint16_t ie)
|
uint16_t ie)
|
||||||
{
|
{
|
||||||
uint32_t cr;
|
uint32_t cr;
|
||||||
@@ -794,13 +794,33 @@ static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv,
|
|||||||
stm32f0serial_putreg(priv, STM32F0_USART_CR3_OFFSET, cr);
|
stm32f0serial_putreg(priv, STM32F0_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32f0serial_restoreusartint
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv,
|
||||||
|
uint16_t ie)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
stm32f0serial_setusartint(priv, ie);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32f0serial_disableusartint
|
* Name: stm32f0serial_disableusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv,
|
static void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv,
|
||||||
FAR uint16_t *ie)
|
FAR uint16_t *ie)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
if (ie)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@@ -837,7 +857,9 @@ static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *pr
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
stm32f0serial_restoreusartint(priv, 0);
|
stm32f0serial_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
+126
-126
@@ -290,7 +290,7 @@
|
|||||||
#if !defined(CONFIG_STM32F7_I2CTIMEOSEC) && !defined(CONFIG_STM32F7_I2CTIMEOMS)
|
#if !defined(CONFIG_STM32F7_I2CTIMEOSEC) && !defined(CONFIG_STM32F7_I2CTIMEOMS)
|
||||||
# define CONFIG_STM32F7_I2CTIMEOSEC 0
|
# define CONFIG_STM32F7_I2CTIMEOSEC 0
|
||||||
# define CONFIG_STM32F7_I2CTIMEOMS 500 /* Default is 500 milliseconds */
|
# define CONFIG_STM32F7_I2CTIMEOMS 500 /* Default is 500 milliseconds */
|
||||||
# warning "Using Defualt 500 Ms Timeout"
|
# warning "Using Default 500 Ms Timeout"
|
||||||
#elif !defined(CONFIG_STM32F7_I2CTIMEOSEC)
|
#elif !defined(CONFIG_STM32F7_I2CTIMEOSEC)
|
||||||
# define CONFIG_STM32F7_I2CTIMEOSEC 0 /* User provided milliseconds */
|
# define CONFIG_STM32F7_I2CTIMEOSEC 0 /* User provided milliseconds */
|
||||||
#elif !defined(CONFIG_STM32F7_I2CTIMEOMS)
|
#elif !defined(CONFIG_STM32F7_I2CTIMEOMS)
|
||||||
@@ -445,7 +445,7 @@ struct stm32_i2c_priv_s
|
|||||||
|
|
||||||
struct stm32_i2c_inst_s
|
struct stm32_i2c_inst_s
|
||||||
{
|
{
|
||||||
struct i2c_ops_s *ops; /* Standard I2C operations */
|
const struct i2c_ops_s *ops; /* Standard I2C operations */
|
||||||
struct stm32_i2c_priv_s *priv; /* Common driver private data structure */
|
struct stm32_i2c_priv_s *priv; /* Common driver private data structure */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -495,7 +495,7 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
|
|||||||
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
|
||||||
int count);
|
int count);
|
||||||
#ifdef CONFIG_I2C_RESET
|
#ifdef CONFIG_I2C_RESET
|
||||||
int stm32_i2c_reset(FAR struct i2c_master_s * dev);
|
static int stm32_i2c_reset(FAR struct i2c_master_s * dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@@ -516,7 +516,7 @@ static const struct stm32_i2c_config_s stm32_i2c1_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_i2c_priv_s stm32_i2c1_priv =
|
static struct stm32_i2c_priv_s stm32_i2c1_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c1_config,
|
.config = &stm32_i2c1_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
@@ -545,7 +545,7 @@ static const struct stm32_i2c_config_s stm32_i2c2_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_i2c_priv_s stm32_i2c2_priv =
|
static struct stm32_i2c_priv_s stm32_i2c2_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c2_config,
|
.config = &stm32_i2c2_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
@@ -574,7 +574,7 @@ static const struct stm32_i2c_config_s stm32_i2c3_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_i2c_priv_s stm32_i2c3_priv =
|
static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c3_config,
|
.config = &stm32_i2c3_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
@@ -603,7 +603,7 @@ static const struct stm32_i2c_config_s stm32_i2c4_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32_i2c_priv_s stm32_i2c4_priv =
|
static struct stm32_i2c_priv_s stm32_i2c4_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c4_config,
|
.config = &stm32_i2c4_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
@@ -620,7 +620,7 @@ struct stm32_i2c_priv_s stm32_i2c4_priv =
|
|||||||
|
|
||||||
/* Device Structures, Instantiation */
|
/* Device Structures, Instantiation */
|
||||||
|
|
||||||
struct i2c_ops_s stm32_i2c_ops =
|
static const struct i2c_ops_s stm32_i2c_ops =
|
||||||
{
|
{
|
||||||
.transfer = stm32_i2c_transfer
|
.transfer = stm32_i2c_transfer
|
||||||
#ifdef CONFIG_I2C_RESET
|
#ifdef CONFIG_I2C_RESET
|
||||||
@@ -2485,6 +2485,124 @@ static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
|
|||||||
return stm32_i2c_process(dev, msgs, count);
|
return stm32_i2c_process(dev, msgs, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: stm32_i2c_reset
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Reset an I2C bus
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_I2C_RESET
|
||||||
|
static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
|
||||||
|
{
|
||||||
|
struct stm32_i2c_priv_s * priv;
|
||||||
|
unsigned int clock_count;
|
||||||
|
unsigned int stretch_count;
|
||||||
|
uint32_t scl_gpio;
|
||||||
|
uint32_t sda_gpio;
|
||||||
|
int ret = ERROR;
|
||||||
|
|
||||||
|
ASSERT(dev);
|
||||||
|
|
||||||
|
/* Get I2C private structure */
|
||||||
|
|
||||||
|
priv = ((struct stm32_i2c_inst_s *)dev)->priv;
|
||||||
|
|
||||||
|
/* Our caller must own a ref */
|
||||||
|
|
||||||
|
ASSERT(priv->refs > 0);
|
||||||
|
|
||||||
|
/* Lock out other clients */
|
||||||
|
|
||||||
|
stm32_i2c_sem_wait(dev);
|
||||||
|
|
||||||
|
/* De-init the port */
|
||||||
|
|
||||||
|
stm32_i2c_deinit(priv);
|
||||||
|
|
||||||
|
/* Use GPIO configuration to un-wedge the bus */
|
||||||
|
|
||||||
|
scl_gpio = MKI2C_OUTPUT(priv->config->scl_pin);
|
||||||
|
sda_gpio = MKI2C_OUTPUT(priv->config->sda_pin);
|
||||||
|
|
||||||
|
/* Let SDA go high */
|
||||||
|
|
||||||
|
stm32_gpiowrite(sda_gpio, 1);
|
||||||
|
|
||||||
|
/* Clock the bus until any slaves currently driving it let it go. */
|
||||||
|
|
||||||
|
clock_count = 0;
|
||||||
|
while (!stm32_gpioread(sda_gpio))
|
||||||
|
{
|
||||||
|
/* Give up if we have tried too hard */
|
||||||
|
|
||||||
|
if (clock_count++ > 10)
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sniff to make sure that clock stretching has finished.
|
||||||
|
*
|
||||||
|
* If the bus never relaxes, the reset has failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
stretch_count = 0;
|
||||||
|
while (!stm32_gpioread(scl_gpio))
|
||||||
|
{
|
||||||
|
/* Give up if we have tried too hard */
|
||||||
|
|
||||||
|
if (stretch_count++ > 10)
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
up_udelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Drive SCL low */
|
||||||
|
|
||||||
|
stm32_gpiowrite(scl_gpio, 0);
|
||||||
|
up_udelay(10);
|
||||||
|
|
||||||
|
/* Drive SCL high again */
|
||||||
|
|
||||||
|
stm32_gpiowrite(scl_gpio, 1);
|
||||||
|
up_udelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate a start followed by a stop to reset slave
|
||||||
|
* state machines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
stm32_gpiowrite(sda_gpio, 0);
|
||||||
|
up_udelay(10);
|
||||||
|
stm32_gpiowrite(scl_gpio, 0);
|
||||||
|
up_udelay(10);
|
||||||
|
stm32_gpiowrite(scl_gpio, 1);
|
||||||
|
up_udelay(10);
|
||||||
|
stm32_gpiowrite(sda_gpio, 1);
|
||||||
|
up_udelay(10);
|
||||||
|
|
||||||
|
/* Revert the GPIO configuration. */
|
||||||
|
|
||||||
|
stm32_unconfiggpio(sda_gpio);
|
||||||
|
stm32_unconfiggpio(scl_gpio);
|
||||||
|
|
||||||
|
/* Re-init the port */
|
||||||
|
|
||||||
|
stm32_i2c_init(priv);
|
||||||
|
ret = OK;
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
|
/* Release the port for re-use by other clients */
|
||||||
|
|
||||||
|
stm32_i2c_sem_post(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_I2C_RESET */
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@@ -2608,122 +2726,4 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* Name: stm32_i2c_reset
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Reset an I2C bus
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_I2C_RESET
|
|
||||||
int stm32_i2c_reset(FAR struct i2c_master_s * dev)
|
|
||||||
{
|
|
||||||
struct stm32_i2c_priv_s * priv;
|
|
||||||
unsigned int clock_count;
|
|
||||||
unsigned int stretch_count;
|
|
||||||
uint32_t scl_gpio;
|
|
||||||
uint32_t sda_gpio;
|
|
||||||
int ret = ERROR;
|
|
||||||
|
|
||||||
ASSERT(dev);
|
|
||||||
|
|
||||||
/* Get I2C private structure */
|
|
||||||
|
|
||||||
priv = ((struct stm32_i2c_inst_s *)dev)->priv;
|
|
||||||
|
|
||||||
/* Our caller must own a ref */
|
|
||||||
|
|
||||||
ASSERT(priv->refs > 0);
|
|
||||||
|
|
||||||
/* Lock out other clients */
|
|
||||||
|
|
||||||
stm32_i2c_sem_wait(dev);
|
|
||||||
|
|
||||||
/* De-init the port */
|
|
||||||
|
|
||||||
stm32_i2c_deinit(priv);
|
|
||||||
|
|
||||||
/* Use GPIO configuration to un-wedge the bus */
|
|
||||||
|
|
||||||
scl_gpio = MKI2C_OUTPUT(priv->config->scl_pin);
|
|
||||||
sda_gpio = MKI2C_OUTPUT(priv->config->sda_pin);
|
|
||||||
|
|
||||||
/* Let SDA go high */
|
|
||||||
|
|
||||||
stm32_gpiowrite(sda_gpio, 1);
|
|
||||||
|
|
||||||
/* Clock the bus until any slaves currently driving it let it go. */
|
|
||||||
|
|
||||||
clock_count = 0;
|
|
||||||
while (!stm32_gpioread(sda_gpio))
|
|
||||||
{
|
|
||||||
/* Give up if we have tried too hard */
|
|
||||||
|
|
||||||
if (clock_count++ > 10)
|
|
||||||
{
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sniff to make sure that clock stretching has finished.
|
|
||||||
*
|
|
||||||
* If the bus never relaxes, the reset has failed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
stretch_count = 0;
|
|
||||||
while (!stm32_gpioread(scl_gpio))
|
|
||||||
{
|
|
||||||
/* Give up if we have tried too hard */
|
|
||||||
|
|
||||||
if (stretch_count++ > 10)
|
|
||||||
{
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
up_udelay(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drive SCL low */
|
|
||||||
|
|
||||||
stm32_gpiowrite(scl_gpio, 0);
|
|
||||||
up_udelay(10);
|
|
||||||
|
|
||||||
/* Drive SCL high again */
|
|
||||||
|
|
||||||
stm32_gpiowrite(scl_gpio, 1);
|
|
||||||
up_udelay(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate a start followed by a stop to reset slave
|
|
||||||
* state machines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
stm32_gpiowrite(sda_gpio, 0);
|
|
||||||
up_udelay(10);
|
|
||||||
stm32_gpiowrite(scl_gpio, 0);
|
|
||||||
up_udelay(10);
|
|
||||||
stm32_gpiowrite(scl_gpio, 1);
|
|
||||||
up_udelay(10);
|
|
||||||
stm32_gpiowrite(sda_gpio, 1);
|
|
||||||
up_udelay(10);
|
|
||||||
|
|
||||||
/* Revert the GPIO configuration. */
|
|
||||||
|
|
||||||
stm32_unconfiggpio(sda_gpio);
|
|
||||||
stm32_unconfiggpio(scl_gpio);
|
|
||||||
|
|
||||||
/* Re-init the port */
|
|
||||||
|
|
||||||
stm32_i2c_init(priv);
|
|
||||||
ret = OK;
|
|
||||||
|
|
||||||
out:
|
|
||||||
|
|
||||||
/* Release the port for re-use by other clients */
|
|
||||||
|
|
||||||
stm32_i2c_sem_post(dev);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_I2C_RESET */
|
|
||||||
|
|
||||||
#endif /* CONFIG_STM32F7_I2C1 || CONFIG_STM32F7_I2C2 || CONFIG_STM32F7_I2C3 */
|
#endif /* CONFIG_STM32F7_I2C1 || CONFIG_STM32F7_I2C2 || CONFIG_STM32F7_I2C3 */
|
||||||
|
|||||||
@@ -1096,10 +1096,10 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: up_restoreusartint
|
* Name: up_setusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
static inline void up_setusartint(struct up_dev_s *priv, uint16_t ie)
|
||||||
{
|
{
|
||||||
uint32_t cr;
|
uint32_t cr;
|
||||||
|
|
||||||
@@ -1120,12 +1120,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
|||||||
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_restoreusartint
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
up_setusartint(priv, ie);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: up_disableusartint
|
* Name: up_disableusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
if (ie)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@@ -1162,7 +1181,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
up_restoreusartint(priv, 0);
|
up_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -2868,6 +2889,7 @@ int up_putc(int ch)
|
|||||||
|
|
||||||
up_lowputc(ch);
|
up_lowputc(ch);
|
||||||
up_restoreusartint(priv, ie);
|
up_restoreusartint(priv, ie);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1008,14 +1008,6 @@ config STM32L4_SPI3
|
|||||||
select SPI
|
select SPI
|
||||||
select STM32L4_SPI
|
select STM32L4_SPI
|
||||||
|
|
||||||
config STM32L4_USART1
|
|
||||||
bool "USART1"
|
|
||||||
default n
|
|
||||||
depends on STM32L4_HAVE_USART1
|
|
||||||
select ARCH_HAVE_SERIAL_TERMIOS
|
|
||||||
select USART1_SERIALDRIVER
|
|
||||||
select STM32L4_USART
|
|
||||||
|
|
||||||
config STM32L4_USART2
|
config STM32L4_USART2
|
||||||
bool "USART2"
|
bool "USART2"
|
||||||
default n
|
default n
|
||||||
@@ -1155,8 +1147,9 @@ config STM32L4_TIM8
|
|||||||
config STM32L4_USART1
|
config STM32L4_USART1
|
||||||
bool "USART1"
|
bool "USART1"
|
||||||
default n
|
default n
|
||||||
select USART1_SERIALDRIVER
|
depends on STM32L4_HAVE_USART1
|
||||||
select ARCH_HAVE_SERIAL_TERMIOS
|
select ARCH_HAVE_SERIAL_TERMIOS
|
||||||
|
select USART1_SERIALDRIVER
|
||||||
select STM32L4_USART
|
select STM32L4_USART
|
||||||
|
|
||||||
config STM32L4_TIM15
|
config STM32L4_TIM15
|
||||||
@@ -1306,9 +1299,6 @@ config STM32L4_SAI2PLL
|
|||||||
Set this true and provide configuration parameters in
|
Set this true and provide configuration parameters in
|
||||||
board.h to use this PLL.
|
board.h to use this PLL.
|
||||||
|
|
||||||
config STM32L4_USART
|
|
||||||
bool
|
|
||||||
|
|
||||||
menu "Timer Configuration"
|
menu "Timer Configuration"
|
||||||
|
|
||||||
if SCHED_TICKLESS
|
if SCHED_TICKLESS
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ static int stm32l4_i2c_reset(FAR struct i2c_master_s *dev);
|
|||||||
|
|
||||||
/* Device Structures, Instantiation */
|
/* Device Structures, Instantiation */
|
||||||
|
|
||||||
const struct i2c_ops_s stm32l4_i2c_ops =
|
static const struct i2c_ops_s stm32l4_i2c_ops =
|
||||||
{
|
{
|
||||||
.transfer = stm32l4_i2c_transfer
|
.transfer = stm32l4_i2c_transfer
|
||||||
#ifdef CONFIG_I2C_RESET
|
#ifdef CONFIG_I2C_RESET
|
||||||
@@ -329,7 +329,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c1_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32l4_i2c_priv_s stm32l4_i2c1_priv =
|
static struct stm32l4_i2c_priv_s stm32l4_i2c1_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32l4_i2c_ops,
|
.ops = &stm32l4_i2c_ops,
|
||||||
.config = &stm32l4_i2c1_config,
|
.config = &stm32l4_i2c1_config,
|
||||||
@@ -358,7 +358,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c2_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32l4_i2c_priv_s stm32l4_i2c2_priv =
|
static struct stm32l4_i2c_priv_s stm32l4_i2c2_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32l4_i2c_ops,
|
.ops = &stm32l4_i2c_ops,
|
||||||
.config = &stm32l4_i2c2_config,
|
.config = &stm32l4_i2c2_config,
|
||||||
@@ -387,7 +387,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c3_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32l4_i2c_priv_s stm32l4_i2c3_priv =
|
static struct stm32l4_i2c_priv_s stm32l4_i2c3_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32l4_i2c_ops,
|
.ops = &stm32l4_i2c_ops,
|
||||||
.config = &stm32l4_i2c3_config,
|
.config = &stm32l4_i2c3_config,
|
||||||
@@ -416,7 +416,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c4_config =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32l4_i2c_priv_s stm32l4_i2c4_priv =
|
static struct stm32l4_i2c_priv_s stm32l4_i2c4_priv =
|
||||||
{
|
{
|
||||||
.ops = &stm32l4_i2c_ops,
|
.ops = &stm32l4_i2c_ops,
|
||||||
.config = &stm32l4_i2c4_config,
|
.config = &stm32l4_i2c4_config,
|
||||||
@@ -1831,7 +1831,7 @@ static int stm32l4_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg
|
|||||||
* dev - Device-specific state data
|
* dev - Device-specific state data
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero (OK) on success; a negated errno value on failure.
|
* Zero (OK) on success; negative value on failure.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -765,11 +765,11 @@ static inline void stm32l4serial_putreg(FAR struct stm32l4_serial_s *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32l4serial_restoreusartint
|
* Name: stm32l4serial_setusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv,
|
static inline void stm32l4serial_setusartint(FAR struct stm32l4_serial_s *priv,
|
||||||
uint16_t ie)
|
uint16_t ie)
|
||||||
{
|
{
|
||||||
uint32_t cr;
|
uint32_t cr;
|
||||||
|
|
||||||
@@ -790,13 +790,33 @@ static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv,
|
|||||||
stm32l4serial_putreg(priv, STM32L4_USART_CR3_OFFSET, cr);
|
stm32l4serial_putreg(priv, STM32L4_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_restoreusartint
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv,
|
||||||
|
uint16_t ie)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
stm32l4serial_setusartint(priv, ie);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32l4serial_disableusartint
|
* Name: stm32l4serial_disableusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv,
|
static void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv,
|
||||||
FAR uint16_t *ie)
|
FAR uint16_t *ie)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
if (ie)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@@ -833,7 +853,9 @@ static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *pr
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
stm32l4serial_restoreusartint(priv, 0);
|
stm32l4serial_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -163,14 +163,14 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
|
|||||||
{
|
{
|
||||||
/* Allocate memory to hold a copy of the .dtor section */
|
/* Allocate memory to hold a copy of the .dtor section */
|
||||||
|
|
||||||
loadinfo->ctoralloc = (binfmt_dtor_t *)kumm_malloc(dtorsize);
|
loadinfo->dtoralloc = (binfmt_dtor_t *)kumm_malloc(dtorsize);
|
||||||
if (!loadinfo->ctoralloc)
|
if (!loadinfo->dtoralloc)
|
||||||
{
|
{
|
||||||
berr("Failed to allocate memory for .dtors\n");
|
berr("Failed to allocate memory for .dtors\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc;
|
loadinfo->dtors = (binfmt_dtor_t *)loadinfo->dtoralloc;
|
||||||
|
|
||||||
/* Read the section header table into memory */
|
/* Read the section header table into memory */
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
#include <nuttx/sched.h>
|
||||||
#include <nuttx/syslog/syslog.h>
|
#include <nuttx/syslog/syslog.h>
|
||||||
|
|
||||||
#include "syslog.h"
|
#include "syslog.h"
|
||||||
@@ -100,8 +103,21 @@ ssize_t syslog_default_write(FAR const char *buffer, size_t buflen)
|
|||||||
ssize_t syslog_write(FAR const char *buffer, size_t buflen)
|
ssize_t syslog_write(FAR const char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SYSLOG_WRITE
|
#ifdef CONFIG_SYSLOG_WRITE
|
||||||
return g_syslog_channel->sc_write(buffer, buflen);
|
if (!up_interrupt_context() && !sched_idletask())
|
||||||
#else
|
{
|
||||||
return syslog_default_write(buffer, buflen);
|
#ifdef CONFIG_SYSLOG_INTBUFFER
|
||||||
|
/* Flush any characters that may have been added to the interrupt
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void)syslog_flush_intbuffer(g_syslog_channel, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return g_syslog_channel->sc_write(buffer, buflen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return syslog_default_write(buffer, buflen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -63,12 +63,15 @@ config IOB_THROTTLE
|
|||||||
config IOB_DEBUG
|
config IOB_DEBUG
|
||||||
bool "Force I/O buffer debug"
|
bool "Force I/O buffer debug"
|
||||||
default n
|
default n
|
||||||
depends on DEBUG_FEATURES
|
depends on DEBUG_FEATURES && !SYSLOG_BUFFER
|
||||||
---help---
|
---help---
|
||||||
This option will force debug output from I/O buffer logic. This
|
This option will force debug output from I/O buffer logic. This
|
||||||
is not normally something that would want to do but is convenient
|
is not normally something that would want to do but is convenient
|
||||||
if you are debugging the I/O buffer logic and do not want to get
|
if you are debugging the I/O buffer logic and do not want to get
|
||||||
overloaded with other un-related debug output.
|
overloaded with other un-related debug output.
|
||||||
|
|
||||||
|
NOTE that this selection is not avaiable with IOBs are being used
|
||||||
|
to syslog buffering logic (CONFIG_SYSLOG_BUFFER=y)!
|
||||||
|
|
||||||
endif # MM_IOB
|
endif # MM_IOB
|
||||||
endmenu # Common I/O buffer support
|
endmenu # Common I/O buffer support
|
||||||
|
|||||||
+9
-1
@@ -91,10 +91,18 @@
|
|||||||
|
|
||||||
extern FAR struct iob_s *g_iob_freelist;
|
extern FAR struct iob_s *g_iob_freelist;
|
||||||
|
|
||||||
/* A list of all free, unallocated I/O buffer queue containers */
|
/* A list of I/O buffers that are committed for allocation */
|
||||||
|
|
||||||
|
extern FAR struct iob_s *g_iob_committed;
|
||||||
|
|
||||||
#if CONFIG_IOB_NCHAINS > 0
|
#if CONFIG_IOB_NCHAINS > 0
|
||||||
|
/* A list of all free, unallocated I/O buffer queue containers */
|
||||||
|
|
||||||
extern FAR struct iob_qentry_s *g_iob_freeqlist;
|
extern FAR struct iob_qentry_s *g_iob_freeqlist;
|
||||||
|
|
||||||
|
/* A list of I/O buffer queue containers that are committed for allocation */
|
||||||
|
|
||||||
|
extern FAR struct iob_s *g_iob_qcommitted;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Counting semaphores that tracks the number of free IOBs/qentries */
|
/* Counting semaphores that tracks the number of free IOBs/qentries */
|
||||||
|
|||||||
+91
-47
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* mm/iob/iob_alloc.c
|
* mm/iob/iob_alloc.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -54,6 +54,47 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: iob_alloc_committed
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate an I/O buffer by taking the buffer at the head of the committed
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static FAR struct iob_s *iob_alloc_committed(void)
|
||||||
|
{
|
||||||
|
FAR struct iob_s *iob = NULL;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
/* We don't know what context we are called from so we use extreme measures
|
||||||
|
* to protect the committed list: We disable interrupts very briefly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Take the I/O buffer from the head of the committed list */
|
||||||
|
|
||||||
|
iob = g_iob_committed;
|
||||||
|
if (iob != NULL)
|
||||||
|
{
|
||||||
|
/* Remove the I/O buffer from the committed list */
|
||||||
|
|
||||||
|
g_iob_committed = iob->io_flink;
|
||||||
|
|
||||||
|
/* Put the I/O buffer in a known state */
|
||||||
|
|
||||||
|
iob->io_flink = NULL; /* Not in a chain */
|
||||||
|
iob->io_len = 0; /* Length of the data in the entry */
|
||||||
|
iob->io_offset = 0; /* Offset to the beginning of data */
|
||||||
|
iob->io_pktlen = 0; /* Total length of the packet */
|
||||||
|
}
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
return iob;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_allocwait
|
* Name: iob_allocwait
|
||||||
*
|
*
|
||||||
@@ -85,73 +126,76 @@ static FAR struct iob_s *iob_allocwait(bool throttled)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
do
|
|
||||||
|
/* Try to get an I/O buffer. If successful, the semaphore count will be
|
||||||
|
* decremented atomically.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iob = iob_tryalloc(throttled);
|
||||||
|
while (ret == OK && iob == NULL)
|
||||||
{
|
{
|
||||||
/* Try to get an I/O buffer. If successful, the semaphore count
|
/* If not successful, then the semaphore count was less than or equal
|
||||||
* will be decremented atomically.
|
* to zero (meaning that there are no free buffers). We need to wait
|
||||||
|
* for an I/O buffer to be released and placed in the committed
|
||||||
|
* list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
iob = iob_tryalloc(throttled);
|
ret = sem_wait(sem);
|
||||||
if (!iob)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
/* If not successful, then the semaphore count was less than or
|
int errcode = get_errno();
|
||||||
* equal to zero (meaning that there are no free buffers). We
|
|
||||||
* need to wait for an I/O buffer to be released when the semaphore
|
/* EINTR is not an error! EINTR simply means that we were
|
||||||
* count will be incremented.
|
* awakened by a signal and we should try again.
|
||||||
|
*
|
||||||
|
* REVISIT: Many end-user interfaces are required to return with
|
||||||
|
* an error if EINTR is set. Most uses of this function are in
|
||||||
|
* internal, non-user logic. But are there cases where the error
|
||||||
|
* should be returned.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ret = sem_wait(sem);
|
if (errcode == EINTR)
|
||||||
if (ret < 0)
|
|
||||||
{
|
{
|
||||||
int errcode = get_errno();
|
/* Force a success indication so that we will continue looping. */
|
||||||
|
|
||||||
/* EINTR is not an error! EINTR simply means that we were
|
ret = 0;
|
||||||
* awakened by a signal and we should try again.
|
|
||||||
*
|
|
||||||
* REVISIT: Many end-user interfaces are required to return
|
|
||||||
* with an error if EINTR is set. Most uses of this function
|
|
||||||
* is in internal, non-user logic. But are there cases where
|
|
||||||
* the error should be returned.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (errcode == EINTR)
|
|
||||||
{
|
|
||||||
/* Force a success indication so that we will continue
|
|
||||||
* looping.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Stop the loop and return a error */
|
|
||||||
|
|
||||||
DEBUGASSERT(errcode > 0);
|
|
||||||
ret = -errcode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* When we wake up from wait successfully, an I/O buffer was
|
/* Stop the loop and return a error */
|
||||||
* returned to the free list. However, if there are concurrent
|
|
||||||
* allocations from interrupt handling, then I suspect that
|
DEBUGASSERT(errcode > 0);
|
||||||
* there is a race condition. But no harm, we will just wait
|
ret = -errcode;
|
||||||
* again in that case.
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* When we wake up from wait successfully, an I/O buffer was
|
||||||
|
* freed and we hold a count for one IOB. Unless somehting
|
||||||
|
* failed, we should have an IOB waiting for us in the
|
||||||
|
* committed list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iob = iob_alloc_committed();
|
||||||
|
DEBUGASSERT(iob != NULL);
|
||||||
|
|
||||||
|
if (iob == NULL)
|
||||||
|
{
|
||||||
|
/* This should not fail, but we allow for that possibility to
|
||||||
|
* handle any potential, non-obvious race condition. Perhaps
|
||||||
|
* the free IOB ended up in the g_iob_free list?
|
||||||
*
|
*
|
||||||
* We need release our count so that it is available to
|
* We need release our count so that it is available to
|
||||||
* iob_tryalloc(), perhaps allowing another thread to take our
|
* iob_tryalloc(), perhaps allowing another thread to take our
|
||||||
* count. In that event, iob_tryalloc() will fail above and
|
* count. In that event, iob_tryalloc() will fail above and
|
||||||
* we will have to wait again.
|
* we will have to wait again.
|
||||||
*
|
|
||||||
* TODO: Consider a design modification to permit us to
|
|
||||||
* complete the allocation without losing our count.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sem_post(sem);
|
sem_post(sem);
|
||||||
|
iob = iob_tryalloc(throttled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (ret == OK && iob == NULL);
|
|
||||||
|
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
return iob;
|
return iob;
|
||||||
@@ -225,7 +269,7 @@ FAR struct iob_s *iob_tryalloc(bool throttled)
|
|||||||
/* Take the I/O buffer from the head of the free list */
|
/* Take the I/O buffer from the head of the free list */
|
||||||
|
|
||||||
iob = g_iob_freelist;
|
iob = g_iob_freelist;
|
||||||
if (iob)
|
if (iob != NULL)
|
||||||
{
|
{
|
||||||
/* Remove the I/O buffer from the free list and decrement the
|
/* Remove the I/O buffer from the free list and decrement the
|
||||||
* counting semaphore(s) that tracks the number of available
|
* counting semaphore(s) that tracks the number of available
|
||||||
|
|||||||
+90
-47
@@ -55,6 +55,44 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: iob_alloc_qcommitted
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate an I/O buffer by taking the buffer at the head of the committed
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static FAR struct iob_qentry_s *iob_alloc_qcommitted(void)
|
||||||
|
{
|
||||||
|
FAR struct iob_qentry_s *iobq = NULL;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
/* We don't know what context we are called from so we use extreme measures
|
||||||
|
* to protect the committed list: We disable interrupts very briefly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Take the I/O buffer from the head of the committed list */
|
||||||
|
|
||||||
|
iobq = g_iob_qcommitted;
|
||||||
|
if (iobq != NULL)
|
||||||
|
{
|
||||||
|
/* Remove the I/O buffer from the committed list */
|
||||||
|
|
||||||
|
g_iob_qcommitted = iobq->qe_flink;
|
||||||
|
|
||||||
|
/* Put the I/O buffer in a known state */
|
||||||
|
|
||||||
|
iobq->qe_head = NULL; /* Nothing is contained */
|
||||||
|
}
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
return iobq;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_allocwait_qentry
|
* Name: iob_allocwait_qentry
|
||||||
*
|
*
|
||||||
@@ -78,73 +116,78 @@ static FAR struct iob_qentry_s *iob_allocwait_qentry(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
do
|
|
||||||
|
/* Try to get an I/O buffer chain container. If successful, the semaphore
|
||||||
|
* count will bedecremented atomically.
|
||||||
|
*/
|
||||||
|
|
||||||
|
qentry = iob_tryalloc_qentry();
|
||||||
|
while (ret == OK && qentry == NULL)
|
||||||
{
|
{
|
||||||
/* Try to get an I/O buffer chain container. If successful, the
|
/* If not successful, then the semaphore count was less than or equal
|
||||||
* semaphore count will be decremented atomically.
|
* to zero (meaning that there are no free buffers). We need to wait
|
||||||
|
* for an I/O buffer chain container to be released when the
|
||||||
|
* semaphore count will be incremented.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
qentry = iob_tryalloc_qentry();
|
ret = sem_wait(&g_qentry_sem);
|
||||||
if (!qentry)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
/* If not successful, then the semaphore count was less than or
|
int errcode = get_errno();
|
||||||
* equal to zero (meaning that there are no free buffers). We
|
|
||||||
* need to wait for an I/O buffer chain container to be released
|
/* EINTR is not an error! EINTR simply means that we were
|
||||||
* when the semaphore count will be incremented.
|
* awakened by a signal and we should try again.
|
||||||
|
*
|
||||||
|
* REVISIT: Many end-user interfaces are required to return
|
||||||
|
* with an error if EINTR is set. Most uses of this function
|
||||||
|
* is in internal, non-user logic. But are there cases where
|
||||||
|
* the error should be returned.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ret = sem_wait(&g_qentry_sem);
|
if (errcode == EINTR)
|
||||||
if (ret < 0)
|
|
||||||
{
|
{
|
||||||
int errcode = get_errno();
|
/* Force a success indication so that we will continue
|
||||||
|
* looping.
|
||||||
/* EINTR is not an error! EINTR simply means that we were
|
|
||||||
* awakened by a signal and we should try again.
|
|
||||||
*
|
|
||||||
* REVISIT: Many end-user interfaces are required to return
|
|
||||||
* with an error if EINTR is set. Most uses of this function
|
|
||||||
* is in internal, non-user logic. But are there cases where
|
|
||||||
* the error should be returned.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (errcode == EINTR)
|
ret = 0;
|
||||||
{
|
|
||||||
/* Force a success indication so that we will continue
|
|
||||||
* looping.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Stop the loop and return a error */
|
|
||||||
|
|
||||||
DEBUGASSERT(errcode > 0);
|
|
||||||
ret = -errcode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* When we wake up from wait successfully, an I/O buffer chain
|
/* Stop the loop and return a error */
|
||||||
* container was returned to the free list. However, if there
|
|
||||||
* are concurrent allocations from interrupt handling, then I
|
DEBUGASSERT(errcode > 0);
|
||||||
* suspect that there is a race condition. But no harm, we
|
ret = -errcode;
|
||||||
* will just wait again in that case.
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* When we wake up from wait successfully, an I/O buffer chain container was
|
||||||
|
* freed and we hold a count for one IOB. Unless somehting
|
||||||
|
* failed, we should have an IOB waiting for us in the
|
||||||
|
* committed list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
qentry = iob_alloc_qcommitted();
|
||||||
|
DEBUGASSERT(qentry != NULL);
|
||||||
|
|
||||||
|
if (qentry == NULL)
|
||||||
|
{
|
||||||
|
/* This should not fail, but we allow for that possibility to
|
||||||
|
* handle any potential, non-obvious race condition. Perhaps
|
||||||
|
* the free IOB ended up in the g_iob_free list?
|
||||||
*
|
*
|
||||||
* We need release our count so that it is available to
|
* We need release our count so that it is available to
|
||||||
* iob_tryalloc_qentry(), perhaps allowing another thread to
|
* iob_tryalloc(), perhaps allowing another thread to take our
|
||||||
* take our count. In that event, iob_tryalloc_qentry() will
|
* count. In that event, iob_tryalloc() will fail above and
|
||||||
* fail above and we will have to wait again.
|
* we will have to wait again.
|
||||||
*
|
|
||||||
* TODO: Consider a design modification to permit us to
|
|
||||||
* complete the allocation without losing our count.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sem_post(&g_qentry_sem);
|
sem_post(&g_qentry_sem);
|
||||||
|
qentry = iob_tryalloc_qentry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (ret == OK && !qentry);
|
|
||||||
|
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
return qentry;
|
return qentry;
|
||||||
|
|||||||
+27
-7
@@ -74,7 +74,7 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
|
|||||||
* the next entry.
|
* the next entry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (next)
|
if (next != NULL)
|
||||||
{
|
{
|
||||||
/* Copy and decrement the total packet length, being careful to
|
/* Copy and decrement the total packet length, being careful to
|
||||||
* do nothing too crazy.
|
* do nothing too crazy.
|
||||||
@@ -101,16 +101,36 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
|
|||||||
next, next->io_pktlen, next->io_len);
|
next, next->io_pktlen, next->io_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the I/O buffer by adding it to the head of the free list. We don't
|
/* Free the I/O buffer by adding it to the head of the free or the
|
||||||
* know what context we are called from so we use extreme measures to
|
* committed list. We don't know what context we are called from so
|
||||||
* protect the free list: We disable interrupts very briefly.
|
* we use extreme measures to protect the free list: We disable
|
||||||
|
* interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
iob->io_flink = g_iob_freelist;
|
|
||||||
g_iob_freelist = iob;
|
|
||||||
|
|
||||||
/* Signal that an IOB is available */
|
/* Which list? If there is a task waiting for an IOB, then put
|
||||||
|
* the IOB on either the free list or on the committed list where
|
||||||
|
* it is reserved for that allocation (and not available to
|
||||||
|
* iob_tryalloc()).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (g_iob_sem.semcount < 0)
|
||||||
|
{
|
||||||
|
iob->io_flink = g_iob_committed;
|
||||||
|
g_iob_committed = iob;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iob->io_flink = g_iob_freelist;
|
||||||
|
g_iob_freelist = iob;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signal that an IOB is available. If there is a thread waiting
|
||||||
|
* for an IOB, this will wake up exactly one thread. The semaphore
|
||||||
|
* count will correctly indicated that the awakened task owns an
|
||||||
|
* IOB and should find it in the committed list.
|
||||||
|
*/
|
||||||
|
|
||||||
sem_post(&g_iob_sem);
|
sem_post(&g_iob_sem);
|
||||||
#if CONFIG_IOB_THROTTLE > 0
|
#if CONFIG_IOB_THROTTLE > 0
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* mm/iob/iob_free_qentry.c
|
* mm/iob/iob_free_qentry.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -68,16 +68,37 @@ FAR struct iob_qentry_s *iob_free_qentry(FAR struct iob_qentry_s *iobq)
|
|||||||
FAR struct iob_qentry_s *nextq = iobq->qe_flink;
|
FAR struct iob_qentry_s *nextq = iobq->qe_flink;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
/* Free the I/O buffer chain container by adding it to the head of the free
|
/* Free the I/O buffer chain container by adding it to the head of the
|
||||||
* list. We don't know what context we are called from so we use extreme
|
* free or the committed list. We don't know what context we are called
|
||||||
* measures to protect the free list: We disable interrupts very briefly.
|
* from so we use extreme measures to protect the free list: We disable
|
||||||
|
* interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
iobq->qe_flink = g_iob_freeqlist;
|
|
||||||
g_iob_freeqlist = iobq;
|
|
||||||
|
|
||||||
/* Signal that an I/O buffer chain container is available */
|
/* Which list? If there is a task waiting for an IOB, then put
|
||||||
|
* the IOB on either the free list or on the committed list where
|
||||||
|
* it is reserved for that allocation (and not available to
|
||||||
|
* iob_tryalloc()).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (g_iob_sem.semcount < 0)
|
||||||
|
{
|
||||||
|
iobq->qe_flink = g_iob_qcommitted;
|
||||||
|
g_iob_qcommitted = iobq;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iobq->qe_flink = g_iob_freeqlist;
|
||||||
|
g_iob_freeqlist = iobq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signal that an I/O buffer chain container is available. If there
|
||||||
|
* is a thread waiting for an I/O buffer chain container, this will
|
||||||
|
* wake up exactly one thread. The semaphore count will correctly
|
||||||
|
* indicated that the awakened task owns an I/O buffer chain container
|
||||||
|
* and should find it in the committed list.
|
||||||
|
*/
|
||||||
|
|
||||||
sem_post(&g_qentry_sem);
|
sem_post(&g_qentry_sem);
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
|
|||||||
+22
-3
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* mm/iob/iob_initialize.c
|
* mm/iob/iob_initialize.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -46,6 +46,14 @@
|
|||||||
|
|
||||||
#include "iob.h"
|
#include "iob.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
# define NULL ((FAR void *)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -65,10 +73,18 @@ static struct iob_qentry_s g_iob_qpool[CONFIG_IOB_NCHAINS];
|
|||||||
|
|
||||||
FAR struct iob_s *g_iob_freelist;
|
FAR struct iob_s *g_iob_freelist;
|
||||||
|
|
||||||
/* A list of all free, unallocated I/O buffer queue containers */
|
/* A list of I/O buffers that are committed for allocation */
|
||||||
|
|
||||||
|
FAR struct iob_s *g_iob_committed;
|
||||||
|
|
||||||
#if CONFIG_IOB_NCHAINS > 0
|
#if CONFIG_IOB_NCHAINS > 0
|
||||||
|
/* A list of all free, unallocated I/O buffer queue containers */
|
||||||
|
|
||||||
FAR struct iob_qentry_s *g_iob_freeqlist;
|
FAR struct iob_qentry_s *g_iob_freeqlist;
|
||||||
|
|
||||||
|
/* A list of I/O buffer queue containers that are committed for allocation */
|
||||||
|
|
||||||
|
FAR struct iob_s *g_iob_qcommitted;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Counting semaphores that tracks the number of free IOBs/qentries */
|
/* Counting semaphores that tracks the number of free IOBs/qentries */
|
||||||
@@ -114,8 +130,9 @@ void iob_initialize(void)
|
|||||||
g_iob_freelist = iob;
|
g_iob_freelist = iob;
|
||||||
}
|
}
|
||||||
|
|
||||||
sem_init(&g_iob_sem, 0, CONFIG_IOB_NBUFFERS);
|
g_iob_committed = NULL;
|
||||||
|
|
||||||
|
sem_init(&g_iob_sem, 0, CONFIG_IOB_NBUFFERS);
|
||||||
#if CONFIG_IOB_THROTTLE > 0
|
#if CONFIG_IOB_THROTTLE > 0
|
||||||
sem_init(&g_throttle_sem, 0, CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE);
|
sem_init(&g_throttle_sem, 0, CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE);
|
||||||
#endif
|
#endif
|
||||||
@@ -133,6 +150,8 @@ void iob_initialize(void)
|
|||||||
g_iob_freeqlist = iobq;
|
g_iob_freeqlist = iobq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_iob_qcommitted = NULL;
|
||||||
|
|
||||||
sem_init(&g_qentry_sem, 0, CONFIG_IOB_NCHAINS);
|
sem_init(&g_qentry_sem, 0, CONFIG_IOB_NCHAINS);
|
||||||
#endif
|
#endif
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|||||||
@@ -61,9 +61,12 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile);
|
static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile);
|
||||||
static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile);
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
static int netprocfs_inet4addresses(FAR struct netprocfs_file_s *netfile);
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_NET_IPv6
|
#ifdef CONFIG_NET_IPv6
|
||||||
static int netprocfs_dripaddress(FAR struct netprocfs_file_s *netfile);
|
static int netprocfs_inet6address(FAR struct netprocfs_file_s *netfile);
|
||||||
|
static int netprocfs_inet6draddress(FAR struct netprocfs_file_s *netfile);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_NETDEV_STATISTICS
|
#ifdef CONFIG_NETDEV_STATISTICS
|
||||||
static int netprocfs_rxstatistics_header(FAR struct netprocfs_file_s *netfile);
|
static int netprocfs_rxstatistics_header(FAR struct netprocfs_file_s *netfile);
|
||||||
@@ -83,10 +86,13 @@ static int netprocfs_errors(FAR struct netprocfs_file_s *netfile);
|
|||||||
|
|
||||||
static const linegen_t g_linegen[] =
|
static const linegen_t g_linegen[] =
|
||||||
{
|
{
|
||||||
netprocfs_linklayer,
|
netprocfs_linklayer
|
||||||
netprocfs_ipaddresses
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
, netprocfs_inet4addresses
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_NET_IPv6
|
#ifdef CONFIG_NET_IPv6
|
||||||
, netprocfs_dripaddress
|
, netprocfs_inet6address
|
||||||
|
, netprocfs_inet6draddress
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_NETDEV_STATISTICS
|
#ifdef CONFIG_NETDEV_STATISTICS
|
||||||
, netprocfs_rxstatistics_header,
|
, netprocfs_rxstatistics_header,
|
||||||
@@ -255,25 +261,19 @@ static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: netprocfs_ipaddresses
|
* Name: netprocfs_inet4addresses
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile)
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
static int netprocfs_inet4addresses(FAR struct netprocfs_file_s *netfile)
|
||||||
{
|
{
|
||||||
FAR struct net_driver_s *dev;
|
FAR struct net_driver_s *dev;
|
||||||
#ifdef CONFIG_NET_IPv4
|
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
|
||||||
char addrstr[INET6_ADDRSTRLEN];
|
|
||||||
uint8_t preflen;
|
|
||||||
#endif
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
|
DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
|
||||||
dev = netfile->dev;
|
dev = netfile->dev;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
|
||||||
/* Show the IPv4 address */
|
/* Show the IPv4 address */
|
||||||
|
|
||||||
addr.s_addr = dev->d_ipaddr;
|
addr.s_addr = dev->d_ipaddr;
|
||||||
@@ -291,9 +291,25 @@ static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile)
|
|||||||
addr.s_addr = dev->d_netmask;
|
addr.s_addr = dev->d_netmask;
|
||||||
len += snprintf(&netfile->line[len], NET_LINELEN - len,
|
len += snprintf(&netfile->line[len], NET_LINELEN - len,
|
||||||
"Mask:%s\n\n", inet_ntoa(addr));
|
"Mask:%s\n\n", inet_ntoa(addr));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netprocfs_inet6address
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
static int netprocfs_inet6address(FAR struct netprocfs_file_s *netfile)
|
||||||
|
{
|
||||||
|
FAR struct net_driver_s *dev;
|
||||||
|
char addrstr[INET6_ADDRSTRLEN];
|
||||||
|
uint8_t preflen;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
|
||||||
|
dev = netfile->dev;
|
||||||
|
|
||||||
/* Convert the 128 network mask to a human friendly prefix length */
|
/* Convert the 128 network mask to a human friendly prefix length */
|
||||||
|
|
||||||
preflen = net_ipv6_mask2pref(dev->d_ipv6netmask);
|
preflen = net_ipv6_mask2pref(dev->d_ipv6netmask);
|
||||||
@@ -305,17 +321,17 @@ static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile)
|
|||||||
len += snprintf(&netfile->line[len], NET_LINELEN - len,
|
len += snprintf(&netfile->line[len], NET_LINELEN - len,
|
||||||
"\tinet6 addr:%s/%d\n", addrstr, preflen);
|
"\tinet6 addr:%s/%d\n", addrstr, preflen);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: netprocfs_dripaddress
|
* Name: netprocfs_inet6draddress
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
#ifdef CONFIG_NET_IPv6
|
||||||
static int netprocfs_dripaddress(FAR struct netprocfs_file_s *netfile)
|
static int netprocfs_inet6draddress(FAR struct netprocfs_file_s *netfile)
|
||||||
{
|
{
|
||||||
FAR struct net_driver_s *dev;
|
FAR struct net_driver_s *dev;
|
||||||
char addrstr[INET6_ADDRSTRLEN];
|
char addrstr[INET6_ADDRSTRLEN];
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@
|
|||||||
* to handle the longest line generated by this logic.
|
* to handle the longest line generated by this logic.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NET_LINELEN 64
|
#define NET_LINELEN 80
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Type Definitions
|
* Public Type Definitions
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask)
|
|||||||
* 1..6 7..2 3..8 9..4 5..0 1..6 7..2 3..8
|
* 1..6 7..2 3..8 9..4 5..0 1..6 7..2 3..8
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = 0; i < 7; i++)
|
for (i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
/* bit = {0, 16, 32, 48, 64, 80, 96, 112} */
|
/* bit = {0, 16, 32, 48, 64, 80, 96, 112} */
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask)
|
|||||||
{
|
{
|
||||||
/* Eg. preflen = 38, bit = {0, 16, 32} */
|
/* Eg. preflen = 38, bit = {0, 16, 32} */
|
||||||
|
|
||||||
if (preflen > (bit + 16))
|
if (preflen >= (bit + 16))
|
||||||
{
|
{
|
||||||
/* Eg. preflen = 38, bit = {0, 16} */
|
/* Eg. preflen = 38, bit = {0, 16} */
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask)
|
|||||||
{
|
{
|
||||||
/* Eg. preflen = 38, bit = {32}
|
/* Eg. preflen = 38, bit = {32}
|
||||||
* bit - preflen = 6
|
* bit - preflen = 6
|
||||||
* make = 0xffff << (16-6)
|
* mask = 0xffff << (16-6)
|
||||||
* = 0xfc00
|
* = 0xfc00
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Eg. preflen=38, bit= {48, 64, 80, 112} */
|
/* Eg. preflen=38, bit= {48, 64, 80, 96, 112} */
|
||||||
|
|
||||||
mask[i] = 0x0000;
|
mask[i] = 0x0000;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user