Merge remote-tracking branch 'origin/master' into ieee802154

This commit is contained in:
Gregory Nutt
2017-05-19 07:17:37 -06:00
23 changed files with 668 additions and 316 deletions
+39 -2
View File
@@ -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
@@ -25,7 +25,7 @@ nuttx/:
(12) Libraries (libc/, libm/)
(10) File system/Generic drivers (fs/, drivers/)
(9) Graphics Subsystem (graphics/)
(2) Build system / Toolchains
(3) Build system / Toolchains
(3) Linux/Cywgin simulation (arch/sim)
(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.
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/)
^^^^^^^^^^^^^^^^^^^^^^^^
+50 -2
View File
@@ -54,6 +54,7 @@
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include <nuttx/wqueue.h>
#include <nuttx/net/phy.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -189,6 +190,42 @@
# 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
# warning "CONFIG_STM32_ETH_PTP is not yet supported"
#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)
static int stm32_phyintenable(struct stm32_ethmac_s *priv)
{
#warning Missing logic
return -ENOSYS;
uint16_t phyval;
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
+25 -4
View File
@@ -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;
@@ -1074,12 +1074,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
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
****************************************************************************/
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)
{
uint32_t cr1;
@@ -1116,7 +1135,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
/* Disable all interrupts */
up_restoreusartint(priv, 0);
up_setusartint(priv, 0);
leave_critical_section(flags);
}
/****************************************************************************
+4 -4
View File
@@ -318,7 +318,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev);
/* Device Structures, Instantiation */
const struct i2c_ops_s stm32_i2c_ops =
static const struct i2c_ops_s stm32_i2c_ops =
{
.transfer = stm32_i2c_transfer
#ifdef CONFIG_I2C_RESET
@@ -340,7 +340,7 @@ static const struct stm32_i2c_config_s stm32_i2c1_config =
#endif
};
struct stm32_i2c_priv_s stm32_i2c1_priv =
static struct stm32_i2c_priv_s stm32_i2c1_priv =
{
.ops = &stm32_i2c_ops,
.config = &stm32_i2c1_config,
@@ -369,7 +369,7 @@ static const struct stm32_i2c_config_s stm32_i2c2_config =
#endif
};
struct stm32_i2c_priv_s stm32_i2c2_priv =
static struct stm32_i2c_priv_s stm32_i2c2_priv =
{
.ops = &stm32_i2c_ops,
.config = &stm32_i2c2_config,
@@ -398,7 +398,7 @@ static const struct stm32_i2c_config_s stm32_i2c3_config =
#endif
};
struct stm32_i2c_priv_s stm32_i2c3_priv =
static struct stm32_i2c_priv_s stm32_i2c3_priv =
{
.ops = &stm32_i2c_ops,
.config = &stm32_i2c3_config,
+4 -4
View File
@@ -307,7 +307,7 @@ static int stm32f0_i2c_reset(FAR struct i2c_master_s *dev);
/* Device Structures, Instantiation */
const struct i2c_ops_s stm32f0_i2c_ops =
static const struct i2c_ops_s stm32f0_i2c_ops =
{
.transfer = stm32f0_i2c_transfer
#ifdef CONFIG_I2C_RESET
@@ -328,7 +328,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c1_config =
#endif
};
struct stm32f0_i2c_priv_s stm32f0_i2c1_priv =
static struct stm32f0_i2c_priv_s stm32f0_i2c1_priv =
{
.ops = &stm32f0_i2c_ops,
.config = &stm32f0_i2c1_config,
@@ -356,7 +356,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c2_config =
#endif
};
struct stm32f0_i2c_priv_s stm32f0_i2c2_priv =
static struct stm32f0_i2c_priv_s stm32f0_i2c2_priv =
{
.ops = &stm32f0_i2c_ops,
.config = &stm32f0_i2c2_config,
@@ -384,7 +384,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c3_config =
#endif
};
struct stm32f0_i2c_priv_s stm32f0_i2c3_priv =
static struct stm32f0_i2c_priv_s stm32f0_i2c3_priv =
{
.ops = &stm32f0_i2c_ops,
.config = &stm32f0_i2c3_config,
+27 -5
View File
@@ -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)
{
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);
}
/****************************************************************************
* 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
****************************************************************************/
static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv,
FAR uint16_t *ie)
static void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv,
FAR uint16_t *ie)
{
irqstate_t flags;
flags = enter_critical_section();
if (ie)
{
uint32_t cr1;
@@ -837,7 +857,9 @@ static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *pr
/* Disable all interrupts */
stm32f0serial_restoreusartint(priv, 0);
stm32f0serial_setusartint(priv, 0);
leave_critical_section(flags);
}
/****************************************************************************
+126 -126
View File
@@ -290,7 +290,7 @@
#if !defined(CONFIG_STM32F7_I2CTIMEOSEC) && !defined(CONFIG_STM32F7_I2CTIMEOMS)
# define CONFIG_STM32F7_I2CTIMEOSEC 0
# 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)
# define CONFIG_STM32F7_I2CTIMEOSEC 0 /* User provided milliseconds */
#elif !defined(CONFIG_STM32F7_I2CTIMEOMS)
@@ -445,7 +445,7 @@ struct stm32_i2c_priv_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 */
};
@@ -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,
int count);
#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
/************************************************************************************
@@ -516,7 +516,7 @@ static const struct stm32_i2c_config_s stm32_i2c1_config =
#endif
};
struct stm32_i2c_priv_s stm32_i2c1_priv =
static struct stm32_i2c_priv_s stm32_i2c1_priv =
{
.config = &stm32_i2c1_config,
.refs = 0,
@@ -545,7 +545,7 @@ static const struct stm32_i2c_config_s stm32_i2c2_config =
#endif
};
struct stm32_i2c_priv_s stm32_i2c2_priv =
static struct stm32_i2c_priv_s stm32_i2c2_priv =
{
.config = &stm32_i2c2_config,
.refs = 0,
@@ -574,7 +574,7 @@ static const struct stm32_i2c_config_s stm32_i2c3_config =
#endif
};
struct stm32_i2c_priv_s stm32_i2c3_priv =
static struct stm32_i2c_priv_s stm32_i2c3_priv =
{
.config = &stm32_i2c3_config,
.refs = 0,
@@ -603,7 +603,7 @@ static const struct stm32_i2c_config_s stm32_i2c4_config =
#endif
};
struct stm32_i2c_priv_s stm32_i2c4_priv =
static struct stm32_i2c_priv_s stm32_i2c4_priv =
{
.config = &stm32_i2c4_config,
.refs = 0,
@@ -620,7 +620,7 @@ struct stm32_i2c_priv_s stm32_i2c4_priv =
/* Device Structures, Instantiation */
struct i2c_ops_s stm32_i2c_ops =
static const struct i2c_ops_s stm32_i2c_ops =
{
.transfer = stm32_i2c_transfer
#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);
}
/************************************************************************************
* 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
************************************************************************************/
@@ -2608,122 +2726,4 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
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 */
+26 -4
View File
@@ -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;
@@ -1120,12 +1120,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
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
****************************************************************************/
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)
{
uint32_t cr1;
@@ -1162,7 +1181,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
/* 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_restoreusartint(priv, ie);
#endif
return ch;
}
+2 -12
View File
@@ -1008,14 +1008,6 @@ config STM32L4_SPI3
select 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
bool "USART2"
default n
@@ -1155,8 +1147,9 @@ config STM32L4_TIM8
config STM32L4_USART1
bool "USART1"
default n
select USART1_SERIALDRIVER
depends on STM32L4_HAVE_USART1
select ARCH_HAVE_SERIAL_TERMIOS
select USART1_SERIALDRIVER
select STM32L4_USART
config STM32L4_TIM15
@@ -1306,9 +1299,6 @@ config STM32L4_SAI2PLL
Set this true and provide configuration parameters in
board.h to use this PLL.
config STM32L4_USART
bool
menu "Timer Configuration"
if SCHED_TICKLESS
+6 -6
View File
@@ -307,7 +307,7 @@ static int stm32l4_i2c_reset(FAR struct i2c_master_s *dev);
/* Device Structures, Instantiation */
const struct i2c_ops_s stm32l4_i2c_ops =
static const struct i2c_ops_s stm32l4_i2c_ops =
{
.transfer = stm32l4_i2c_transfer
#ifdef CONFIG_I2C_RESET
@@ -329,7 +329,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c1_config =
#endif
};
struct stm32l4_i2c_priv_s stm32l4_i2c1_priv =
static struct stm32l4_i2c_priv_s stm32l4_i2c1_priv =
{
.ops = &stm32l4_i2c_ops,
.config = &stm32l4_i2c1_config,
@@ -358,7 +358,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c2_config =
#endif
};
struct stm32l4_i2c_priv_s stm32l4_i2c2_priv =
static struct stm32l4_i2c_priv_s stm32l4_i2c2_priv =
{
.ops = &stm32l4_i2c_ops,
.config = &stm32l4_i2c2_config,
@@ -387,7 +387,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c3_config =
#endif
};
struct stm32l4_i2c_priv_s stm32l4_i2c3_priv =
static struct stm32l4_i2c_priv_s stm32l4_i2c3_priv =
{
.ops = &stm32l4_i2c_ops,
.config = &stm32l4_i2c3_config,
@@ -416,7 +416,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c4_config =
#endif
};
struct stm32l4_i2c_priv_s stm32l4_i2c4_priv =
static struct stm32l4_i2c_priv_s stm32l4_i2c4_priv =
{
.ops = &stm32l4_i2c_ops,
.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
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
* Zero (OK) on success; negative value on failure.
*
************************************************************************************/
+28 -6
View File
@@ -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,
uint16_t ie)
static inline void stm32l4serial_setusartint(FAR struct stm32l4_serial_s *priv,
uint16_t ie)
{
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);
}
/****************************************************************************
* 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
****************************************************************************/
static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv,
FAR uint16_t *ie)
static void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv,
FAR uint16_t *ie)
{
irqstate_t flags;
flags = enter_critical_section();
if (ie)
{
uint32_t cr1;
@@ -833,7 +853,9 @@ static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *pr
/* Disable all interrupts */
stm32l4serial_restoreusartint(priv, 0);
stm32l4serial_setusartint(priv, 0);
leave_critical_section(flags);
}
/****************************************************************************
+3 -3
View File
@@ -163,14 +163,14 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
{
/* Allocate memory to hold a copy of the .dtor section */
loadinfo->ctoralloc = (binfmt_dtor_t *)kumm_malloc(dtorsize);
if (!loadinfo->ctoralloc)
loadinfo->dtoralloc = (binfmt_dtor_t *)kumm_malloc(dtorsize);
if (!loadinfo->dtoralloc)
{
berr("Failed to allocate memory for .dtors\n");
return -ENOMEM;
}
loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc;
loadinfo->dtors = (binfmt_dtor_t *)loadinfo->dtoralloc;
/* Read the section header table into memory */
+19 -3
View File
@@ -40,6 +40,9 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/syslog/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)
{
#ifdef CONFIG_SYSLOG_WRITE
return g_syslog_channel->sc_write(buffer, buflen);
#else
return syslog_default_write(buffer, buflen);
if (!up_interrupt_context() && !sched_idletask())
{
#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
return g_syslog_channel->sc_write(buffer, buflen);
}
else
#endif
{
return syslog_default_write(buffer, buflen);
}
}
+4 -1
View File
@@ -63,12 +63,15 @@ config IOB_THROTTLE
config IOB_DEBUG
bool "Force I/O buffer debug"
default n
depends on DEBUG_FEATURES
depends on DEBUG_FEATURES && !SYSLOG_BUFFER
---help---
This option will force debug output from I/O buffer logic. This
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
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
endmenu # Common I/O buffer support
+9 -1
View File
@@ -91,10 +91,18 @@
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
/* A list of all free, unallocated I/O buffer queue containers */
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
/* Counting semaphores that tracks the number of free IOBs/qentries */
+91 -47
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* Redistribution and use in source and binary forms, with or without
@@ -54,6 +54,47 @@
* 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
*
@@ -85,73 +126,76 @@ static FAR struct iob_s *iob_allocwait(bool throttled)
*/
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
* will be decremented atomically.
/* If not successful, then the semaphore count was less than or equal
* 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);
if (!iob)
ret = sem_wait(sem);
if (ret < 0)
{
/* If not successful, then the semaphore count was less than or
* 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
* count will be incremented.
int errcode = get_errno();
/* 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 are in
* internal, non-user logic. But are there cases where the error
* should be returned.
*/
ret = sem_wait(sem);
if (ret < 0)
if (errcode == EINTR)
{
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)
{
/* 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;
}
ret = 0;
}
else
{
/* When we wake up from wait successfully, an I/O buffer was
* returned to the free list. However, if there are concurrent
* allocations from interrupt handling, then I suspect that
* there is a race condition. But no harm, we will just wait
* again in that case.
/* Stop the loop and return a error */
DEBUGASSERT(errcode > 0);
ret = -errcode;
}
}
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
* iob_tryalloc(), perhaps allowing another thread to take our
* count. In that event, iob_tryalloc() will fail above and
* 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);
iob = iob_tryalloc(throttled);
}
}
}
while (ret == OK && iob == NULL);
leave_critical_section(flags);
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 */
iob = g_iob_freelist;
if (iob)
if (iob != NULL)
{
/* Remove the I/O buffer from the free list and decrement the
* counting semaphore(s) that tracks the number of available
+90 -47
View File
@@ -55,6 +55,44 @@
* 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
*
@@ -78,73 +116,78 @@ static FAR struct iob_qentry_s *iob_allocwait_qentry(void)
*/
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
* semaphore count will be decremented atomically.
/* If not successful, then the semaphore count was less than or equal
* 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();
if (!qentry)
ret = sem_wait(&g_qentry_sem);
if (ret < 0)
{
/* If not successful, then the semaphore count was less than or
* equal 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.
int errcode = get_errno();
/* 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.
*/
ret = sem_wait(&g_qentry_sem);
if (ret < 0)
if (errcode == EINTR)
{
int errcode = get_errno();
/* 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.
/* Force a success indication so that we will continue
* looping.
*/
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;
}
ret = 0;
}
else
{
/* When we wake up from wait successfully, an I/O buffer chain
* container was returned to the free list. However, if there
* are concurrent allocations from interrupt handling, then I
* suspect that there is a race condition. But no harm, we
* will just wait again in that case.
/* Stop the loop and return a error */
DEBUGASSERT(errcode > 0);
ret = -errcode;
}
}
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
* iob_tryalloc_qentry(), perhaps allowing another thread to
* take our count. In that event, iob_tryalloc_qentry() will
* fail above and we will have to wait again.
*
* TODO: Consider a design modification to permit us to
* complete the allocation without losing our count.
* iob_tryalloc(), perhaps allowing another thread to take our
* count. In that event, iob_tryalloc() will fail above and
* we will have to wait again.
*/
sem_post(&g_qentry_sem);
qentry = iob_tryalloc_qentry();
}
}
}
while (ret == OK && !qentry);
leave_critical_section(flags);
return qentry;
+27 -7
View File
@@ -74,7 +74,7 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
* the next entry.
*/
if (next)
if (next != NULL)
{
/* Copy and decrement the total packet length, being careful to
* 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);
}
/* Free the I/O buffer by adding it to the head of the free list. We don't
* know what context we are called from so we use extreme measures to
* protect the free list: We disable interrupts very briefly.
/* Free the I/O buffer by adding it to the head of the free or the
* committed list. We don't know what context we are called from so
* we use extreme measures to protect the free list: We disable
* interrupts very briefly.
*/
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);
#if CONFIG_IOB_THROTTLE > 0
+28 -7
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* 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;
irqstate_t flags;
/* Free the I/O buffer chain container by adding it to the head of the free
* list. We don't know what context we are called from so we use extreme
* measures to protect the free list: We disable interrupts very briefly.
/* Free the I/O buffer chain container by adding it to the head of the
* free or the committed list. We don't know what context we are called
* from so we use extreme measures to protect the free list: We disable
* interrupts very briefly.
*/
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);
leave_critical_section(flags);
+22 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,14 @@
#include "iob.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef NULL
# define NULL ((FAR void *)0)
#endif
/****************************************************************************
* Private Data
****************************************************************************/
@@ -65,10 +73,18 @@ static struct iob_qentry_s g_iob_qpool[CONFIG_IOB_NCHAINS];
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
/* A list of all free, unallocated I/O buffer queue containers */
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
/* Counting semaphores that tracks the number of free IOBs/qentries */
@@ -114,8 +130,9 @@ void iob_initialize(void)
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
sem_init(&g_throttle_sem, 0, CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE);
#endif
@@ -133,6 +150,8 @@ void iob_initialize(void)
g_iob_freeqlist = iobq;
}
g_iob_qcommitted = NULL;
sem_init(&g_qentry_sem, 0, CONFIG_IOB_NCHAINS);
#endif
initialized = true;
+33 -17
View File
@@ -61,9 +61,12 @@
****************************************************************************/
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
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
#ifdef CONFIG_NETDEV_STATISTICS
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[] =
{
netprocfs_linklayer,
netprocfs_ipaddresses
netprocfs_linklayer
#ifdef CONFIG_NET_IPv4
, netprocfs_inet4addresses
#endif
#ifdef CONFIG_NET_IPv6
, netprocfs_dripaddress
, netprocfs_inet6address
, netprocfs_inet6draddress
#endif
#ifdef CONFIG_NETDEV_STATISTICS
, 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;
#ifdef CONFIG_NET_IPv4
struct in_addr addr;
#endif
#ifdef CONFIG_NET_IPv6
char addrstr[INET6_ADDRSTRLEN];
uint8_t preflen;
#endif
int len = 0;
DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
dev = netfile->dev;
#ifdef CONFIG_NET_IPv4
/* Show the IPv4 address */
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;
len += snprintf(&netfile->line[len], NET_LINELEN - len,
"Mask:%s\n\n", inet_ntoa(addr));
return len;
}
#endif
/****************************************************************************
* Name: netprocfs_inet6address
****************************************************************************/
#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 */
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,
"\tinet6 addr:%s/%d\n", addrstr, preflen);
}
#endif
return len;
}
#endif
/****************************************************************************
* Name: netprocfs_dripaddress
* Name: netprocfs_inet6draddress
****************************************************************************/
#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;
char addrstr[INET6_ADDRSTRLEN];
+1 -1
View File
@@ -54,7 +54,7 @@
* to handle the longest line generated by this logic.
*/
#define NET_LINELEN 64
#define NET_LINELEN 80
/****************************************************************************
* Public Type Definitions
+4 -4
View File
@@ -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
*/
for (i = 0; i < 7; i++)
for (i = 0; i < 8; i++)
{
/* 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} */
if (preflen > (bit + 16))
if (preflen >= (bit + 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}
* bit - preflen = 6
* make = 0xffff << (16-6)
* mask = 0xffff << (16-6)
* = 0xfc00
*/
@@ -111,7 +111,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask)
}
else
{
/* Eg. preflen=38, bit= {48, 64, 80, 112} */
/* Eg. preflen=38, bit= {48, 64, 80, 96, 112} */
mask[i] = 0x0000;
}