Merge remote-tracking branch 'nuttx_bitbucket/master'

This commit is contained in:
Masayuki Ishikawa 2017-08-27 19:02:52 +09:00
commit cd946c5712
52 changed files with 2948 additions and 454 deletions

View File

@ -3249,7 +3249,9 @@ config STM32L4_DAC1_TIMER
config STM32L4_DAC1_TIMER_FREQUENCY config STM32L4_DAC1_TIMER_FREQUENCY
int "DAC1 timer frequency" int "DAC1 timer frequency"
default 0 default 100
---help---
DAC1 output frequency. Default: 100Hz
endif endif
@ -3272,7 +3274,9 @@ config STM32L4_DAC2_TIMER
config STM32L4_DAC2_TIMER_FREQUENCY config STM32L4_DAC2_TIMER_FREQUENCY
int "DAC2 timer frequency" int "DAC2 timer frequency"
default 0 default 100
---help---
DAC2 output frequency. Default: 100Hz
endif endif

View File

@ -177,7 +177,7 @@
#elif defined(CONFIG_STM32L4_TIM15_ADC1) #elif defined(CONFIG_STM32L4_TIM15_ADC1)
# define ADC1_HAVE_TIMER 1 # define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM15_BASE # define ADC1_TIMER_BASE STM32L4_TIM15_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM15_CLKIN # define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM15_CLKIN
#else #else
# undef ADC1_HAVE_TIMER # undef ADC1_HAVE_TIMER
#endif #endif
@ -219,7 +219,7 @@
#elif defined(CONFIG_STM32L4_TIM15_ADC2) #elif defined(CONFIG_STM32L4_TIM15_ADC2)
# define ADC2_HAVE_TIMER 1 # define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM15_BASE # define ADC2_TIMER_BASE STM32L4_TIM15_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM15_CLKIN # define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM15_CLKIN
#else #else
# undef ADC2_HAVE_TIMER # undef ADC2_HAVE_TIMER
#endif #endif
@ -261,7 +261,7 @@
#elif defined(CONFIG_STM32L4_TIM15_ADC3) #elif defined(CONFIG_STM32L4_TIM15_ADC3)
# define ADC3_HAVE_TIMER 1 # define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM15_BASE # define ADC3_TIMER_BASE STM32L4_TIM15_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM15_CLKIN # define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM15_CLKIN
#else #else
# undef ADC3_HAVE_TIMER # undef ADC3_HAVE_TIMER
#endif #endif

View File

@ -103,11 +103,12 @@
#ifdef CONFIG_STM32L4_DAC1_DMA #ifdef CONFIG_STM32L4_DAC1_DMA
# if !defined(CONFIG_STM32L4_DAC1_TIMER) # if !defined(CONFIG_STM32L4_DAC1_TIMER)
# warning "A timer number must be specificed in CONFIG_STM32L4_DAC1_TIMER" # warning "A timer number must be specified in CONFIG_STM32L4_DAC1_TIMER"
# undef CONFIG_STM32L4_DAC1_DMA # undef CONFIG_STM32L4_DAC1_DMA
# undef CONFIG_STM32L4_DAC1_TIMER_FREQUENCY # undef CONFIG_STM32L4_DAC1_TIMER_FREQUENCY
# elif !defined(CONFIG_STM32L4_DAC1_TIMER_FREQUENCY) # elif !defined(CONFIG_STM32L4_DAC1_TIMER_FREQUENCY) || \
# warning "A timer frequency must be specificed in CONFIG_STM32L4_DAC1_TIMER_FREQUENCY" (CONFIG_STM32L4_DAC1_TIMER_FREQUENCY < 1)
# warning "A timer frequency (>0) must be specified in CONFIG_STM32L4_DAC1_TIMER_FREQUENCY"
# undef CONFIG_STM32L4_DAC1_DMA # undef CONFIG_STM32L4_DAC1_DMA
# undef CONFIG_STM32L4_DAC1_TIMER # undef CONFIG_STM32L4_DAC1_TIMER
# endif # endif
@ -115,11 +116,12 @@
#ifdef CONFIG_STM32L4_DAC2_DMA #ifdef CONFIG_STM32L4_DAC2_DMA
# if !defined(CONFIG_STM32L4_DAC2_TIMER) # if !defined(CONFIG_STM32L4_DAC2_TIMER)
# warning "A timer number must be specificed in CONFIG_STM32L4_DAC2_TIMER" # warning "A timer number must be specified in CONFIG_STM32L4_DAC2_TIMER"
# undef CONFIG_STM32L4_DAC2_DMA # undef CONFIG_STM32L4_DAC2_DMA
# undef CONFIG_STM32L4_DAC2_TIMER_FREQUENCY # undef CONFIG_STM32L4_DAC2_TIMER_FREQUENCY
# elif !defined(CONFIG_STM32L4_DAC2_TIMER_FREQUENCY) # elif !defined(CONFIG_STM32L4_DAC2_TIMER_FREQUENCY) || \
# warning "A timer frequency must be specificed in CONFIG_STM32L4_DAC2_TIMER_FREQUENCY" (CONFIG_STM32L4_DAC2_TIMER_FREQUENCY < 1)
# warning "A timer frequency (>0) must be specified in CONFIG_STM32L4_DAC2_TIMER_FREQUENCY"
# undef CONFIG_STM32L4_DAC2_DMA # undef CONFIG_STM32L4_DAC2_DMA
# undef CONFIG_STM32L4_DAC2_TIMER # undef CONFIG_STM32L4_DAC2_TIMER
# endif # endif
@ -269,7 +271,7 @@
#endif #endif
/* Calculate timer divider values based upon DACn_TIMER_PCLK_FREQUENCY and /* Calculate timer divider values based upon DACn_TIMER_PCLK_FREQUENCY and
* CONFIG_STM32_DACn_TIMER_FREQUENCY. * CONFIG_STM32L4_DACn_TIMER_FREQUENCY.
*/ */
#warning "Missing Logic" #warning "Missing Logic"
@ -312,6 +314,7 @@ struct stm32_chan_s
DMA_HANDLE dma; /* Allocated DMA channel */ DMA_HANDLE dma; /* Allocated DMA channel */
uint32_t tbase; /* Timer base address */ uint32_t tbase; /* Timer base address */
uint32_t tfrequency; /* Timer frequency */ uint32_t tfrequency; /* Timer frequency */
int result; /* DMA result */
uint16_t dmabuffer[CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE]; /* DMA transfer buffer */ uint16_t dmabuffer[CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE]; /* DMA transfer buffer */
#endif #endif
}; };
@ -323,9 +326,10 @@ struct stm32_chan_s
/* DAC Register access */ /* DAC Register access */
#ifdef HAVE_DMA #ifdef HAVE_DMA
static uint32_t tim_getreg(FAR struct stm32_chan_s *chan, int offset); static inline void tim_putreg(FAR struct stm32_chan_s *chan, int offset,
static void tim_putreg(FAR struct stm32_chan_s *chan, int offset, uint32_t value);
uint32_t value); static inline void tim_modifyreg(FAR struct stm32_chan_s *chan, int offset,
uint32_t clearbits, uint32_t setbits);
#endif #endif
/* DAC methods */ /* DAC methods */
@ -457,7 +461,7 @@ static struct stm32_dac_s g_dacblock;
* Modify the contents of the DAC control register. * Modify the contents of the DAC control register.
* *
* Input Parameters: * Input Parameters:
* priv - Driver state instance * chan - A reference to the DAC channel state data
* clearbits - Bits in the control register to be cleared * clearbits - Bits in the control register to be cleared
* setbits - Bits in the control register to be set * setbits - Bits in the control register to be set
* *
@ -484,28 +488,6 @@ static inline void stm32l4_dac_modify_cr(FAR struct stm32_chan_s *chan,
modifyreg32(chan->cr, clearbits << shift, setbits << shift); modifyreg32(chan->cr, clearbits << shift, setbits << shift);
} }
/****************************************************************************
* Name: tim_getreg
*
* Description:
* Read the value of an DMA timer register.
*
* Input Parameters:
* chan - A reference to the DAC block status
* offset - The offset to the register to read
*
* Returned Value:
* The current contents of the specified register
*
****************************************************************************/
#ifdef HAVE_DMA
static uint32_t tim_getreg(FAR struct stm32_chan_s *chan, int offset)
{
return getreg32(chan->tbase + offset);
}
#endif
/**************************************************************************** /****************************************************************************
* Name: tim_putreg * Name: tim_putreg
* *
@ -513,7 +495,7 @@ static uint32_t tim_getreg(FAR struct stm32_chan_s *chan, int offset)
* Read the value of an DMA timer register. * Read the value of an DMA timer register.
* *
* Input Parameters: * Input Parameters:
* chan - A reference to the DAC block status * chan - A reference to the DAC channel state data
* offset - The offset to the register to read * offset - The offset to the register to read
* *
* Returned Value: * Returned Value:
@ -522,8 +504,8 @@ static uint32_t tim_getreg(FAR struct stm32_chan_s *chan, int offset)
****************************************************************************/ ****************************************************************************/
#ifdef HAVE_DMA #ifdef HAVE_DMA
static void tim_putreg(FAR struct stm32_chan_s *chan, int offset, static inline void tim_putreg(FAR struct stm32_chan_s *chan, int offset,
uint32_t value) uint32_t value)
{ {
putreg32(value, chan->tbase + offset); putreg32(value, chan->tbase + offset);
} }
@ -536,7 +518,7 @@ static void tim_putreg(FAR struct stm32_chan_s *chan, int offset,
* Modify the value of an DMA timer register. * Modify the value of an DMA timer register.
* *
* Input Parameters: * Input Parameters:
* priv - Driver state instance * chan - A reference to the DAC channel state data
* offset - The timer register offset * offset - The timer register offset
* clearbits - Bits in the control register to be cleared * clearbits - Bits in the control register to be cleared
* setbits - Bits in the control register to be set * setbits - Bits in the control register to be set
@ -547,8 +529,8 @@ static void tim_putreg(FAR struct stm32_chan_s *chan, int offset,
****************************************************************************/ ****************************************************************************/
#ifdef HAVE_DMA #ifdef HAVE_DMA
static void tim_modifyreg(FAR struct stm32_chan_s *chan, int offset, static inline void tim_modifyreg(FAR struct stm32_chan_s *chan, int offset,
uint32_t clearbits, uint32_t setbits) uint32_t clearbits, uint32_t setbits)
{ {
modifyreg32(chan->tbase + offset, clearbits, setbits); modifyreg32(chan->tbase + offset, clearbits, setbits);
} }
@ -659,6 +641,48 @@ static void dac_txint(FAR struct dac_dev_s *dev, bool enable)
#ifdef HAVE_DMA #ifdef HAVE_DMA
static void dac_dmatxcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg) static void dac_dmatxcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg)
{ {
struct stm32_chan_s *chan = (struct stm32_chan_s *)arg;
struct dac_dev_s *dev;
DEBUGASSERT(chan);
#ifdef CONFIG_STM32L4_DAC1
if (chan->intf == 0)
{
dev = &g_dac1dev;
}
#if STM32L4_NDAC > 1
else if (chan->intf == 1)
{
dev = &g_dac2dev;
}
#endif
else
#endif /* CONFIG_STM32L4_DAC1 */
#ifdef CONFIG_STM32L4_DAC2
if (chan->intf == 2)
{
dev = &g_dac3dev;
}
else
#endif
{
DEBUGPANIC();
}
DEBUGASSERT(dev->ad_priv == chan);
/* Report the result of the transfer only if the TX callback has not already
* reported an error.
*/
if (chan->result == -EBUSY)
{
/* Save the result of the transfer if no error was previously reported. */
chan->result = (isr & DMA_CHAN_TEIF_BIT) ? -EIO : OK;
dac_txdone(dev);
}
} }
#endif #endif
@ -705,8 +729,9 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg)
stm32l4_dmasetup(chan->dma, chan->dro, (uint32_t)chan->dmabuffer, stm32l4_dmasetup(chan->dma, chan->dro, (uint32_t)chan->dmabuffer,
CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE, DAC_DMA_CONTROL_WORD); CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE, DAC_DMA_CONTROL_WORD);
/* Enable DMA */ /* Start the DMA */
chan->result = -EBUSY;
stm32l4_dmastart(chan->dma, dac_dmatxcallback, chan, false); stm32l4_dmastart(chan->dma, dac_dmatxcallback, chan, false);
/* Enable DMA for DAC Channel */ /* Enable DMA for DAC Channel */
@ -777,7 +802,7 @@ static int dac_timinit(FAR struct stm32_chan_s *chan)
* counter mode (up). * counter mode (up).
*/ */
/* Enable the timer. At most, two of the following cases (pluse the /* Enable the timer. At most, two of the following cases (plus the
* default) will be enabled * default) will be enabled
*/ */
@ -1004,6 +1029,7 @@ static int dac_chaninit(FAR struct stm32_chan_s *chan)
if (ret < 0) if (ret < 0)
{ {
aerr("ERROR: Failed to initialize the DMA timer: %d\n", ret); aerr("ERROR: Failed to initialize the DMA timer: %d\n", ret);
stm32l4_dmafree(chan->dma);
return ret; return ret;
} }
} }

View File

@ -548,7 +548,7 @@ static struct stm32l4_pwmtimer_s g_pwm15dev =
.irq = STM32L4_IRQ_TIM15, .irq = STM32L4_IRQ_TIM15,
#endif #endif
.base = STM32L4_TIM15_BASE, .base = STM32L4_TIM15_BASE,
.pclk = STM32L4_APB1_TIM15_CLKIN, .pclk = STM32L4_APB2_TIM15_CLKIN,
}; };
#endif #endif
@ -574,7 +574,7 @@ static struct stm32l4_pwmtimer_s g_pwm16dev =
.irq = STM32L4_IRQ_TIM16, .irq = STM32L4_IRQ_TIM16,
#endif #endif
.base = STM32L4_TIM16_BASE, .base = STM32L4_TIM16_BASE,
.pclk = STM32L4_APB1_TIM16_CLKIN, .pclk = STM32L4_APB2_TIM16_CLKIN,
}; };
#endif #endif
@ -600,7 +600,7 @@ static struct stm32l4_pwmtimer_s g_pwm17dev =
.irq = STM32L4_IRQ_TIM17, .irq = STM32L4_IRQ_TIM17,
#endif #endif
.base = STM32L4_TIM17_BASE, .base = STM32L4_TIM17_BASE,
.pclk = STM32L4_APB1_TIM17_CLKIN, .pclk = STM32L4_APB2_TIM17_CLKIN,
}; };
#endif #endif

View File

@ -435,8 +435,10 @@ static inline void rcc_enableapb2(void)
regval = getreg32(STM32L4_RCC_APB2ENR); regval = getreg32(STM32L4_RCC_APB2ENR);
#ifdef CONFIG_STM32L4_SYSCFG #if defined(CONFIG_STM32L4_SYSCFG) || defined(CONFIG_STM32L4_COMP)
/* System configuration controller clock enable */ /* System configuration controller, comparators, and voltage reference buffer
* clock enable
*/
regval |= RCC_APB2ENR_SYSCFGEN; regval |= RCC_APB2ENR_SYSCFGEN;
#endif #endif

View File

@ -446,8 +446,10 @@ static inline void rcc_enableapb2(void)
regval = getreg32(STM32L4_RCC_APB2ENR); regval = getreg32(STM32L4_RCC_APB2ENR);
#ifdef CONFIG_STM32L4_SYSCFG #if defined(CONFIG_STM32L4_SYSCFG) || defined(CONFIG_STM32L4_COMP)
/* System configuration controller clock enable */ /* System configuration controller, comparators, and voltage reference buffer
* clock enable
*/
regval |= RCC_APB2ENR_SYSCFGEN; regval |= RCC_APB2ENR_SYSCFGEN;
#endif #endif

View File

@ -491,8 +491,10 @@ static inline void rcc_enableapb2(void)
regval = getreg32(STM32L4_RCC_APB2ENR); regval = getreg32(STM32L4_RCC_APB2ENR);
#ifdef CONFIG_STM32L4_SYSCFG #if defined(CONFIG_STM32L4_SYSCFG) || defined(CONFIG_STM32L4_COMP)
/* System configuration controller clock enable */ /* System configuration controller, comparators, and voltage reference buffer
* clock enable
*/
regval |= RCC_APB2ENR_SYSCFGEN; regval |= RCC_APB2ENR_SYSCFGEN;
#endif #endif

View File

@ -16,6 +16,9 @@ config HOST_X86_64
config HOST_X86 config HOST_X86
bool "x86" bool "x86"
config HOST_ARM
bool "arm"
endchoice # Host CPU Type endchoice # Host CPU Type
config SIM_M32 config SIM_M32

View File

@ -57,10 +57,12 @@
/* Storage order: %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, %rip */ /* Storage order: %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, %rip */
# define XCPTCONTEXT_REGS 8 # define XCPTCONTEXT_REGS 8
#else #elif defined(CONFIG_HOST_X86) || defined(CONFIG_SIM_M32)
/* Storage order: %ebx, %esi, %edi, %ebp, sp, and return PC */ /* Storage order: %ebx, %esi, %edi, %ebp, sp, and return PC */
# define XCPTCONTEXT_REGS 6 # define XCPTCONTEXT_REGS 6
#elif defined(CONFIG_HOST_ARM)
# define XCPTCONTEXT_REGS 16
#endif #endif
/**************************************************************************** /****************************************************************************

View File

@ -47,10 +47,16 @@ ifeq ($(CONFIG_SIM_M32),y)
else else
ASRCS += up_setjmp64.S ASRCS += up_setjmp64.S
endif endif
else endif
ifeq ($(CONFIG_HOST_X86_64),y)
ASRCS += up_setjmp32.S ASRCS += up_setjmp32.S
endif endif
ifeq ($(CONFIG_HOST_ARM),y)
ASRCS += up_setjmp_arm.S
endif
AOBJS = $(ASRCS:.S=$(OBJEXT)) AOBJS = $(ASRCS:.S=$(OBJEXT))
CSRCS = up_initialize.c up_idle.c up_interruptcontext.c up_initialstate.c CSRCS = up_initialize.c up_idle.c up_interruptcontext.c up_initialstate.c

View File

@ -132,7 +132,7 @@
# define JB_SP JB_RSP # define JB_SP JB_RSP
# define JB_PC JB_RSI # define JB_PC JB_RSI
#else #elif defined(CONFIG_HOST_X86) || defined(CONFIG_SIM_M32)
/* Storage order: %ebx, $esi, %edi, %ebp, sp, and return PC */ /* Storage order: %ebx, $esi, %edi, %ebp, sp, and return PC */
# ifdef __ASSEMBLY__ # ifdef __ASSEMBLY__
@ -152,7 +152,10 @@
# define JB_PC (5) # define JB_PC (5)
# endif /* __ASSEMBLY__ */ # endif /* __ASSEMBLY__ */
#endif /* CONFIG_HOST_X86_64 && !CONFIG_SIM_M32 */ #elif defined(CONFIG_HOST_ARM)
# define JB_SP 8
# define JB_PC 9
#endif
/* Simulated Heap Definitions **********************************************/ /* Simulated Heap Definitions **********************************************/
/* Size of the simulated heap */ /* Size of the simulated heap */

View File

@ -0,0 +1,103 @@
/****************************************************************************
* arch/sim/src/up_setjmp_arm.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Nickolay Semyonov (RPI) <snob@wolpike.com>
*
* Extracted from the MUSL C-library. The MUSL C library has a compatible
* MIT license and is released here under the NuttX 3-clause BSD license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
.syntax unified
.global up_setjmp
.type up_setjmp,%function
up_setjmp:
mov ip,r0
stmia ip!,{v1,v2,v3,v4,v5,v6,sl,fp}
mov r2,sp
stmia ip!,{r2,lr}
mov r0,#0
#if 0
adr r1,1f
ldr r2,1f
ldr r1,[r1,r2]
tst r1,#0x260
beq 3f
tst r1,#0x20
beq 2f
stc p2, cr4, [ip], #48
2: tst r1,#0x40
beq 2f
.fpu vfp
vstmia ip!, {d8-d15}
.fpu softvfp
.eabi_attribute 10, 0
.eabi_attribute 27, 0
2: tst r1,#0x200
beq 3f
stcl p1, cr10, [ip], #8
stcl p1, cr11, [ip], #8
stcl p1, cr12, [ip], #8
stcl p1, cr13, [ip], #8
stcl p1, cr14, [ip], #8
stcl p1, cr15, [ip], #8
#endif
3: bx lr
.syntax unified
.global up_longjmp
.type up_longjmp,%function
up_longjmp:
mov ip,r0
movs r0,r1
moveq r0,#1
ldmia ip!, {v1,v2,v3,v4,v5,v6,sl,fp}
ldmia ip!, {r2,lr}
mov sp,r2
#if 0
.fpu vfp
vldmia ip!, {d8-d15}
.fpu softvfp
.eabi_attribute 10, 0
.eabi_attribute 27, 0
2: tst r1,#0x200
beq 3f
ldcl p1, cr10, [ip], #8
ldcl p1, cr11, [ip], #8
ldcl p1, cr12, [ip], #8
ldcl p1, cr13, [ip], #8
ldcl p1, cr14, [ip], #8
ldcl p1, cr15, [ip], #8
#endif
3: bx lr

View File

@ -2,8 +2,15 @@ README
^^^^^^ ^^^^^^
This README discusses issues unique to NuttX configurations for the This README discusses issues unique to NuttX configurations for the
Arduino DUE board featuring the Atmel ATSAM3X8E MCU running at 84 Arduino DUE board featuring the Atmel ATSAM3X8E MCU running at 84 MHz.
MHz.
NOTE: If found that newer Arduino Due board differ from the older boards
mine: Mine has the 32.768 slow clock crystal and associated caps installed.
the newer boards do not. This can cause a hang in the SAM startup code
where it waits for the slow crystal input to lock on.
Options: (1) Solder a 32.768 KHz crystal and associated caps on board or,
(2) disable the function sam_setupsupc() in sam_clockconfig.c
Supported Shields Supported Shields
----------------- -----------------

View File

@ -58,7 +58,7 @@
/* After power-on reset, the SAM3X device is running on a 4MHz internal RC. These /* After power-on reset, the SAM3X device is running on a 4MHz internal RC. These
* definitions will configure clocking * definitions will configure clocking
* *
* MAINOSC: Frequency = 12MHz (crysta) * MAINOSC: Frequency = 12MHz (crystal)
* PLLA: PLL Divider = 1, Multiplier = 14 to generate PLLACK = 168MHz * PLLA: PLL Divider = 1, Multiplier = 14 to generate PLLACK = 168MHz
* Master Clock (MCK): Source = PLLACK, Prescalar = 1 to generate MCK = 84MHz * Master Clock (MCK): Source = PLLACK, Prescalar = 1 to generate MCK = 84MHz
* CPU clock: 84MHz * CPU clock: 84MHz

View File

@ -610,7 +610,17 @@ Configuration sub-directories
unnecessarily busy. There is some prototype code to do just this unnecessarily busy. There is some prototype code to do just this
in the driver, but does not seem to work. in the driver, but does not seem to work.
2017-08-24: There is only a single buffer for reassemblying larger 2017-08-26: There was only a single buffer for reassemblying larger
packets. This could be an important issue for the hub configuration packets. This could be a problem issue for the hub configuration
which really needs the capability concurrently reassemble multiple which really needs the capability concurrently reassemble multiple
incoming streams. incoming streams. The design was extended to support multiple
reassembly buffers.
Initial testing shows the same basic behavior as noted before:
The UDP test works and TCP test (usually) works. There are,
however, are errors in reported by the hub in the TCP test.
Occassionally the test will hang when ther server echoes the data
back to the client. These errors are presumably the result of ACKs
from the receiver colliding with frames from the sender.
Needs more investigation.

View File

@ -671,6 +671,7 @@ Configurations
two star endpoints via the hub, the frames are correctly directed two star endpoints via the hub, the frames are correctly directed
to the hub. However, they are not being forwarded to the other to the hub. However, they are not being forwarded to the other
endpoint. endpoint.
2017-06-30: The failure to forward is understood: When the star 2017-06-30: The failure to forward is understood: When the star
endpoint sent the IPv6 destination address, the HC06 compression endpoint sent the IPv6 destination address, the HC06 compression
logic elided the address -- meaning that it could be reconstructed logic elided the address -- meaning that it could be reconstructed
@ -686,13 +687,16 @@ Configurations
some additional fixes for byte ordering in 16-bit and 64-bit some additional fixes for byte ordering in 16-bit and 64-bit
compressed IPv6 addresses, then all tests are working as expected: compressed IPv6 addresses, then all tests are working as expected:
TCP, UDP, Telnet. TCP, UDP, Telnet.
2017-08-05: It looks like I have lost one of my Clicker2-STM32 boards. 2017-08-05: It looks like I have lost one of my Clicker2-STM32 boards.
This means that I will not be able to do any regression testing as This means that I will not be able to do any regression testing as
changes are made to the radio interfaces and 6LoWPAN :( changes are made to the radio interfaces and 6LoWPAN :(
2017-08-24: There is only a single buffer for reassemblying larger
packets. This could be an important issue for the hub configuration 2017-08-26: There was only a single buffer for reassemblying larger
packets. This could be a problem issue for the hub configuration
which really needs the capability concurrently reassemble multiple which really needs the capability concurrently reassemble multiple
incoming streams. incoming streams. The design was extended to support multiple
reassembly buffers but have not yet been verified on this platform.
nsh: nsh:

View File

@ -203,7 +203,8 @@
*/ */
/* prescaler common to all PLL inputs; will be 1 (XXX source is implicitly /* prescaler common to all PLL inputs; will be 1 (XXX source is implicitly
as per comment above HSI) */ * as per comment above HSI)
*/
#define STM32L4_PLLCFG_PLLM RCC_PLLCFG_PLLM(1) #define STM32L4_PLLCFG_PLLM RCC_PLLCFG_PLLM(1)
@ -292,11 +293,12 @@
/* REVISIT : this can be configured */ /* REVISIT : this can be configured */
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx /* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
* otherwise frequency is 2xAPBx. * otherwise frequency is 2xAPBx.
* Note: TIM1,8 are on APB2, others on APB1 * Note: TIM1,15,16 are on APB2, others on APB1
*/ */
/* REVISIT : this can be configured */ /* REVISIT : this can be configured */
@ -379,7 +381,8 @@
#define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1) #define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1)
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#elif defined(MSI_CLOCK_CONFIG) #elif defined(MSI_CLOCK_CONFIG)
@ -459,13 +462,14 @@
#define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1) #define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1)
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#endif #endif
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx /* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
* otherwise frequency is 2xAPBx. * otherwise frequency is 2xAPBx.
* Note: TIM1,8,15,16,17 are on APB2, others on APB1 * Note: TIM1,15,16 are on APB2, others on APB1
*/ */
#define BOARD_TIM1_FREQUENCY STM32L4_HCLK_FREQUENCY #define BOARD_TIM1_FREQUENCY STM32L4_HCLK_FREQUENCY
@ -475,10 +479,8 @@
#define BOARD_TIM5_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_TIM5_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_TIM6_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_TIM6_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_TIM7_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_TIM7_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_TIM8_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_TIM15_FREQUENCY STM32L4_HCLK_FREQUENCY #define BOARD_TIM15_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_TIM16_FREQUENCY STM32L4_HCLK_FREQUENCY #define BOARD_TIM16_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_TIM17_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_LPTIM1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_LPTIM1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_LPTIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_LPTIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)

View File

@ -292,11 +292,12 @@
/* REVISIT : this can be configured */ /* REVISIT : this can be configured */
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx /* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
* otherwise frequency is 2xAPBx. * otherwise frequency is 2xAPBx.
* Note: TIM1,8 are on APB2, others on APB1 * Note: TIM1,15,16 are on APB2, others on APB1
*/ */
/* REVISIT : this can be configured */ /* REVISIT : this can be configured */
@ -379,7 +380,8 @@
#define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1) #define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1)
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#elif defined(MSI_CLOCK_CONFIG) #elif defined(MSI_CLOCK_CONFIG)
@ -459,13 +461,14 @@
#define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1) #define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1)
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#endif #endif
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx /* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
* otherwise frequency is 2xAPBx. * otherwise frequency is 2xAPBx.
* Note: TIM1,8,15,16,17 are on APB2, others on APB1 * Note: TIM1,15,16 are on APB2, others on APB1
*/ */
#define BOARD_TIM1_FREQUENCY STM32L4_HCLK_FREQUENCY #define BOARD_TIM1_FREQUENCY STM32L4_HCLK_FREQUENCY
@ -475,10 +478,8 @@
#define BOARD_TIM5_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_TIM5_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_TIM6_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_TIM6_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_TIM7_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_TIM7_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_TIM8_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_TIM15_FREQUENCY STM32L4_HCLK_FREQUENCY #define BOARD_TIM15_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_TIM16_FREQUENCY STM32L4_HCLK_FREQUENCY #define BOARD_TIM16_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_TIM17_FREQUENCY STM32L4_HCLK_FREQUENCY
#define BOARD_LPTIM1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_LPTIM1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
#define BOARD_LPTIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2) #define BOARD_LPTIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)

View File

@ -49,7 +49,7 @@
#include "nucleo-l452re.h" #include "nucleo-l452re.h"
/**************************************************************************** /****************************************************************************
* Pre-processor Defintiionis * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
#undef HAVE_I2C_DRIVER #undef HAVE_I2C_DRIVER

View File

@ -293,10 +293,13 @@
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM17_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx /* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
* otherwise frequency is 2xAPBx. * otherwise frequency is 2xAPBx.
* Note: TIM1,8 are on APB2, others on APB1 * Note: TIM1,8,15,16,17 are on APB2, others on APB1
*/ */
/* REVISIT : this can be configured */ /* REVISIT : this can be configured */
@ -380,6 +383,9 @@
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM17_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#elif defined(MSI_CLOCK_CONFIG) #elif defined(MSI_CLOCK_CONFIG)
@ -460,6 +466,9 @@
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM17_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#endif #endif

View File

@ -178,10 +178,13 @@
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY) #define STM32L4_APB2_TIM8_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM15_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM16_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
#define STM32L4_APB2_TIM17_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx /* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
* otherwise frequency is 2xAPBx. * otherwise frequency is 2xAPBx.
* Note: TIM1,8 are on APB2, others on APB1 * Note: TIM1,8,15,16,17 are on APB2, others on APB1
*/ */
/* REVISIT : this can be configured */ /* REVISIT : this can be configured */
@ -361,9 +364,9 @@
/* DMA channels *************************************************************/ /* DMA channels *************************************************************/
/* ADC */ /* ADC */
#define ADC1_DMA_CHAN DMAMAP_ADC1_1 #define ADC1_DMA_CHAN DMACHAN_ADC1_1
#define ADC2_DMA_CHAN DMAMAP_ADC2_1 #define ADC2_DMA_CHAN DMACHAN_ADC2_1
#define ADC3_DMA_CHAN DMAMAP_ADC3_1 #define ADC3_DMA_CHAN DMACHAN_ADC3_1
/* SPI /* SPI
* *

View File

@ -997,7 +997,7 @@ Tickless OS
will have an error of 0.6% and will have inaccuracies that will will have an error of 0.6% and will have inaccuracies that will
effect the time due to long term error build-up. effect the time due to long term error build-up.
Using the slow clock clock input, the Tickless support is functional, Using the slow clock input, the Tickless support is functional,
however, there are inaccuracies in delays. For example, however, there are inaccuracies in delays. For example,
nsh> sleep 10 nsh> sleep 10
@ -1318,7 +1318,7 @@ Configuration sub-directories
mrf24j40-starhub mrf24j40-starhub
This configuration implement a hub node in a 6LoWPAN start network. This configuration implements a hub node in a 6LoWPAN start network.
It is intended for the us the mrf24j40-starpoint configuration with It is intended for the us the mrf24j40-starpoint configuration with
the clicker2-stm32 configurations. Essentially, the SAME70 Xplained the clicker2-stm32 configurations. Essentially, the SAME70 Xplained
plays the roll of the hub in the configuration and the clicker2-stm32 plays the roll of the hub in the configuration and the clicker2-stm32
@ -1383,10 +1383,11 @@ Configuration sub-directories
No significant functional testing has yet been performed. No significant functional testing has yet been performed.
2017-08-24: There is only a single buffer for reassemblying larger 2017-08-26: There was only a single buffer for reassemblying larger
packets. This could be an important issue for the hub configuration packets. This could be a problem issue for the hub configuration
which really needs the capability concurrently reassemble multiple which really needs the capability concurrently reassemble multiple
incoming streams. incoming streams. The design was extended to support multiple
reassembly buffers but have not yet been verified on this platform.
netnsh: netnsh:

View File

@ -1956,10 +1956,11 @@ Configuration sub-directories
The SPI signals look clean on the board and the MRF24J40 seems The SPI signals look clean on the board and the MRF24J40 seems
fully functional. fully functional.
2017-08-24: There is only a single buffer for reassemblying larger 2017-08-26: There was only a single buffer for reassemblying larger
packets. This could be an important issue for the hub configuration packets. This could be a problem issue for the hub configuration
which really needs the capability concurrently reassemble multiple which really needs the capability concurrently reassemble multiple
incoming streams. incoming streams. The design was extended to support multiple
reassembly buffers but additional testing is needed.
mxtxplnd: mxtxplnd:

View File

@ -292,6 +292,25 @@ config BQ2425X
---help--- ---help---
The BQ24250/BQ24251 are battery charger for lithium-ion batteries. The BQ24250/BQ24251 are battery charger for lithium-ion batteries.
config BQ2429X
bool "BQ2429X Battery charger support"
default n
select I2C
select I2C_BQ2429X
depends on BATTERY_CHARGER
---help---
The BQ24296/BQ24297/BQ24296M are battery charger for lithium-ion batteries.
if BQ2429X
config DEBUG_BQ2429X
bool "BQ2429X Debug Features"
default n
---help---
Enable BQ2429X battery management debug features.
endif # BQ2429X
config BATTERY_GAUGE config BATTERY_GAUGE
bool "Battery Fuel Gauge support" bool "Battery Fuel Gauge support"
default n default n
@ -312,6 +331,10 @@ config I2C_BQ2425X
bool bool
default y if BQ2425X default y if BQ2425X
config I2C_BQ2429X
bool
default y if BQ2429X
config I2C_MAX1704X config I2C_MAX1704X
bool bool
default y if MAX1704X default y if MAX1704X

View File

@ -80,6 +80,12 @@ ifeq ($(CONFIG_I2C_BQ2425X),y)
CSRCS += bq2425x.c CSRCS += bq2425x.c
endif endif
# Add the BQ2429x I2C-based battery charger driver
ifeq ($(CONFIG_I2C_BQ2429X),y)
CSRCS += bq2429x.c
endif
endif endif
# Include power support in the build # Include power support in the build

View File

@ -160,7 +160,7 @@ static int bat_charger_ioctl(FAR struct file *filep, int cmd,
FAR struct battery_charger_dev_s *dev = inode->i_private; FAR struct battery_charger_dev_s *dev = inode->i_private;
int ret; int ret;
/* Inforce mutually exclusive access to the battery driver */ /* Enforce mutually exclusive access to the battery driver */
ret = sem_wait(&dev->batsem); ret = sem_wait(&dev->batsem);
if (ret < 0) if (ret < 0)
@ -168,7 +168,7 @@ static int bat_charger_ioctl(FAR struct file *filep, int cmd,
return -errno; /* Probably EINTR */ return -errno; /* Probably EINTR */
} }
/* Procss the IOCTL command */ /* Process the IOCTL command */
ret = -EINVAL; /* Assume a bad argument */ ret = -EINVAL; /* Assume a bad argument */
switch (cmd) switch (cmd)
@ -239,6 +239,16 @@ static int bat_charger_ioctl(FAR struct file *filep, int cmd,
} }
break; break;
case BATIOC_OPERATE:
{
FAR int *ptr = (FAR int *)((uintptr_t)arg);
if (ptr)
{
ret = dev->ops->operate(dev, (uintptr_t)arg);
}
}
break;
default: default:
_err("ERROR: Unrecognized cmd: %d\n", cmd); _err("ERROR: Unrecognized cmd: %d\n", cmd);
ret = -ENOTTY; ret = -ENOTTY;

View File

@ -134,6 +134,7 @@ static int bq2425x_online(struct battery_charger_dev_s *dev, bool *status);
static int bq2425x_voltage(struct battery_charger_dev_s *dev, int value); static int bq2425x_voltage(struct battery_charger_dev_s *dev, int value);
static int bq2425x_current(struct battery_charger_dev_s *dev, int value); static int bq2425x_current(struct battery_charger_dev_s *dev, int value);
static int bq2425x_input_current(struct battery_charger_dev_s *dev, int value); static int bq2425x_input_current(struct battery_charger_dev_s *dev, int value);
static int bq2425x_operate(struct battery_charger_dev_s *dev, uintptr_t param);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@ -146,7 +147,8 @@ static const struct battery_charger_operations_s g_bq2425xops =
bq2425x_online, bq2425x_online,
bq2425x_voltage, bq2425x_voltage,
bq2425x_current, bq2425x_current,
bq2425x_input_current bq2425x_input_current,
bq2425x_operate
}; };
/**************************************************************************** /****************************************************************************
@ -728,6 +730,19 @@ static int bq2425x_input_current(struct battery_charger_dev_s *dev, int value)
return OK; return OK;
} }
/****************************************************************************
* Name: bq2425x_operate
*
* Description:
* Do miscellaneous battery ioctl()
*
****************************************************************************/
static int bq2425x_operate(struct battery_charger_dev_s *dev, uintptr_t param)
{
return -ENOSYS;
}
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/

1262
drivers/power/bq2429x.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -127,6 +127,7 @@
#include <nuttx/spi/spi.h> #include <nuttx/spi/spi.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
#include <nuttx/net/radiodev.h> #include <nuttx/net/radiodev.h>
#include <nuttx/net/sixlowpan.h>
#include <nuttx/wireless/spirit.h> #include <nuttx/wireless/spirit.h>
#include <nuttx/wireless/pktradio.h> #include <nuttx/wireless/pktradio.h>
@ -363,6 +364,12 @@ int spirit_hw_initialize(FAR struct spirit_driver_s *dev,
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN
/* One single packet buffer */
static struct sixlowpan_reassbuf_s g_iobuffer;
#endif
/* Spirit radio initialization */ /* Spirit radio initialization */
static const struct radio_init_s g_radio_init = static const struct radio_init_s g_radio_init =
@ -1043,6 +1050,11 @@ static void spirit_receive_work(FAR void *arg)
iob = pktmeta->pm_iob; iob = pktmeta->pm_iob;
pktmeta->pm_iob = NULL; pktmeta->pm_iob = NULL;
/* Make sure the our single packet buffer is attached */
priv->radio.r_dev.d_buf = g_iobuffer.rb_buf;
priv->radio.r_dev.d_len = 0;
/* Send the next frame to the network */ /* Send the next frame to the network */
wlinfo("Send frame %p to the network: Offset=%u Length=%u\n", wlinfo("Send frame %p to the network: Offset=%u Length=%u\n",
@ -1137,7 +1149,7 @@ static void spirit_interrupt_work(FAR void *arg)
#ifdef CONFIG_SPIRIT_FIFOS #ifdef CONFIG_SPIRIT_FIFOS
irqstatus.IRQ_RX_FIFO_ALMOST_FULL = 0; irqstatus.IRQ_RX_FIFO_ALMOST_FULL = 0;
/* Discard any RX buffer that might have been allocated */ /* Discard any packet buffer that might have been allocated */
if (priv->rxbuffer != NULL) if (priv->rxbuffer != NULL)
{ {
@ -1281,7 +1293,12 @@ static void spirit_interrupt_work(FAR void *arg)
if (priv->state != DRIVER_STATE_RECEIVING) if (priv->state != DRIVER_STATE_RECEIVING)
{ {
DEBUGASSERT(priv->state == DRIVER_STATE_IDLE); /* As a race condition, the TX state, but overriden by concurrent
* RX activity? This assertion here *does* fire:
*
* DEBUGASSERT(priv->state == DRIVER_STATE_IDLE);
*/
priv->state = DRIVER_STATE_RECEIVING; priv->state = DRIVER_STATE_RECEIVING;
} }
@ -1320,7 +1337,7 @@ static void spirit_interrupt_work(FAR void *arg)
irqstatus.IRQ_RX_FIFO_ALMOST_FULL = 0; irqstatus.IRQ_RX_FIFO_ALMOST_FULL = 0;
/* There should be a RX buffer that was allocated when the data sync /* There should be a packet buffer that was allocated when the data sync
* interrupt was processed. * interrupt was processed.
*/ */
@ -1473,7 +1490,7 @@ static void spirit_interrupt_work(FAR void *arg)
wlinfo("RX FIFO almost full\n"); wlinfo("RX FIFO almost full\n");
/* There should be a RX buffer that was allocated when the data sync /* There should be a packet buffer that was allocated when the data sync
* interrupt was processed. * interrupt was processed.
*/ */
@ -1571,7 +1588,7 @@ static void spirit_interrupt_work(FAR void *arg)
*/ */
#ifdef CONFIG_SPIRIT_FIFOS #ifdef CONFIG_SPIRIT_FIFOS
/* Discard any RX buffer that might have been allocated */ /* Discard any packet buffer that might have been allocated */
if (priv->rxbuffer != NULL) if (priv->rxbuffer != NULL)
{ {
@ -1752,6 +1769,12 @@ static void spirit_txpoll_work(FAR void *arg)
net_lock(); net_lock();
#ifdef CONFIG_NET_6LOWPAN
/* Make sure the our single packet buffer is attached */
priv->radio.r_dev.d_buf = g_iobuffer.rb_buf;
#endif
/* Do nothing if the network is not yet UP */ /* Do nothing if the network is not yet UP */
if (!priv->ifup) if (!priv->ifup)
@ -2752,7 +2775,6 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi,
FAR struct spirit_driver_s *priv; FAR struct spirit_driver_s *priv;
FAR struct radio_driver_s *radio; FAR struct radio_driver_s *radio;
FAR struct net_driver_s *dev; FAR struct net_driver_s *dev;
FAR uint8_t *pktbuf;
int ret; int ret;
/* Allocate a driver state structure instance */ /* Allocate a driver state structure instance */
@ -2764,16 +2786,6 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi,
return -ENOMEM; return -ENOMEM;
} }
/* Allocate a packet buffer */
pktbuf = (uint8_t *)kmm_zalloc(CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE);
if (priv == NULL)
{
wlerr("ERROR: Failed to allocate a packet buffer\n");
ret = -ENOMEM;
goto errout_with_alloc;
}
/* Attach the interface, lower driver, and devops */ /* Attach the interface, lower driver, and devops */
priv->lower = lower; priv->lower = lower;
@ -2798,7 +2810,6 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi,
/* Initialize the common network device fields */ /* Initialize the common network device fields */
dev = &radio->r_dev; dev = &radio->r_dev;
dev->d_buf = pktbuf; /* Single packet buffer */
dev->d_ifup = spirit_ifup; /* I/F up (new IP address) callback */ dev->d_ifup = spirit_ifup; /* I/F up (new IP address) callback */
dev->d_ifdown = spirit_ifdown; /* I/F down callback */ dev->d_ifdown = spirit_ifdown; /* I/F down callback */
dev->d_txavail = spirit_txavail; /* New TX data callback */ dev->d_txavail = spirit_txavail; /* New TX data callback */
@ -2839,7 +2850,7 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi,
if (ret < 0) if (ret < 0)
{ {
wlerr("ERROR: Failed to attach interrupt: %d\n", ret); wlerr("ERROR: Failed to attach interrupt: %d\n", ret);
goto errout_with_pktbuf; goto errout_with_alloc;
} }
/* Enable Radio IRQ */ /* Enable Radio IRQ */
@ -2850,11 +2861,6 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi,
errout_with_attach: errout_with_attach:
(void)lower->attach(lower, NULL, NULL); (void)lower->attach(lower, NULL, NULL);
errout_with_pktbuf:
#if 0
kmm_free(pktbuf);
#endif
errout_with_alloc: errout_with_alloc:
kmm_free(priv); kmm_free(priv);
return ret; return ret;

View File

@ -13,6 +13,7 @@ config FS_AUTOMOUNTER
bool "Auto-mounter" bool "Auto-mounter"
default n default n
depends on !DISABLE_MOUNTPOINT depends on !DISABLE_MOUNTPOINT
select SCHED_LPWORK
---help--- ---help---
The automounter provides an OS-internal mechanism for automatically The automounter provides an OS-internal mechanism for automatically
mounting and unmounting removable media as the media is inserted and mounting and unmounting removable media as the media is inserted and

View File

@ -42,8 +42,6 @@
#include <stdint.h> #include <stdint.h>
#include <nuttx/clock.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
#if defined(CONFIG_NET_6LOWPAN) || defined(CONFIG_NET_IEEE802154) #if defined(CONFIG_NET_6LOWPAN) || defined(CONFIG_NET_IEEE802154)
@ -76,22 +74,37 @@ struct radiodev_properties_s
* The radio network driver does not use the d_buf packet buffer directly. * The radio network driver does not use the d_buf packet buffer directly.
* Rather, it uses a list smaller frame buffers. * Rather, it uses a list smaller frame buffers.
* *
* - The packet fragment data is provided in an IOB in the via the * - Outgoing frame data is provided in an IOB in the via the
* r_req_data() interface method each time that the radio needs to * r_req_data() interface method each time that the radio needs to
* send more data. The length of the frame is provided in the io_len * send more data. The length of the frame is provided in the io_len
* field of the IOB. * field of the IOB.
* *
* In this case, the d_buf is not used at all and, if fact, may be * Outgoing frames are generated when the radio network driver calls
* NULL. * the devif_poll(), devif_timer(), sixlowpan_input(), or
* ieee802154_input() interfaces. In each case, the radio driver must
* provide a working buffer in the d_buf pointer. A special form of
* the packet buffer must be used, struct sixlowpan_reassbuf_s. This
* special for includes appended data for managing reassembly of packets.
* *
* - Received frames are provided by radio network driver to the network * - Received frames are provided by radio network driver to the network
* via an IOB parameter in the sixlowpan_input() pr ieee802154_input() * via an IOB parameter in the sixlowpan_input() pr ieee802154_input()
* interface. The length of the frame is io_len. * interface. The length of the frame is io_len.
* *
* - 6LoWPAN frames and will be uncompressed and possibly reassembled in * Again, the radio network driver must provide an instance of struct
* the d_buf; d_len will hold the size of the reassembled packet. * sixlowpan_reassbuf_s as the packet buffer in the d_buf field. This
* driver-provided data will only be used if the the receive frames are
* not fragmented.
* *
* In this case, a d_buf of size CONFIG_NET_6LOWPAN_MTU must be provided. * - Received 6LoWPAN frames and will be uncompressed and possibly
* reassembled in resassembled the d_buf; d_len will hold the size of
* the reassembled packet.
*
* For fagemented frames, d_buf provided by radio driver will not be
* used. 6LoWPAN must handle mutliple reassemblies from different
* sources simultaneously. To support this, 6LoWPAN will allocate a
* unique reassembly buffer for each active reassembly, based on the
* reassembly tag and source radio address. These reassembly buffers
* are managed entirely by the 6LoWPAN layer.
* *
* This is accomplished by "inheriting" the standard 'struct net_driver_s' * This is accomplished by "inheriting" the standard 'struct net_driver_s'
* and appending the frame buffer as well as other metadata needed to * and appending the frame buffer as well as other metadata needed to
@ -103,8 +116,9 @@ struct radiodev_properties_s
* structure. In general, all fields must be set to NULL. In addition: * structure. In general, all fields must be set to NULL. In addition:
* *
* 1. On a TX poll, the radio network driver should provide its driver * 1. On a TX poll, the radio network driver should provide its driver
* structure. During the course of the poll, the networking layer may * structure along is (single) reassemby buffer provided at d_buf.
* generate outgoing frames. These frames will by provided to the MAC * During the course of the poll, the networking layer may generate
* outgoing frames. These frames will by provided to the radio network
* driver via the req_data() method. * driver via the req_data() method.
* *
* After sending each frame through the radio, the MAC driver must * After sending each frame through the radio, the MAC driver must
@ -117,16 +131,17 @@ struct radiodev_properties_s
* payload area of an IOB frame structure. That IOB structure may be * payload area of an IOB frame structure. That IOB structure may be
* obtained using the iob_alloc() function. * obtained using the iob_alloc() function.
* *
* For 6LoWPAN, the larger dev.d_buf must have a size of at least the * For 6LoWPAN, fragmented packets will be reassembled using allocated
* advertised MTU of the protocol, CONFIG_NET_6LOWPAN_MTU, plus * reassembly buffers that are managed by the 6LoWPAN layer. The radio
* CONFIG_NET_GUARDSIZE. If fragmentation is enabled, then the logical * driver must still provide its (single) reassembly buffer in d_buf;
* packet size may be significantly larger than the size of the frame * that buffer is still used for the case where the packet is not
* buffer. The dev.d_buf is used for de-compressing each frame and * fragmented into many frames. In either case, the packet buffer will
* reassembling any fragmented packets to create the full input packet * have a size of advertised MTU of the protocol, CONFIG_NET_6LOWPAN_MTU,
* that is provided to the application. * plus CONFIG_NET_GUARDSIZE and some additional overhead for reassembly
* state data.
* *
* The MAC driver should then inform the network of the reciptor of a * The radio network driver should then inform the network of the recipt
* frame by calling sixlowpan_input() or ieee802154_input(). That * of a frame by calling sixlowpan_input() or ieee802154_input(). That
* single frame (or, perhaps, list of frames) should be provided as * single frame (or, perhaps, list of frames) should be provided as
* second argument of that call. * second argument of that call.
* *
@ -167,65 +182,6 @@ struct radio_driver_s
uint8_t r_msdu_handle; uint8_t r_msdu_handle;
#endif #endif
#if CONFIG_NET_6LOWPAN_FRAG
/* Fragmentation Support *************************************************/
/* Fragmentation is handled frame by frame and requires that certain
* state information be retained from frame to frame.
*/
/* r_dgramtag. Datagram tag to be put in the header of the set of
* fragments. It is used by the recipient to match fragments of the
* same payload.
*
* This is the sender's copy of the tag. It is incremented after each
* fragmented packet is sent so that it will be unique to that
* sequence fragmentation. Its value is then persistent, the values of
* other fragmentation variables are valid on during a single
* fragmentation sequence (while r_accumlen > 0)
*/
uint16_t r_dgramtag;
/* r_reasstag. Each frame in the reassembly has a tag. That tag must
* match the reassembly tag in the fragments being merged.
*
* This is the same tag as r_dgramtag but is saved on the receiving
* side to match all of the fragments of the packet.
*/
uint16_t r_reasstag;
/* r_pktlen. The total length of the IPv6 packet to be re-assembled in
* d_buf. Used to determine when the re-assembly is complete.
*/
uint16_t r_pktlen;
/* The current accumulated length of the packet being received in d_buf.
* Included IPv6 and protocol headers. Currently used only to determine
* there is a fragmentation sequence in progress.
*/
uint16_t r_accumlen;
/* r_boffset. Offset to the beginning of data in d_buf. As each fragment
* is received, data is placed at an appriate offset added to this.
*/
uint16_t r_boffset;
/* The source MAC address of the fragments being merged */
struct netdev_varaddr_s r_fragsrc;
/* That time at which reassembly was started. If the elapsed time
* exceeds CONFIG_NET_6LOWPAN_MAXAGE, then the reassembly will
* be cancelled.
*/
systime_t r_time;
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/* MAC network driver callback functions **********************************/ /* MAC network driver callback functions **********************************/
/************************************************************************** /**************************************************************************
* Name: r_get_mhrlen * Name: r_get_mhrlen

View File

@ -53,6 +53,10 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <nuttx/clock.h>
#include <nuttx/net/netdev.h>
#ifdef CONFIG_NET_6LOWPAN #ifdef CONFIG_NET_6LOWPAN
@ -337,6 +341,99 @@
(a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \ (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \
(((a)[7] & HTONS(0xff00)) == 0x0000)) (((a)[7] & HTONS(0xff00)) == 0x0000))
/****************************************************************************
* Public Types
****************************************************************************/
/* Fragmentation Support
*
* This structure defines the reassembly buffer. NOTE: The packet buffer
* is needed even in the case where reassembly is disabled.
*/
struct sixlowpan_reassbuf_s
{
/* This is the externally visible packet buffer. This is assigned
* to the driver's d_buf field when the reassembly is complete and
* provides the full reassembly packet to the network.
*/
uint8_t rb_buf[CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE];
/* Memory pool used to allocate this reassembly buffer */
uint8_t rb_pool;
/* True if the reassemby buffer is active (set to false when reassembly is
* complete).
*/
bool rb_active;
/* Supports a singly linked list */
FAR struct sixlowpan_reassbuf_s *rb_flink;
#if CONFIG_NET_6LOWPAN_FRAG
/* Fragmentation is handled frame by frame and requires that certain
* state information be retained from frame to frame. That additional
* information follows the externally visible packet buffer.
*/
/* rb_dgramtag. Datagram tag to be put in the header of the set of
* fragments. It is used by the recipient to match fragments of the
* same payload.
*
* This is the sender's copy of the tag. It is incremented after each
* fragmented packet is sent so that it will be unique to that
* sequence fragmentation. Its value is then persistent, the values of
* other fragmentation variables are valid on during a single
* fragmentation sequence (while rb_accumlen > 0)
*/
uint16_t rb_dgramtag;
/* rb_reasstag. Each frame in the reassembly has a tag. That tag must
* match the reassembly tag in the fragments being merged.
*
* This is the same tag as rb_dgramtag but is saved on the receiving
* side to match all of the fragments of the packet.
*/
uint16_t rb_reasstag;
/* rb_pktlen. The total length of the IPv6 packet to be re-assembled in
* d_buf. Used to determine when the re-assembly is complete.
*/
uint16_t rb_pktlen;
/* The current accumulated length of the packet being received in d_buf.
* Included IPv6 and protocol headers. Currently used only to determine
* there is a fragmentation sequence in progress.
*/
uint16_t rb_accumlen;
/* rb_boffset. Offset to the beginning of data in d_buf. As each fragment
* is received, data is placed at an appriate offset added to this.
*/
uint16_t rb_boffset;
/* The source MAC address of the fragments being merged */
struct netdev_varaddr_s rb_fragsrc;
/* That time at which reassembly was started. If the elapsed time
* exceeds CONFIG_NET_6LOWPAN_MAXAGE, then the reassembly will
* be cancelled.
*/
systime_t rb_time;
#endif /* CONFIG_NET_6LOWPAN_FRAG */
};
/**************************************************************************** /****************************************************************************
* Public Function Prototypes * Public Function Prototypes
****************************************************************************/ ****************************************************************************/

View File

@ -60,6 +60,7 @@
* *
* CONFIG_I2C - I2C support *may* be needed * CONFIG_I2C - I2C support *may* be needed
* CONFIG_I2C_BQ2425X - The BQ2425x driver must be explicitly selected. * CONFIG_I2C_BQ2425X - The BQ2425x driver must be explicitly selected.
* CONFIG_I2C_BQ2429X - The BQ2429x driver must be explicitly selected.
*/ */
/* IOCTL Commands ***********************************************************/ /* IOCTL Commands ***********************************************************/
@ -84,6 +85,8 @@
* Input value: An int defining the current value. * Input value: An int defining the current value.
* BATIOC_INPUT_CURRENT - Define the input current limit of power supply. * BATIOC_INPUT_CURRENT - Define the input current limit of power supply.
* Input value: An int defining the input current limit value. * Input value: An int defining the input current limit value.
* BATIOC_OPERATE - Perform miscellaneous, device-specific charger operation.
* Input value: An uintptr_t that can hold a pointer to struct batio_operate_msg_s.
*/ */
/* Special input values for BATIOC_INPUT_CURRENT that may optionally /* Special input values for BATIOC_INPUT_CURRENT that may optionally
@ -151,6 +154,10 @@ struct battery_charger_operations_s
/* Set the input current limit of power supply */ /* Set the input current limit of power supply */
int (*input_current)(struct battery_charger_dev_s *dev, int value); int (*input_current)(struct battery_charger_dev_s *dev, int value);
/* Do device specific operation */
int (*operate)(struct battery_charger_dev_s *dev, uintptr_t param);
}; };
/* This structure defines the battery driver state structure */ /* This structure defines the battery driver state structure */
@ -207,11 +214,11 @@ int battery_charger_register(FAR const char *devpath,
* *
* Description: * Description:
* Initialize the BQ2425X battery driver and return an instance of the * Initialize the BQ2425X battery driver and return an instance of the
* lower_half interface that may be used with battery_charger_register(); * lower-half interface that may be used with battery_charger_register().
* *
* This driver requires: * This driver requires:
* *
* CONFIG_BATTERY_CHARGER - Upper half battery fuel gauge driver support * CONFIG_BATTERY_CHARGER - Upper half battery charger driver support
* CONFIG_I2C - I2C support * CONFIG_I2C - I2C support
* CONFIG_I2C_BQ2425X - And the driver must be explictly selected. * CONFIG_I2C_BQ2425X - And the driver must be explictly selected.
* *
@ -237,6 +244,55 @@ FAR struct battery_charger_dev_s *bq2425x_initialize(FAR struct i2c_master_s *i2
int current); int current);
#endif #endif
/****************************************************************************
* Name: bq2429x_initialize
*
* Description:
* Initialize the BQ2429X (BQ24series LiIon Charger with USB OTG boost 5V)
* battery driver and return an instance of the lower-half interface that
* may be used with battery_charger_register().
*
* This is for:
* BQ24296M VQFN24
* BQ24296 VQFN24
* BQ24297
* BQ24298
* Possibly similar:
* BQ24262
* BQ24259
* BQ24292I BQ24295 B
* Possibly the following:
* BQ24260/1/2 Vin-14V
* BQ24190 Vin=17V
*
* This driver requires:
*
* CONFIG_BATTERY_CHARGER - Upper half battery charger driver support
* CONFIG_I2C - I2C support
* CONFIG_I2C_BQ2429X - And the driver must be explictly selected.
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate with
* the BQ2429X
* addr - The I2C address of the BQ2429X (Better be 0x6B).
* frequency - The I2C frequency
* current - The input current our power-supply can offer to charger
*
* Returned Value:
* A pointer to the initialized battery driver instance. A NULL pointer
* is returned on a failure to initialize the BQ2429X lower half.
*
****************************************************************************/
#if defined(CONFIG_I2C) && defined(CONFIG_I2C_BQ2429X)
struct i2c_master_s;
FAR struct battery_charger_dev_s *bq2429x_initialize(FAR struct i2c_master_s *i2c,
uint8_t addr,
uint32_t frequency,
int current);
#endif
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -2,7 +2,7 @@
* include/nuttx/power/battery_ioctl.h * include/nuttx/power/battery_ioctl.h
* NuttX Battery IOCTLs definition * NuttX Battery IOCTLs definition
* *
* Copyright (C) 2015 Gregory Nutt. All rights reserved. * Copyright (C) 2015, 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
@ -60,5 +60,35 @@
#define BATIOC_CURRENT _BATIOC(0x0005) #define BATIOC_CURRENT _BATIOC(0x0005)
#define BATIOC_INPUT_CURRENT _BATIOC(0x0006) #define BATIOC_INPUT_CURRENT _BATIOC(0x0006)
#define BATIOC_CAPACITY _BATIOC(0x0007) #define BATIOC_CAPACITY _BATIOC(0x0007)
#define BATIOC_OPERATE _BATIOC(0x0008)
/****************************************************************************
* Public Types
****************************************************************************/
struct batio_operate_msg_s
{
uint8_t operate_type; /* Really enum batio_operate_e */
union
{
uint32_t u32;
uint8_t u8[8];
};
};
#if defined(CONFIG_I2C_BQ2429X)
enum batio_operate_e
{
BATIO_OPRTN_NOP = 0,
BATIO_OPRTN_BOOST,
BATIO_OPRTN_CHARGE,
BATIO_OPRTN_EN_TERM,
BATIO_OPRTN_HIZ,
BATIO_OPRTN_SYSOFF,
BATIO_OPRTN_RESET,
BATIO_OPRTN_WDOG,
BATIO_OPRTN_END
};
#endif
#endif /* __INCLUDE_NUTTX_POWER_BATTERY_IOCTL_H */ #endif /* __INCLUDE_NUTTX_POWER_BATTERY_IOCTL_H */

View File

@ -0,0 +1,244 @@
/****************************************************************************
* drivers/power/bq2429x.h
* Lower half driver for BQ2429X battery charger
*
* Copyright (C) 2017 Neil Hancock. All rights reserved.
*
* Copyright (C) 2017 Haltian Ltd. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __DRIVERS_POWER_BQ2429X_H
#define __DRIVERS_POWER_BQ2429X_H
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Auxiliary Definitions */
#define BQ2429X_VOLTCHG_MIN 3504
#define BQ2429X_VOLTCHG_MAX 4400
#define BQ2429X_CURRCHG_MIN 512
#define BQ2429X_CURRCHG_MAX 3008
/* BQ2429X Register Definitions ********************************************/
#define BQ2429X_REG00 0x00
#define BQ2429X_REG01 0x01
#define BQ2429X_REG02 0x02
#define BQ2429X_REG03 0x03
#define BQ2429X_REG04 0x04
#define BQ2429X_REG05 0x05
#define BQ2429X_REG06 0x06
#define BQ2429X_REG07 0x07
#define BQ2429X_REG08 0x08
#define BQ2429X_REG09 0x09
#define BQ2429X_REG0A 0x0a
/* REG00 Input Source Control Register */
/* For enabling Device Shutdown for shipping - EN_HIZ=1 until QON pressed*/
#define BQ2429XR1_EN_HIZ (1 << 7) /* 0 Disable (default) 1 Enable HighZ on battery, powerdown */
/* Dynamic Power Management - Indicated in StatusReg DPM_STAT REG08[3]
VINDPM - Input Voltage threshold (a drop below 5V) that triggers DPM
INLIM - Input current threshold that tiggers DPM */
#define BQ2429XR0_VINDPM_SHIFT 3 /* VIN DPM Offset 5V? Range*/
#define BQ2429XR0_VINDPM_MASK (0xf << BQ2429XR0_VINDPM_SHIFT)
# define BQ2429XR0_VINDPM3_080mV (1 << BQ2429XR0_VINDPM_SHIFT)
# define BQ2429XR0_VINDPM2_160mV (2 << BQ2429XR0_VINDPM_SHIFT)
# define BQ2429XR0_VINDPM1_320mV (4 << BQ2429XR0_VINDPM_SHIFT)
# define BQ2429XR0_VINDPM0_640mV (8 << BQ2429XR0_VINDPM_SHIFT)
#define BQ2429XR0_INLIM_SHIFT 0 /* Input Current Limit - lower of I2C & ILIM */
#define BQ2429XR0_INLIM_MASK (0x7 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_0100mA (0x0 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_0150mA (0x1 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_0500mA (0x2 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_0900mA (0x3 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_1000mA (0x4 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_1500mA (0x5 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_2000mA (0x6 << BQ2429XR0_INLIM_SHIFT)
# define BQ2429XR0_INLIM_3000mA (0x7 << BQ2429XR0_INLIM_SHIFT)
/* REG01 Power-On Configuration Register */
#define BQ2429XR1_REG_RESET (1 << 7) /* Write 1 to Reset all registers to default values */
#define BQ2429XR1_DOG_RESET (1 << 6) /* Write 1 for watchdog timer reset */
#define BQ2429XR1_OTG_CONFIG (1 << 5) /* =0 Disable (default) =1 Enable See description */
#define BQ2429XR1_CHG_CONFIG (1 << 4) /* =0 Disable =1 Enable (default) See description */
#define BQ2429XR1_SYS_MINV_SHIFT 1 /* Min Sys Voltage Limit. Offset 3.0V Range 3-3.7V */
#define BQ2429XR1_SYS_MINV_MASK (7 << BQ2429XR1_SYS_MINV_SHIFT)
#define BQ2429XR1_SYS_MINV0_0_1V (1 << BQ2429XR1_SYS_MINV_SHIFT)
#define BQ2429XR1_SYS_MINV0_0_2V (2 << BQ2429XR1_SYS_MINV_SHIFT)
#define BQ2429XR1_SYS_MINV0_0_4V (4 << BQ2429XR1_SYS_MINV_SHIFT)
#define BQ2429XR2_BOOST_LIM (1 << 0) /* 0=1A, 1=1.5A (default) Vout Boost Current Limit */
/* REG02 Charge Current Control */
#define BQ2429XR2_ICHG_SHIFT 2
#define BQ2429XR2_ICHG_MASK (0x3f << BQ2429XR2_ICHG_SHIFT)
#define BQ2429XR2_BCOLD (1 << 1) /* Boost Mode temperature threshold config for boost disable 0=76% 1=79% */
#define BQ2429XR2_FORCE_20PCT (1 << 0) /* Charge Configuration Threshold 0=Fast 1=less */
/* REG03 Pre-charge Termination Control Register */
#define BQ2429XR3_IPRECHG_SHIFT 4 /* Precharge I Limit. Offset 128mA Range 128-2048 mA */
#define BQ2429XR3_IPRECHG_MASK (0xf << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_0128mA (0x00 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_0128mA (0x01 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_0256mA (0x02 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_0384mA (0x03 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_0512mA (0x04 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_0768mA (0x05 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_0896mA (0x06 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1024mA (0x07 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1152mA (0x10 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1280mA (0x11 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1408mA (0x12 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1536mA (0x13 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1664mA (0x14 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1792mA (0x15 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_1920mA (0x16 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_IPRECHG_2048mA (0x17 << BQ2429XR3_IPRECHG_SHIFT)
#define BQ2429XR3_ITERM_SHIFT 0 /* Offset 128mA Range 128-2048 mA (128-1024 mA in BQ24296M )*/
#define BQ2429XR3_ITERM_MASK (0xf << BQ2429XR3_ITERM_SHIFT)
#define BQ2429XR3_ITERM0_128mA (1 << BQ2429XR3_ITERM_SHIFT)
#define BQ2429XR3_ITERM0_256mA (2 << BQ2429XR3_ITERM_SHIFT)
#define BQ2429XR3_ITERM0_512mA (4 << BQ2429XR3_ITERM_SHIFT)
#define BQ2429XR3_ITERM0_1024mA (8 << BQ2429XR3_ITERM_SHIFT) /* Reserved in BQ24296M */
/* REG04 Charge Voltage Control Register */
#define BQ2429XR4_VREG_SHIFT 2 /* Offset 3.504V Range 3.504-4.400V Default 4.208V */
#define BQ2429XR4_VREG_MASK (0x3f<< BQ2429XR4_VREG_SHIFT)
#define BQ2429XR4_BATLOWV (1 << 1) /* 0=2.8V 1=3.0V Pre-charge to fast Charge */
#define BQ2429XR4_VRECHG (1 << 0) /* 0=100mV 1=300mV */
/* REG05 Charge Termination Timer Control Register */
#define BQ2429XR5_EN_TERM (1 << 7) /* 0=Disable 1=Enable(default) terminate of charge */
#define BQ2429XR5_RESERVED6 (1 << 6)
#define BQ2429XR5_WATCHDOG_SHIFT 4 /* Watchdog Timer Settings */
#define BQ2429XR5_WATCHDOG_MASK (3 << BQ2429XR5_WATCHDOG_SHIFT)
# define BQ2429XR5_WATCHDOG_DIS (0 << BQ2429XR5_WATCHDOG_SHIFT)
# define BQ2429XR5_WATCHDOG_040Sec (1 << BQ2429XR5_WATCHDOG_SHIFT)
# define BQ2429XR5_WATCHDOG_080Sec (2 << BQ2429XR5_WATCHDOG_SHIFT)
# define BQ2429XR5_WATCHDOG_160Sec (3 << BQ2429XR5_WATCHDOG_SHIFT)
#define BQ2429XR5_EN_TIMER (1 << 3) /* 0=Disable 1=Enable(default) */
/* Fast Charge Timer Settings */
#define BQ2429XR5_CHG_TIMER_SHIFT 1
#define BQ2429XR5_CHG_TIMER_MASK (3 << BQ2429XR5_CHG_TIMER_SHIFT)
# define BQ2429XR5_CHG_TIMER_05hrs (0 << BQ2429XR5_CHG_TIMER_SHIFT)
# define BQ2429XR5_CHG_TIMER_08hrs (1 << BQ2429XR5_CHG_TIMER_SHIFT)
# define BQ2429XR5_CHG_TIMER_12hrs (2 << BQ2429XR5_CHG_TIMER_SHIFT)
# define BQ2429XR5_CHG_TIMER_20hrs (3 << BQ2429XR5_CHG_TIMER_SHIFT)
#define BQ2429XR5_RESERVED0 (1 << 0)
/* REG06 Boost Voltage/Thermal Regulation Control register */
#define BQ2429XR6_BOOSTV_SHIFT 4 /* Offset 4.55V Range 4.55-5.51A Dev 4.998V(0111) */
#define BQ2429XR6_BOOSTV_MASK (0xf << BQ2429XR6_BOOSTV_SHIFT)
# define BQ2429XR6_BOOSTV_064mV (1 << BQ2429XR6_BOOSTV_SHIFT)
# define BQ2429XR6_BOOSTV_128mV (2 << BQ2429XR6_BOOSTV_SHIFT)
# define BQ2429XR6_BOOSTV_256mV (4 << BQ2429XR6_BOOSTV_SHIFT)
# define BQ2429XR6_BOOSTV_512mV (8 << BQ2429XR6_BOOSTV_SHIFT)
#define BQ2429XR6_BHOT_SHIFT 2 /* Boost Mode temp threshold */
#define BQ2429XR6_BHOT_MASK (3 << BQ2429XR6_BHOT_SHIFT)
# define BQ2429XR6_BHOT_55C (0 << BQ2429XR6_BHOT_SHIFT)
# define BQ2429XR6_BHOT_60C (1 << BQ2429XR6_BHOT_SHIFT)
# define BQ2429XR6_BHOT_65C (2 << BQ2429XR6_BHOT_SHIFT)
# define BQ2429XR6_BHOT_DISABLE (3 << BQ2429XR6_BHOT_SHIFT)
#define BQ2429XR6_TREG_SHIFT 0 /* Thermal Regulation */
#define BQ2429XR6_TREG_MASK (3 << BQ2429XR6_TREG_SHIFT)
# define BQ2429XR6_TREG_060C (0 << BQ2429XR6_TREG_SHIFT)
# define BQ2429XR6_TREG_080C (1 << BQ2429XR6_TREG_SHIFT)
# define BQ2429XR6_TREG_100C (2 << BQ2429XR6_TREG_SHIFT)
# define BQ2429XR6_TREG_110C (3 << BQ2429XR6_TREG_SHIFT)
/* REG07 Misc Operation Control Register */
#define BQ2429XR7_DPDM_EN (1 << 7) /* 1=Force Detection when VBUS power is present */
#define BQ2429XR7_TMR2X_EN (1 << 6) /* 1=Safety Timer slowed by 2X during DPM/Thermal regulation */
#define BQ2429XR7_BATFET_DISABLE (1 << 5) /* 1=BATFET (Q4) turn off */
#define BQ2429XR7_RESERVED4 (1 << 4)
#define BQ2429XR7_RESERVED3 (1 << 3)
#define BQ2429XR7_RESERVED2 (1 << 2)
#define BQ2429XR7_INT_MASK1 (1 << 1) /* =1 (default) INT on CHRG_FAULT */
#define BQ2429XR7_INT_MASK0 (1 << 0) /* =1 (default) INT on BAT_FAULT */
/* REG08 Systems Status Register */
#define BQ2429XR8_VBUS_STAT_SHIFT 6 /* VBUS Connection Type */
#define BQ2429XR8_VBUS_STAT_MASK (3 << BQ2429XR8_VBUS_STAT_SHIFT)
# define BQ2429XR8_VBUS_STAT_UNKNOWN (0 << BQ2429XR8_VBUS_STAT_SHIFT)
# define BQ2429XR8_VBUS_STAT_USBH (1 << BQ2429XR8_VBUS_STAT_SHIFT)
# define BQ2429XR8_VBUS_STAT_ADAPTER (2 << BQ2429XR8_VBUS_STAT_SHIFT)
# define BQ2429XR8_VBUS_STAT_OTG (3 << BQ2429XR8_VBUS_STAT_SHIFT)
#define BQ2429XR8_CHRG_STAT_SHIFT 4 /* Charging Status */
#define BQ2429XR8_CHRG_STAT_MASK (3 << BQ2429XR8_CHRG_STAT_SHIFT)
# define BQ2429XR8_CHRG_STAT_NONE (0 << BQ2429XR8_CHRG_STAT_SHIFT)
# define BQ2429XR8_CHRG_STAT_PRECHG (1 << BQ2429XR8_CHRG_STAT_SHIFT)
# define BQ2429XR8_CHRG_STAT_FASTCHG (2 << BQ2429XR8_CHRG_STAT_SHIFT)
# define BQ2429XR8_CHRG_STAT_DONE (3 << BQ2429XR8_CHRG_STAT_SHIFT)
#define BQ2429XR8_DPM_STAT (1 << 3) /* 0= NotDPM 1=VINDPM or INDPM */
#define BQ2429XR8_PG_STAT (1 << 2) /* 0= Not 1=Power Good */
#define BQ2429XR8_THERM_STAT (1 << 1) /* 0= Normal 1=In Thermal Regulation */
#define BQ2429XR8_VSYS_STAT (1 << 0) /* 0= Not 1=In VSYSMIN regulation BAT < VSYSMIN */
/* REG09 New Fault Register */
#define BQ2429XR9_WATCHDOG_FAULT (1 << 7) /* 1=Watchdog Timer expired */
#define BQ2429XR9_OTG_FAULT (1 << 6) /* 1=Bus overloaded in OTG, or VBUS OVP or battery low */
#define BQ2429XR9_CHRG_FAULT_SHIFT 4 /* Charging Status */
#define BQ2429XR9_CHRG_FAULT_MASK (3 << BQ2429XR9_CHRG_FAULT_SHIFT)
# define BQ2429XR9_CHRG_FAULT_NORMAL (0 << BQ2429XR9_CHRG_FAULT_SHIFT)
# define BQ2429XR9_CHRG_FAULT_INPUT (1 << BQ2429XR9_CHRG_FAULT_SHIFT)
# define BQ2429XR9_CHRG_FAULT_THERMAL (2 << BQ2429XR9_CHRG_FAULT_SHIFT)
# define BQ2429XR9_CHRG_FAULT_TIMER (3 << BQ2429XR9_CHRG_FAULT_SHIFT)
#define BQ2429XR9_BAT_FAULT (1 << 3) /* 1=Battery OVP */
#define BQ2429XR9_RESERVED2 (1 << 2)
#define BQ2429XR9_NTC_FAULT1_COLD (1 << 1) /* Cold temperature */
#define BQ2429XR9_NTC_FAULT2_HOT (1 << 0) /* Hot temperature */
/* REG0A Vendor Part Revision Info */
#define BQ24296_VENDOR_ID 0x20 /* BQ24296 */
#define BQ24296M_VENDOR_ID 0x20 /* BQ24296M */
#define BQ24297_VENDOR_ID 0x60 /* BQ24297 */
#endif /* __DRIVERS_POWER_BQ2429X_H */

View File

@ -447,7 +447,6 @@ uint16_t devif_conn_event(FAR struct net_driver_s *dev, void *pvconn,
* beginning of the list (which will be ignored on this pass) * beginning of the list (which will be ignored on this pass)
*/ */
ninfo("Call event=%p with flags=%04x\n", list->event, flags);
flags = list->event(dev, pvconn, list->priv, flags); flags = list->event(dev, pvconn, list->priv, flags);
} }
@ -511,7 +510,6 @@ uint16_t devif_dev_event(FAR struct net_driver_s *dev, void *pvconn,
* beginning of the list (which will be ignored on this pass) * beginning of the list (which will be ignored on this pass)
*/ */
ninfo("Call event=%p with flags=%04x\n", cb->event, flags);
flags = cb->event(dev, pvconn, cb->priv, flags); flags = cb->event(dev, pvconn, cb->priv, flags);
} }

View File

@ -67,7 +67,7 @@
void devif_send(struct net_driver_s *dev, const void *buf, int len) void devif_send(struct net_driver_s *dev, const void *buf, int len)
{ {
DEBUGASSERT(dev && len > 0 && len < NET_DEV_MTU(dev)); DEBUGASSERT(dev != NULL && len > 0 && len < NET_DEV_MTU(dev));
memcpy(dev->d_appdata, buf, len); memcpy(dev->d_appdata, buf, len);
dev->d_sndlen = len; dev->d_sndlen = len;

View File

@ -51,6 +51,7 @@
#include <nuttx/clock.h> #include <nuttx/clock.h>
#include <nuttx/semaphore.h> #include <nuttx/semaphore.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h> #include <nuttx/net/net.h>
#include <nuttx/net/radiodev.h> #include <nuttx/net/radiodev.h>
#include <netpacket/ieee802154.h> #include <netpacket/ieee802154.h>

View File

@ -64,7 +64,7 @@
#endif #endif
#if defined(CONFIG_NET_TCP) #if defined(CONFIG_NET_TCP)
# define L3_MAXHDRLEN TCP_MAX_HDRLEN # define L3_MAXHDRLEN TCP_HDRLEN /* Could be up to TCP_MAX_HDRLEN */
#elif defined(CONFIG_NET_UDP) #elif defined(CONFIG_NET_UDP)
# define L3_MAXHDRLEN UDP_HDRLEN # define L3_MAXHDRLEN UDP_HDRLEN
#elif defined(CONFIG_NET_ICMPv6) #elif defined(CONFIG_NET_ICMPv6)

View File

@ -12,6 +12,40 @@ config NET_6LOWPAN_FRAG
CONFIG_NET_6LOWPAN_FRAG specifies if 6lowpan fragmentation should be CONFIG_NET_6LOWPAN_FRAG specifies if 6lowpan fragmentation should be
used or not. Fragmentation is on by default. used or not. Fragmentation is on by default.
config NET_6LOWPAN_NREASSBUF
int "Number of preallocated reassembly buffers"
default 2
depends on NET_6LOWPAN_FRAG
---help---
Large IPv6 packets will be fragmented by 6LoWPAN into multiple
frames and reconstitued into a reassembly buffer on the receiving
side. Each concurrent reassembly requires one buffer. Reassembly
buffers are large: The size of the 6LoWPAN MTU plus some overhead
for the reassembly state.
Some reassembly buffers may be preallocated; some may be allocated
dynamically from the stack. The former require more static memory
usage; the later require additional CPU cycles to perform the
allocation and may effect deterministic behavior. So this is a
trade-off between resources and performance. If the number of pre-
allocated reassembly buffers are exhausted, the reassembly will
continue with dynamically allocated reassembly buffers.
This behavior can be changed with CONFIG_NET_6LOWPAN_REASS_STATIC
config NET_6LOWPAN_REASS_STATIC
bool "Static reassembly buffers"
default n
depends on NET_6LOWPAN_FRAG
---help---
By default, reassembly buffers may be allocated dynamically from the
stack when all of the statically allocation reassembly buffers are
in use. This will equire additional CPU cycles to perform the
allocation and may effect deterministic behavior. This option may
be selected to suppress all dynamica allocation of reassembly
buffers. In that case, only static reassembly buffers are available;
when those are exhausted, frames that require reassembly will be lost.
config NET_6LOWPAN_FRAMELEN config NET_6LOWPAN_FRAMELEN
int "Max Radio Frame Size" int "Max Radio Frame Size"
default 127 default 127

View File

@ -68,6 +68,10 @@ ifeq ($(CONFIG_NET_6LOWPAN_COMPRESSION_HC06),y)
NET_CSRCS += sixlowpan_hc06.c NET_CSRCS += sixlowpan_hc06.c
endif endif
ifeq ($(CONFIG_NET_6LOWPAN_FRAG),y)
NET_CSRCS += sixlowpan_reassbuf.c
endif
# Include the sixlowpan directory in the build # Include the sixlowpan directory in the build
DEPPATH += --dep-path sixlowpan DEPPATH += --dep-path sixlowpan

View File

@ -54,6 +54,7 @@
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
#include <nuttx/net/radiodev.h> #include <nuttx/net/radiodev.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h> #include <nuttx/wireless/ieee802154/ieee802154_mac.h>
@ -384,9 +385,9 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
FAR uint8_t *fptr; FAR uint8_t *fptr;
int framer_hdrlen; int framer_hdrlen;
struct netdev_varaddr_s bcastmac; struct netdev_varaddr_s bcastmac;
#ifdef CONFIG_NET_6LOWPAN_FRAG
uint16_t pktlen; uint16_t pktlen;
uint16_t paysize; uint16_t paysize;
#ifdef CONFIG_NET_6LOWPAN_FRAG
uint16_t outlen = 0; uint16_t outlen = 0;
#endif #endif
uint8_t protosize; uint8_t protosize;
@ -505,12 +506,18 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
* added at qtail. * added at qtail.
*/ */
FAR struct sixlowpan_reassbuf_s *reass;
FAR struct iob_s *qhead; FAR struct iob_s *qhead;
FAR struct iob_s *qtail; FAR struct iob_s *qtail;
FAR uint8_t *frame1; FAR uint8_t *frame1;
FAR uint8_t *fragptr; FAR uint8_t *fragptr;
uint16_t frag1_hdrlen; uint16_t frag1_hdrlen;
/* Recover the reassembly buffer from the driver d_buf. */
reass = (FAR struct sixlowpan_reassbuf_s *)radio->r_dev.d_buf;
DEBUGASSERT(reass != NULL);
/* The outbound IPv6 packet is too large to fit into a single 15.4 /* The outbound IPv6 packet is too large to fit into a single 15.4
* packet, so we fragment it into multiple packets and send them. * packet, so we fragment it into multiple packets and send them.
* The first fragment contains frag1 dispatch, then * The first fragment contains frag1 dispatch, then
@ -548,7 +555,7 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
pktlen = buflen + g_uncomp_hdrlen + protosize; pktlen = buflen + g_uncomp_hdrlen + protosize;
PUTHOST16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE, PUTHOST16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE,
((SIXLOWPAN_DISPATCH_FRAG1 << 8) | pktlen)); ((SIXLOWPAN_DISPATCH_FRAG1 << 8) | pktlen));
PUTHOST16(fragptr, SIXLOWPAN_FRAG_TAG, radio->r_dgramtag); PUTHOST16(fragptr, SIXLOWPAN_FRAG_TAG, reass->rb_dgramtag);
g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN; g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
@ -575,7 +582,7 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
outlen = paysize; outlen = paysize;
ninfo("First fragment: length %d, tag %d\n", ninfo("First fragment: length %d, tag %d\n",
paysize, radio->r_dgramtag); paysize, reass->rb_dgramtag);
sixlowpan_dumpbuffer("Outgoing frame", sixlowpan_dumpbuffer("Outgoing frame",
(FAR const uint8_t *)iob->io_data, iob->io_len); (FAR const uint8_t *)iob->io_data, iob->io_len);
@ -630,7 +637,7 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
PUTHOST16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE, PUTHOST16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE,
((SIXLOWPAN_DISPATCH_FRAGN << 8) | pktlen)); ((SIXLOWPAN_DISPATCH_FRAGN << 8) | pktlen));
PUTHOST16(fragptr, SIXLOWPAN_FRAG_TAG, radio->r_dgramtag); PUTHOST16(fragptr, SIXLOWPAN_FRAG_TAG, reass->rb_dgramtag);
fragptr[SIXLOWPAN_FRAG_OFFSET] = outlen >> 3; fragptr[SIXLOWPAN_FRAG_OFFSET] = outlen >> 3;
fragn_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN; fragn_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
@ -654,8 +661,8 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
iob->io_len = paysize + fragn_hdrlen; iob->io_len = paysize + fragn_hdrlen;
outlen += paysize; outlen += paysize;
ninfo("Fragment offset=%d, paysize=%d, r_dgramtag=%d\n", ninfo("Fragment offset=%d, paysize=%d, rb_dgramtag=%d\n",
outlen >> 3, paysize, radio->r_dgramtag); outlen >> 3, paysize, reass->rb_dgramtag);
sixlowpan_dumpbuffer("Outgoing frame", sixlowpan_dumpbuffer("Outgoing frame",
(FAR const uint8_t *)iob->io_data, (FAR const uint8_t *)iob->io_data,
iob->io_len); iob->io_len);
@ -697,7 +704,7 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
/* Update the datagram TAG value */ /* Update the datagram TAG value */
radio->r_dgramtag++; reass->rb_dgramtag++;
#else #else
nerr("ERROR: Packet too large: %d\n", buflen); nerr("ERROR: Packet too large: %d\n", buflen);
nerr(" Cannot to be sent without fragmentation support\n"); nerr(" Cannot to be sent without fragmentation support\n");

View File

@ -61,6 +61,7 @@
#include <string.h> #include <string.h>
#include <debug.h> #include <debug.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
#include <nuttx/net/radiodev.h> #include <nuttx/net/radiodev.h>
#include <nuttx/net/ip.h> #include <nuttx/net/ip.h>

View File

@ -53,6 +53,7 @@
#include <assert.h> #include <assert.h>
#include <debug.h> #include <debug.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
#include <nuttx/net/radiodev.h> #include <nuttx/net/radiodev.h>
#include "sixlowpan/sixlowpan_internal.h" #include "sixlowpan/sixlowpan_internal.h"

View File

@ -69,6 +69,12 @@
void sixlowpan_initialize(void) void sixlowpan_initialize(void)
{ {
#ifdef CONFIG_NET_6LOWPAN_FRAG
/* Initialize the reassembly buffer allocator */
sixlowpan_reass_initialize();
#endif
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06 #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
/* Initialize HC06 data data structures */ /* Initialize HC06 data data structures */

View File

@ -54,10 +54,7 @@
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#ifdef CONFIG_NET_6LOWPAN_FRAG #include "nuttx/mm/iob.h"
# include "nuttx/clock.h"
#endif
#include "nuttx/net/netdev.h" #include "nuttx/net/netdev.h"
#include "nuttx/net/radiodev.h" #include "nuttx/net/radiodev.h"
#include "nuttx/net/ip.h" #include "nuttx/net/ip.h"
@ -82,10 +79,6 @@
#define INPUT_PARTIAL 0 /* Frame processed successful, packet incomplete */ #define INPUT_PARTIAL 0 /* Frame processed successful, packet incomplete */
#define INPUT_COMPLETE 1 /* Frame processed successful, packet complete */ #define INPUT_COMPLETE 1 /* Frame processed successful, packet complete */
/* Re-assembly timeout in clock ticks */
#define NET_6LOWPAN_TIMEOUT SEC2TICK(CONFIG_NET_6LOWPAN_MAXAGE)
/* This is the size of a buffer large enough to hold the largest uncompressed /* This is the size of a buffer large enough to hold the largest uncompressed
* HC06 or HC1 headers. * HC06 or HC1 headers.
*/ */
@ -132,50 +125,6 @@ static uint8_t g_bitbucket[UNCOMP_MAXHDR];
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: sixlowpan_compare_fragsrc
*
* Description:
* Check if the fragment that we just received is from the same source as
* the previosly received fragements.
*
* Input Parameters:
* radio - Radio network device driver state instance
* metadata - Characteristics of the newly received frame
*
* Returned Value:
* true if the sources are the same.
*
****************************************************************************/
static bool sixlowpan_compare_fragsrc(FAR struct radio_driver_s *radio,
FAR const void *metadata)
{
struct netdev_varaddr_s fragsrc;
int ret;
/* Extract the source address from the 'metadata' */
ret = sixlowpan_extract_srcaddr(radio, metadata, &fragsrc);
if (ret < 0)
{
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
return false;
}
/* The addresses cannot match if they are not the same size */
if (fragsrc.nv_addrlen == radio->r_fragsrc.nv_addrlen)
{
/* The are the same sizer, return the address comparisson */
return (memcmp(fragsrc.nv_addr, radio->r_fragsrc.nv_addr,
fragsrc.nv_addrlen) == 0);
}
return false;
}
/**************************************************************************** /****************************************************************************
* Name: sixlowpan_compress_ipv6hdr * Name: sixlowpan_compress_ipv6hdr
* *
@ -311,14 +260,15 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */ uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */
int reqsize; /* Required buffer size */ int reqsize; /* Required buffer size */
int hdrsize; /* Size of the IEEE802.15.4 header */ int hdrsize; /* Size of the IEEE802.15.4 header */
int ret;
#ifdef CONFIG_NET_6LOWPAN_FRAG #ifdef CONFIG_NET_6LOWPAN_FRAG
FAR struct sixlowpan_reassbuf_s *reass;
struct netdev_varaddr_s fragsrc;
FAR uint8_t *fragptr; /* Pointer to the fragmentation header */ FAR uint8_t *fragptr; /* Pointer to the fragmentation header */
bool isfrag = false; bool isfrag = false;
bool isfirstfrag = false; bool isfirstfrag = false;
uint16_t fragtag = 0; /* Tag of the fragment */ uint16_t fragtag = 0; /* Tag of the fragment */
systime_t elapsed; /* Elapsed time */
int ret;
#endif /* CONFIG_NET_6LOWPAN_FRAG */ #endif /* CONFIG_NET_6LOWPAN_FRAG */
/* Get a pointer to the payload following the IEEE802.15.4 frame header(s). /* Get a pointer to the payload following the IEEE802.15.4 frame header(s).
@ -359,166 +309,119 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
ninfo("FRAG1: fragsize=%d fragtag=%d fragoffset=%d\n", ninfo("FRAG1: fragsize=%d fragtag=%d fragoffset=%d\n",
fragsize, fragtag, fragoffset); fragsize, fragtag, fragoffset);
/* Drop any zero length fragments */
if (fragsize == 0)
{
nwarn("WARNING: Dropping zero-length 6LoWPAN fragment\n");
return INPUT_PARTIAL;
}
/* Drop the packet if it cannot fit into the d_buf */
if (fragsize > CONFIG_NET_6LOWPAN_MTU)
{
nwarn("WARNING: Reassembled packet size exeeds CONFIG_NET_6LOWPAN_MTU\n");
return -ENOSPC;
}
/* Extract the source address from the 'metadata'. */
ret = sixlowpan_extract_srcaddr(radio, metadata, &fragsrc);
if (ret < 0)
{
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
return ret;
}
/* Allocate a new reassembly buffer */
reass = sixlowpan_reass_allocate(fragtag, &fragsrc);
if (reass == NULL)
{
nerr("ERROR: Failed to allocate a reassembly buffer\n");
return -ENOMEM;
}
radio->r_dev.d_buf = reass->rb_buf;
radio->r_dev.d_len = 0;
reass->rb_pktlen = fragsize;
/* Indicate the first fragment of the reassembly */ /* Indicate the first fragment of the reassembly */
isfirstfrag = true; bptr = reass->rb_buf;
isfrag = true; isfirstfrag = true;
isfrag = true;
} }
break; break;
case SIXLOWPAN_DISPATCH_FRAGN: case SIXLOWPAN_DISPATCH_FRAGN:
{ {
/* Set offset, tag, size. Offset is in units of 8 bytes. */ /* Get offset, tag, size. Offset is in units of 8 bytes. */
fragoffset = fragptr[SIXLOWPAN_FRAG_OFFSET]; fragoffset = fragptr[SIXLOWPAN_FRAG_OFFSET];
fragtag = GETUINT16(fragptr, SIXLOWPAN_FRAG_TAG); fragtag = GETUINT16(fragptr, SIXLOWPAN_FRAG_TAG);
fragsize = GETUINT16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE) & 0x07ff; fragsize = GETUINT16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE) & 0x07ff;
g_frame_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN; g_frame_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
/* Extract the source address from the 'metadata'. */
ret = sixlowpan_extract_srcaddr(radio, metadata, &fragsrc);
if (ret < 0)
{
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
return ret;
}
/* Find the existing reassembly buffer with the same tag and source address */
reass = sixlowpan_reass_find(fragtag, &fragsrc);
if (reass == NULL)
{
nerr("ERROR: Failed to find a reassembly buffer for tag=%04x\n",
fragtag);
return -ENOENT;
}
if (fragsize != reass->rb_pktlen)
{
/* The packet is a fragment but its size does not match. */
nwarn("WARNING: Dropping 6LoWPAN packet. Bad fragsize: %u vs &u\n",
fragsize, reass->rb_pktlen);
ret = -EPERM;
goto errout_with_reass;
}
radio->r_dev.d_buf = reass->rb_buf;
radio->r_dev.d_len = 0;
ninfo("FRAGN: fragsize=%d fragtag=%d fragoffset=%d\n", ninfo("FRAGN: fragsize=%d fragtag=%d fragoffset=%d\n",
fragsize, fragtag, fragoffset); fragsize, fragtag, fragoffset);
ninfo("FRAGN: r_accumlen=%d paysize=%u fragsize=%u\n", ninfo("FRAGN: rb_accumlen=%d paysize=%u fragsize=%u\n",
radio->r_accumlen, iob->io_len - g_frame_hdrlen, fragsize); reass->rb_accumlen, iob->io_len - g_frame_hdrlen, fragsize);
/* Indicate that this frame is a another fragment for reassembly */ /* Indicate that this frame is a another fragment for reassembly */
isfrag = true; bptr = g_bitbucket;
isfrag = true;
} }
break; break;
/* Not a fragment */ /* Not a fragment */
default: default:
/* We still need a packet buffer. But in this case, the driver should
* have provided one.
*/
DEBUGASSERT(radio->r_dev.d_buf != NULL);
reass = (FAR struct sixlowpan_reassbuf_s *)radio->r_dev.d_buf;
bptr = reass->rb_buf;
break; break;
} }
#else
/* Check if we are currently reassembling a packet */ bptr = radio->r_dev.d_buf;
bptr = radio->r_dev.d_buf;
if (radio->r_accumlen > 0)
{
/* If reassembly timed out, cancel it */
elapsed = clock_systimer() - radio->r_time;
if (elapsed > NET_6LOWPAN_TIMEOUT)
{
nwarn("WARNING: Reassembly timed out\n");
radio->r_pktlen = 0;
radio->r_accumlen = 0;
}
/* In this case what we expect is that the next frame will hold the
* next FRAGN of the sequence. We have to handle a few exeptional
* cases that we need to handle:
*
* 1. If we are currently reassembling a packet, but have just received
* the first fragment of another packet. We can either ignore it and
* hope to receive the rest of the under-reassembly packet fragments,
* or we can discard the previous packet altogether, and start
* reassembling the new packet. Here we discard the previous packet,
* and start reassembling the new packet.
* 2. The new frame is not a fragment. We should be able to handle this
* case, but we cannot because that would require two packet buffers.
* It could be handled with a more extensive design.
* 3. The fragment came from a different sender. What would this mean?
*
*/
else if (!isfrag)
{
/* Discard the partially assembled packet */
nwarn("WARNING: Non-fragment frame received during reassembly\n");
radio->r_pktlen = 0;
radio->r_accumlen = 0;
}
/* It is a fragment of some kind. Drop any zero length fragments */
else if (fragsize == 0)
{
nwarn("WARNING: Dropping zero-length 6LoWPAN fragment\n");
return INPUT_PARTIAL;
}
/* A non-zero, first fragement received while we are in the middle of
* rassembly. Discard the partially assembled packet and start over.
*/
else if (isfirstfrag)
{
nwarn("WARNING: First fragment frame received during reassembly\n");
radio->r_pktlen = 0;
radio->r_accumlen = 0;
}
/* Verify that this fragment is part of that reassembly sequence */
else if (fragsize != radio->r_pktlen || radio->r_reasstag != fragtag ||
!sixlowpan_compare_fragsrc(radio, metadata))
{
/* The packet is a fragment that does not belong to the packet
* being reassembled or the packet is not a fragment.
*/
nwarn("WARNING: Dropping 6LoWPAN packet that is not a fragment of "
"the packet currently being reassembled\n");
return -EPERM;
}
else
{
/* Looks good. We are currently processing a reassembling sequence
* and we recieved a valid FRAGN fragment. Redirect the header
* uncompression to our bitbucket.
*/
bptr = g_bitbucket;
}
}
/* There is no reassembly in progress. Check if we received a fragment */
else if (isfrag)
{
/* Another case that we have to handle is if a FRAGN fragment of a
* reassembly is received, but we are not currently reassembling a
* packet. I think we have no choice but to drop the packet in this
* case.
*/
if (!isfirstfrag)
{
nwarn("WARNING: FRAGN 6LoWPAN fragment while not reassembling\n");
return -EPERM;
}
/* Drop the packet if it cannot fit into the d_buf */
if (fragsize > CONFIG_NET_6LOWPAN_MTU)
{
nwarn("WARNING: Reassembled packet size exeeds CONFIG_NET_6LOWPAN_MTU\n");
return -ENOSPC;
}
radio->r_pktlen = fragsize;
radio->r_reasstag = fragtag;
radio->r_time = clock_systimer();
ninfo("Starting reassembly: r_pktlen %u, r_reasstag %d\n",
radio->r_pktlen, radio->r_reasstag);
/* Extract the source address from the 'metadata'. NOTE that the size
* of the source address may be different than our local, destination
* address.
*/
ret = sixlowpan_extract_srcaddr(radio, metadata, &radio->r_fragsrc);
if (ret < 0)
{
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
return ret;
}
}
#endif /* CONFIG_NET_6LOWPAN_FRAG */ #endif /* CONFIG_NET_6LOWPAN_FRAG */
/* Process next dispatch and headers */ /* Process next dispatch and headers */
@ -553,7 +456,8 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
/* Unknown or unsupported header */ /* Unknown or unsupported header */
nwarn("WARNING: Unknown dispatch: %u\n", hc1[SIXLOWPAN_HC1_DISPATCH]); nwarn("WARNING: Unknown dispatch: %u\n", hc1[SIXLOWPAN_HC1_DISPATCH]);
return -ENOSYS; ret = -ENOSYS;
goto errout_with_reass;
} }
#ifdef CONFIG_NET_6LOWPAN_FRAG #ifdef CONFIG_NET_6LOWPAN_FRAG
@ -565,7 +469,7 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
* begin placing the data payload. * begin placing the data payload.
*/ */
radio->r_boffset = g_uncomp_hdrlen; reass->rb_boffset = g_uncomp_hdrlen;
} }
/* No.. is this a subsequent fragment in the same sequence? */ /* No.. is this a subsequent fragment in the same sequence? */
@ -576,7 +480,7 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
* we began placing payload data. * we began placing payload data.
*/ */
g_uncomp_hdrlen = radio->r_boffset; g_uncomp_hdrlen = reass->rb_boffset;
} }
#endif /* CONFIG_NET_6LOWPAN_FRAG */ #endif /* CONFIG_NET_6LOWPAN_FRAG */
@ -591,7 +495,8 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
{ {
nwarn("WARNING: Packet dropped due to payload (%u) > packet buffer (%u)\n", nwarn("WARNING: Packet dropped due to payload (%u) > packet buffer (%u)\n",
paysize, CONFIG_NET_6LOWPAN_MTU); paysize, CONFIG_NET_6LOWPAN_MTU);
return -ENOSPC; ret = -ENOSPC;
goto errout_with_reass;
} }
/* Sanity-check size of incoming packet to avoid buffer overflow */ /* Sanity-check size of incoming packet to avoid buffer overflow */
@ -602,14 +507,15 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
nwarn("WARNING: Required buffer size: %u+%u+%u=%u Available=%u\n", nwarn("WARNING: Required buffer size: %u+%u+%u=%u Available=%u\n",
g_uncomp_hdrlen, (fragoffset << 3), paysize, g_uncomp_hdrlen, (fragoffset << 3), paysize,
reqsize, CONFIG_NET_6LOWPAN_MTU); reqsize, CONFIG_NET_6LOWPAN_MTU);
return -ENOMEM; ret = -ENOMEM;
goto errout_with_reass;
} }
memcpy(radio->r_dev.d_buf + g_uncomp_hdrlen + (fragoffset << 3), memcpy(radio->r_dev.d_buf + g_uncomp_hdrlen + (fragoffset << 3),
fptr + g_frame_hdrlen, paysize); fptr + g_frame_hdrlen, paysize);
#ifdef CONFIG_NET_6LOWPAN_FRAG #ifdef CONFIG_NET_6LOWPAN_FRAG
/* Update radio->r_accumlen if the frame is a fragment, radio->r_pktlen /* Update reass->rb_accumlen if the frame is a fragment, reass->rb_pktlen
* otherwise. * otherwise.
*/ */
@ -621,36 +527,49 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
* bytes at the end. We must be liberal in what we accept. * bytes at the end. We must be liberal in what we accept.
*/ */
radio->r_accumlen = g_uncomp_hdrlen + (fragoffset << 3) + paysize; reass->rb_accumlen = g_uncomp_hdrlen + (fragoffset << 3) + paysize;
} }
else else
{ {
radio->r_pktlen = paysize + g_uncomp_hdrlen; reass->rb_pktlen = paysize + g_uncomp_hdrlen;
} }
/* If we have a full IP packet in sixlowpan_buf, deliver it to /* If we have a full IP packet in sixlowpan_buf, deliver it to
* the IP stack * the IP stack
*/ */
ninfo("r_accumlen=%d r_pktlen=%d paysize=%d\n", ninfo("rb_accumlen=%d rb_pktlen=%d paysize=%d\n",
radio->r_accumlen, radio->r_pktlen, paysize); reass->rb_accumlen, reass->rb_pktlen, paysize);
if (radio->r_accumlen == 0 || radio->r_accumlen >= radio->r_pktlen) if (reass->rb_accumlen == 0 || reass->rb_accumlen >= reass->rb_pktlen)
{ {
ninfo("IP packet ready (length %d)\n", radio->r_pktlen); ninfo("IP packet ready (length %d)\n", reass->rb_pktlen);
radio->r_dev.d_len = radio->r_pktlen; radio->r_dev.d_buf = reass->rb_buf;
radio->r_pktlen = 0; radio->r_dev.d_len = reass->rb_pktlen;
radio->r_accumlen = 0; reass->rb_active = false;
reass->rb_pktlen = 0;
reass->rb_accumlen = 0;
return INPUT_COMPLETE; return INPUT_COMPLETE;
} }
radio->r_dev.d_buf = NULL;
radio->r_dev.d_len = 0;
return INPUT_PARTIAL; return INPUT_PARTIAL;
errout_with_reass:
sixlowpan_reass_free(reass);
return ret;
#else #else
/* Deliver the packet to the IP stack */ /* Deliver the packet to the IP stack */
radio->r_dev.d_len = paysize + g_uncomp_hdrlen; radio->r_dev.d_len = paysize + g_uncomp_hdrlen;
return INPUT_COMPLETE; return INPUT_COMPLETE;
errout_with_reass:
return ret;
#endif /* CONFIG_NET_6LOWPAN_FRAG */ #endif /* CONFIG_NET_6LOWPAN_FRAG */
} }
@ -670,6 +589,11 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
static int sixlowpan_dispatch(FAR struct radio_driver_s *radio) static int sixlowpan_dispatch(FAR struct radio_driver_s *radio)
{ {
#ifdef CONFIG_NET_6LOWPAN_FRAG
FAR struct sixlowpan_reassbuf_s *reass;
#endif
int ret;
sixlowpan_dumpbuffer("Incoming packet", sixlowpan_dumpbuffer("Incoming packet",
(FAR const uint8_t *)IPv6BUF(&radio->r_dev), (FAR const uint8_t *)IPv6BUF(&radio->r_dev),
radio->r_dev.d_len); radio->r_dev.d_len);
@ -691,7 +615,17 @@ static int sixlowpan_dispatch(FAR struct radio_driver_s *radio)
* be set to zero. Oddly, ipv6_input() will return OK in this case. * be set to zero. Oddly, ipv6_input() will return OK in this case.
*/ */
return ipv6_input(&radio->r_dev); ret = ipv6_input(&radio->r_dev);
#ifdef CONFIG_NET_6LOWPAN_FRAG
/* Free the reassemby buffer */
reass = (FAR struct sixlowpan_reassbuf_s *)radio->r_dev.d_buf;
DEBUGASSERT(reass != NULL);
sixlowpan_reass_free(reass);
#endif
return ret;
} }
/**************************************************************************** /****************************************************************************

View File

@ -115,8 +115,13 @@
/* Sucessful return values from header compression logic */ /* Sucessful return values from header compression logic */
#define COMPRESS_HDR_INLINE 0 /* L2 header not compressed */ #define COMPRESS_HDR_INLINE 0 /* L2 header not compressed */
#define COMPRESS_HDR_ELIDED 1 /* L2 header compressed */ #define COMPRESS_HDR_ELIDED 1 /* L2 header compressed */
/* Memory Pools *************************************************************/
#define REASS_POOL_PREALLOCATED 0
#define REASS_POOL_DYNAMIC 1
/* Debug ********************************************************************/ /* Debug ********************************************************************/
@ -657,5 +662,107 @@ int sixlowpan_extract_destaddr(FAR struct radio_driver_s *radio,
FAR const void *metadata, FAR const void *metadata,
FAR struct netdev_varaddr_s *destaddr); FAR struct netdev_varaddr_s *destaddr);
/****************************************************************************
* Name: sixlowpan_reass_initialize
*
* Description:
* This function initializes the reassembly buffer allocator. This
* function must be called early in the initialization sequence before
* any radios begin operation.
*
* Called only once during network initialization.
*
* Inputs:
* None
*
* Return Value:
* None
*
****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN_FRAG
void sixlowpan_reass_initialize(void);
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/****************************************************************************
* Name: sixlowpan_reass_allocate
*
* Description:
* The sixlowpan_reass_allocate function will get a free reassembly buffer
* structure for use by 6LoWPAN.
*
* This function will first attempt to allocate from the g_free_reass
* list. If that the list is empty, then the reassembly buffer structure
* will be allocated from the dynamic memory pool.
*
* Inputs:
* reasstag - The reassembly tag for subsequent lookup.
* fragsrc - The source address of the fragment.
*
* Return Value:
* A reference to the allocated reass structure. All fields used by the
* reasembly logic have been zeroed. On a failure to allocate, NULL is
* returned.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN_FRAG
FAR struct sixlowpan_reassbuf_s *
sixlowpan_reass_allocate(uint16_t reasstag,
FAR const struct netdev_varaddr_s *fragsrc);
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/****************************************************************************
* Name: sixlowpan_reass_find
*
* Description:
* Find a previously allocated, active reassembly buffer with the specified
* reassembly tag.
*
* Inputs:
* reasstag - The reassembly tag to match.
* fragsrc - The source address of the fragment.
*
* Return Value:
* A reference to the matching reass structure.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN_FRAG
FAR struct sixlowpan_reassbuf_s *
sixlowpan_reass_find(uint16_t reasstag,
FAR const struct netdev_varaddr_s *fragsrc);
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/****************************************************************************
* Name: sixlowpan_reass_free
*
* Description:
* The sixlowpan_reass_free function will return a reass structure
* to the free list of messages if it was a pre-allocated reass
* structure. If the reass structure was allocated dynamically it will
* be deallocated.
*
* Inputs:
* reass - reass structure to free
*
* Return Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN_FRAG
void sixlowpan_reass_free(FAR struct sixlowpan_reassbuf_s *reass);
#endif /* CONFIG_NET_6LOWPAN_FRAG */
#endif /* CONFIG_NET_6LOWPAN */ #endif /* CONFIG_NET_6LOWPAN */
#endif /* _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H */ #endif /* _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H */

View File

@ -0,0 +1,458 @@
/****************************************************************************
* net/sixlowpan/sixlowpan_reassbuf.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/clock.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mm/iob.h>
#include "sixlowpan_internal.h"
#ifdef CONFIG_NET_6LOWPAN_FRAG
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Re-assembly timeout in clock ticks */
#define NET_6LOWPAN_TIMEOUT SEC2TICK(CONFIG_NET_6LOWPAN_MAXAGE)
/****************************************************************************
* Private Data
****************************************************************************/
/* The g_free_reass is a list of reassembly buffer structures that are available for
* general use. The number of messages in this list is a system configuration
* item. Protected only by the network lock.
*/
static FAR struct sixlowpan_reassbuf_s *g_free_reass;
/* This is a list of active, allocated reassemby buffers */
static FAR struct sixlowpan_reassbuf_s *g_active_reass;
/* Pool of pre-allocated reassembly buffer stuctures */
static struct sixlowpan_reassbuf_s g_metadata_pool[CONFIG_NET_6LOWPAN_NREASSBUF];
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sixlowpan_compare_fragsrc
*
* Description:
* Check if the fragment that we just received is from the same source as
* the previosly received fragements.
*
* Input Parameters:
* radio - Radio network device driver state instance
* fragsrc - The source address of the fragment.
*
* Returned Value:
* true if the sources are the same.
*
****************************************************************************/
static bool sixlowpan_compare_fragsrc(FAR struct sixlowpan_reassbuf_s *reass,
FAR const struct netdev_varaddr_s *fragsrc)
{
/* The addresses cannot match if they are not the same size */
if (fragsrc->nv_addrlen == reass->rb_fragsrc.nv_addrlen)
{
/* The are the same size, return the address comparison */
return (memcmp(fragsrc->nv_addr, reass->rb_fragsrc.nv_addr,
fragsrc->nv_addrlen) == 0);
}
return false;
}
/****************************************************************************
* Name: sixlowpan_reass_expire
*
* Description:
* Free all expired or inactive reassembly buffers.
*
* Inputs:
* None
*
* Return Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static void sixlowpan_reass_expire(void)
{
FAR struct sixlowpan_reassbuf_s *reass;
FAR struct sixlowpan_reassbuf_s *next;
systime_t elapsed;
/* If reassembly timed out, cancel it */
for (reass = g_active_reass; reass != NULL; reass = next)
{
/* Needed if 'reass' is freed */
next = reass->rb_flink;
/* Free any inactive reassembly buffers. This is done because the life
* the reassembly buffer is not cerain.
*/
if (!reass->rb_active)
{
sixlowpan_reass_free(reass);
}
else
{
/* Get the elpased time of the reassembly */
elapsed = clock_systimer() - reass->rb_time;
/* If the reassembly has expired, then free the reassembly buffer */
if (elapsed > NET_6LOWPAN_TIMEOUT)
{
nwarn("WARNING: Reassembly timed out\n");
sixlowpan_reass_free(reass);
}
}
}
}
/****************************************************************************
* Name: sixlowpan_remove_active
*
* Description:
* Remove a reassembly buffer from the active reassembly buffer list.
*
* Inputs:
* reass - The reassembly buffer to be removed.
*
* Return Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static void sixlowpan_remove_active(FAR struct sixlowpan_reassbuf_s *reass)
{
FAR struct sixlowpan_reassbuf_s *curr;
FAR struct sixlowpan_reassbuf_s *prev;
/* Find the reassembly buffer in the list of active reassembly buffers */
for (prev = NULL, curr = g_active_reass;
curr != NULL && curr != reass;
prev = curr, curr = curr->rb_flink)
{
}
/* Did we find it? */
if (curr != NULL)
{
/* Yes.. remove it from the active reassembly buffer list */
if (prev == NULL)
{
g_active_reass = reass->rb_flink;
}
else
{
prev->rb_flink = reass->rb_flink;
}
}
reass->rb_flink = NULL;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sixlowpan_reass_initialize
*
* Description:
* This function initializes the reassembly buffer allocator. This
* function must be called early in the initialization sequence before
* any radios begin operation.
*
* Called only once during network initialization.
*
* Inputs:
* None
*
* Return Value:
* None
*
****************************************************************************/
void sixlowpan_reass_initialize(void)
{
FAR struct sixlowpan_reassbuf_s *reass;
int i;
/* Initialize g_free_reass, the list of reassembly buffer structures that are
* available for allocation.
*/
g_free_reass = NULL;
for (i = 0, reass = g_metadata_pool;
i < CONFIG_NET_6LOWPAN_NREASSBUF;
i++, reass++)
{
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
reass->rb_flink = g_free_reass;
g_free_reass = reass;
}
}
/****************************************************************************
* Name: sixlowpan_reass_allocate
*
* Description:
* The sixlowpan_reass_allocate function will get a free reassembly buffer
* structure for use by 6LoWPAN.
*
* This function will first attempt to allocate from the g_free_reass
* list. If that the list is empty, then the reassembly buffer structure
* will be allocated from the dynamic memory pool.
*
* Inputs:
* reasstag - The reassembly tag for subsequent lookup.
* fragsrc - The source address of the fragment.
*
* Return Value:
* A reference to the allocated reass structure. All fields used by the
* reasembly logic have been zeroed. On a failure to allocate, NULL is
* returned.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
FAR struct sixlowpan_reassbuf_s *
sixlowpan_reass_allocate(uint16_t reasstag,
FAR const struct netdev_varaddr_s *fragsrc)
{
FAR struct sixlowpan_reassbuf_s *reass;
uint8_t pool;
/* First, removed any expired or inactive reassembly buffers. This might
* free up a pre-allocated buffer for this allocation.
*/
sixlowpan_reass_expire();
/* Now, try the free list first */
if (g_free_reass != NULL)
{
reass = g_free_reass;
g_free_reass = reass->rb_flink;
pool = REASS_POOL_PREALLOCATED;
}
else
{
#ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
reass = NULL;
#else
/* If we cannot get a reassembly buffer instance from the free list, then we
* will have to allocate one from the kernal memory pool.
*/
reass = (FAR struct sixlowpan_reassbuf_s *)
kmm_malloc((sizeof (struct sixlowpan_reassbuf_s)));
pool = REASS_POOL_DYNAMIC;
#endif
}
/* We have successfully allocated memory from some source? */
if (reass != NULL)
{
/* Zero and tag the allocated reassembly buffer structure. */
memset(reass, 0, sizeof(struct sixlowpan_reassbuf_s));
memcpy(&reass->rb_fragsrc, fragsrc, sizeof(struct netdev_varaddr_s));
reass->rb_pool = pool;
reass->rb_active = true;
reass->rb_reasstag = reasstag;
reass->rb_time = clock_systimer();
/* Add the reassembly buffer to the list of active reassembly buffers */
reass->rb_flink = g_active_reass;
g_active_reass = reass;
}
return reass;
}
/****************************************************************************
* Name: sixlowpan_reass_find
*
* Description:
* Find a previously allocated, active reassembly buffer with the specified
* reassembly tag.
*
* Inputs:
* reasstag - The reassembly tag to match.
* fragsrc - The source address of the fragment.
*
* Return Value:
* A reference to the matching reass structure.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
FAR struct sixlowpan_reassbuf_s *
sixlowpan_reass_find(uint16_t reasstag,
FAR const struct netdev_varaddr_s *fragsrc)
{
FAR struct sixlowpan_reassbuf_s *reass;
/* First, removed any expired or inactive reassembly buffers (we don't want
* to return old reassembly buffer with the same tag)
*/
sixlowpan_reass_expire();
/* Now search for the matching reassembly buffer in the remainng, active
* reassembly buffers.
*/
for (reass = g_active_reass; reass != NULL; reass = reass->rb_flink)
{
/* In order to be a match, it must have the same reassembly tag as
* well as source address (different sources might use the same
* reassembly tag).
*/
if (reass->rb_reasstag == reasstag &&
sixlowpan_compare_fragsrc(reass, fragsrc))
{
return reass;
}
}
/* Not found */
return NULL;
}
/****************************************************************************
* Name: sixlowpan_reass_free
*
* Description:
* The sixlowpan_reass_free function will return a reass structure
* to the free list of messages if it was a pre-allocated reass
* structure. If the reass structure was allocated dynamically it will
* be deallocated.
*
* Inputs:
* reass - reass structure to free
*
* Return Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
void sixlowpan_reass_free(FAR struct sixlowpan_reassbuf_s *reass)
{
/* First, remove the reassembly buffer from the list of active reassembly
* buffers.
*/
sixlowpan_remove_active(reass);
/* If this is a pre-allocated reassembly buffer structure, then just put it back
* in the free list.
*/
if (reass->rb_pool == REASS_POOL_PREALLOCATED)
{
reass->rb_flink = g_free_reass;
g_free_reass = reass;
}
else
{
#ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
DEBUGPANIC();
#else
DEBUGASSERT(reass->rb_pool == REASS_POOL_DYNAMIC);
/* Otherwise, deallocate it. */
sched_kfree(reass);
#endif
}
}
#endif /* CONFIG_NET_6LOWPAN_FRAG */

View File

@ -48,6 +48,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <debug.h> #include <debug.h>
#include <nuttx/net/netconfig.h> #include <nuttx/net/netconfig.h>
@ -342,9 +343,12 @@ found:
#endif #endif
/* We must free this TCP connection structure; this connection /* We must free this TCP connection structure; this connection
* will never be established. * will never be established. There should only be one reference
* on this connection when we allocated for the connection.
*/ */
DEBUGASSERT(conn->crefs == 1);
conn->crefs = 0;
tcp_free(conn); tcp_free(conn);
} }
else else

View File

@ -51,6 +51,7 @@
#include <nuttx/wdog.h> #include <nuttx/wdog.h>
#include <nuttx/wqueue.h> #include <nuttx/wqueue.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h> #include <nuttx/net/net.h>
#include <nuttx/net/ip.h> #include <nuttx/net/ip.h>
#include <nuttx/net/radiodev.h> #include <nuttx/net/radiodev.h>
@ -137,7 +138,7 @@ struct lo_driver_s
static struct lo_driver_s g_loopback; static struct lo_driver_s g_loopback;
#ifdef CONFIG_NET_6LOWPAN #ifdef CONFIG_NET_6LOWPAN
static uint8_t g_iobuffer[CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE]; static struct sixlowpan_reassbuf_s g_iobuffer;
#endif #endif
static uint8_t g_eaddr[IEEE802154_EADDRSIZE] = static uint8_t g_eaddr[IEEE802154_EADDRSIZE] =
@ -388,6 +389,12 @@ static int lo_loopback(FAR struct net_driver_s *dev)
#endif #endif
#ifdef CONFIG_NET_6LOWPAN #ifdef CONFIG_NET_6LOWPAN
{ {
/* Make sure the our single packet buffer is attached */
priv->lo_radio.r_dev.d_buf = g_iobuffer.rb_buf;
/* Then give the frame to 6LoWPAN */
ret = sixlowpan_input(&priv->lo_radio, iob, (FAR void *)&ind); ret = sixlowpan_input(&priv->lo_radio, iob, (FAR void *)&ind);
} }
#endif #endif
@ -459,6 +466,15 @@ static void lo_poll_work(FAR void *arg)
/* Perform the poll */ /* Perform the poll */
net_lock(); net_lock();
#ifdef CONFIG_NET_6LOWPAN
/* Make sure the our single packet buffer is attached */
priv->lo_radio.r_dev.d_buf = g_iobuffer.rb_buf;
#endif
/* Then perform the poll */
(void)devif_timer(&priv->lo_radio.r_dev, lo_loopback); (void)devif_timer(&priv->lo_radio.r_dev, lo_loopback);
/* Setup the watchdog poll timer again */ /* Setup the watchdog poll timer again */
@ -634,6 +650,12 @@ static void lo_txavail_work(FAR void *arg)
{ {
/* If so, then poll the network for new XMIT data */ /* If so, then poll the network for new XMIT data */
#ifdef CONFIG_NET_6LOWPAN
/* Make sure the our single packet buffer is attached */
priv->lo_radio.r_dev.d_buf = g_iobuffer.rb_buf;
#endif
(void)devif_poll(&priv->lo_radio.r_dev, lo_loopback); (void)devif_poll(&priv->lo_radio.r_dev, lo_loopback);
} }
@ -1063,9 +1085,6 @@ int ieee8021514_loopback(void)
#endif #endif
#ifdef CONFIG_NETDEV_IOCTL #ifdef CONFIG_NETDEV_IOCTL
dev->d_ioctl = lo_ioctl; /* Handle network IOCTL commands */ dev->d_ioctl = lo_ioctl; /* Handle network IOCTL commands */
#endif
#ifdef CONFIG_NET_6LOWPAN
dev->d_buf = g_iobuffer; /* Attach the IO buffer */
#endif #endif
dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */ dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */

View File

@ -224,6 +224,14 @@ static int macnet_req_data(FAR struct radio_driver_s *netdev,
static int macnet_properties(FAR struct radio_driver_s *netdev, static int macnet_properties(FAR struct radio_driver_s *netdev,
FAR struct radiodev_properties_s *properties); FAR struct radiodev_properties_s *properties);
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN
static struct sixlowpan_reassbuf_s g_iobuffer;
#endif
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -470,6 +478,12 @@ static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
} }
else else
{ {
/* Make sure the our single packet buffer is attached */
priv->md_dev.r_dev.d_buf = g_iobuffer.rb_buf;
/* And give the packet to 6LoWPAN */
ret = sixlowpan_input(&priv->md_dev, iob, (FAR void *)ind); ret = sixlowpan_input(&priv->md_dev, iob, (FAR void *)ind);
} }
} }
@ -568,7 +582,13 @@ static void macnet_txpoll_work(FAR void *arg)
net_lock(); net_lock();
/* Perform the poll */ #ifdef CONFIG_NET_6LOWPAN
/* Make sure the our single packet buffer is attached */
priv->md_dev.r_dev.d_buf = g_iobuffer.rb_buf;
#endif
/* Then perform the poll */
(void)devif_timer(&priv->md_dev.r_dev, macnet_txpoll_callback); (void)devif_timer(&priv->md_dev.r_dev, macnet_txpoll_callback);
@ -836,9 +856,13 @@ static void macnet_txavail_work(FAR void *arg)
if (priv->md_bifup) if (priv->md_bifup)
{ {
/* Check if there is room in the hardware to hold another outgoing packet. */ #ifdef CONFIG_NET_6LOWPAN
/* Make sure the our single packet buffer is attached */
/* If so, then poll the network for new XMIT data */ priv->md_dev.r_dev.d_buf = g_iobuffer.rb_buf;
#endif
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->md_dev.r_dev, macnet_txpoll_callback); (void)devif_poll(&priv->md_dev.r_dev, macnet_txpoll_callback);
} }
@ -1206,9 +1230,6 @@ int mac802154netdev_register(MACHANDLE mac)
FAR struct radio_driver_s *radio; FAR struct radio_driver_s *radio;
FAR struct net_driver_s *dev; FAR struct net_driver_s *dev;
FAR struct mac802154_maccb_s *maccb; FAR struct mac802154_maccb_s *maccb;
#ifdef CONFIG_NET_6LOWPAN
FAR uint8_t *pktbuf;
#endif
int ret; int ret;
DEBUGASSERT(mac != NULL); DEBUGASSERT(mac != NULL);
@ -1224,27 +1245,10 @@ int mac802154netdev_register(MACHANDLE mac)
return -ENOMEM; return -ENOMEM;
} }
#ifdef CONFIG_NET_6LOWPAN
/* Allocate a packet buffer (not used by this driver, but needed by the
* upper networking layer)
*/
pktbuf = (FAR uint8_t *)kmm_malloc(CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE);
if (pktbuf == NULL)
{
nerr("ERROR: Failed to allocate the packet buffer\n");
kmm_free(priv);
return -ENOMEM;
}
#endif
/* Initialize the driver structure */ /* Initialize the driver structure */
radio = &priv->md_dev; radio = &priv->md_dev;
dev = &radio->r_dev; dev = &radio->r_dev;
#ifdef CONFIG_NET_6LOWPAN
dev->d_buf = pktbuf; /* Single packet buffer */
#endif
dev->d_ifup = macnet_ifup; /* I/F up (new IP address) callback */ dev->d_ifup = macnet_ifup; /* I/F up (new IP address) callback */
dev->d_ifdown = macnet_ifdown; /* I/F down callback */ dev->d_ifdown = macnet_ifdown; /* I/F down callback */
dev->d_txavail = macnet_txavail; /* New TX data callback */ dev->d_txavail = macnet_txavail; /* New TX data callback */
@ -1297,9 +1301,6 @@ int mac802154netdev_register(MACHANDLE mac)
/* Free memory and return the error */ /* Free memory and return the error */
#ifdef CONFIG_NET_6LOWPAN
kmm_free(pktbuf);
#endif
kmm_free(priv); kmm_free(priv);
return ret; return ret;
} }

View File

@ -51,6 +51,7 @@
#include <nuttx/wdog.h> #include <nuttx/wdog.h>
#include <nuttx/wqueue.h> #include <nuttx/wqueue.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h> #include <nuttx/net/net.h>
#include <nuttx/net/ip.h> #include <nuttx/net/ip.h>
#include <nuttx/net/radiodev.h> #include <nuttx/net/radiodev.h>
@ -130,7 +131,9 @@ struct lo_driver_s
****************************************************************************/ ****************************************************************************/
static struct lo_driver_s g_loopback; static struct lo_driver_s g_loopback;
static uint8_t g_iobuffer[CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE]; #ifdef CONFIG_NET_6LOWPAN
static struct sixlowpan_reassbuf_s g_iobuffer;
#endif
static uint8_t g_mac_addr[CONFIG_PKTRADIO_ADDRLEN] = static uint8_t g_mac_addr[CONFIG_PKTRADIO_ADDRLEN] =
{ {
@ -346,6 +349,10 @@ static int lo_loopback(FAR struct net_driver_s *dev)
priv->lo_tail = NULL; priv->lo_tail = NULL;
} }
/* Make sure the our single packet buffer is attached */
priv->lo_radio.r_dev.d_buf = g_iobuffer.rb_buf;
/* Return the next frame to the network */ /* Return the next frame to the network */
ninfo("Send frame %p to the network: Offset=%u Length=%u\n", ninfo("Send frame %p to the network: Offset=%u Length=%u\n",
@ -420,6 +427,15 @@ static void lo_poll_work(FAR void *arg)
/* Perform the poll */ /* Perform the poll */
net_lock(); net_lock();
#ifdef CONFIG_NET_6LOWPAN
/* Make sure the our single packet buffer is attached */
priv->lo_radio.r_dev.d_buf = g_iobuffer.rb_buf;
#endif
/* And perform the poll */
(void)devif_timer(&priv->lo_radio.r_dev, lo_loopback); (void)devif_timer(&priv->lo_radio.r_dev, lo_loopback);
/* Setup the watchdog poll timer again */ /* Setup the watchdog poll timer again */
@ -576,6 +592,13 @@ static void lo_txavail_work(FAR void *arg)
if (priv->lo_bifup) if (priv->lo_bifup)
{ {
/* If so, then poll the network for new XMIT data */ /* If so, then poll the network for new XMIT data */
#ifdef CONFIG_NET_6LOWPAN
/* Make sure the our single packet buffer is attached */
priv->lo_radio.r_dev.d_buf = g_iobuffer.rb_buf;
#endif
/* Then perform the poll */
(void)devif_poll(&priv->lo_radio.r_dev, lo_loopback); (void)devif_poll(&priv->lo_radio.r_dev, lo_loopback);
} }
@ -1009,7 +1032,6 @@ int pktradio_loopback(void)
#ifdef CONFIG_NETDEV_IOCTL #ifdef CONFIG_NETDEV_IOCTL
dev->d_ioctl = lo_ioctl; /* Handle network IOCTL commands */ dev->d_ioctl = lo_ioctl; /* Handle network IOCTL commands */
#endif #endif
dev->d_buf = g_iobuffer; /* Attach the IO buffer */
dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */ dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */
/* Set the network mask and advertise our MAC-based IP address */ /* Set the network mask and advertise our MAC-based IP address */