Compare commits

...

23 commits

Author SHA1 Message Date
hujun5
d9a766582a use small lock in following files
arch/risc-v/src/litex/litex_emac.c
arch/risc-v/src/mpfs/mpfs_coremmc.c
arch/risc-v/src/mpfs/mpfs_usb.c
arch/xtensa/src/esp32/esp32_idle.c
arch/xtensa/src/esp32/esp32_rtc_lowerhalf.c
arch/xtensa/src/esp32s2/esp32s2_idle.c
arch/xtensa/src/esp32s2/esp32s2_lowputc.c
arch/xtensa/src/esp32s2/esp32s2_lowputc.h
arch/xtensa/src/esp32s2/esp32s2_rtc_lowerhalf.c
arch/xtensa/src/esp32s3/esp32s3_idle.c

Signed-off-by: hujun5 <hujun5@xiaomi.com>
2024-12-22 11:07:14 +08:00
wangmingrong1
e26e8bda0e gcov: gcov.py, gcov_convert.py scripts merged
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
2024-12-21 20:49:37 +08:00
wangmingrong1
7d6b2e4804 gcov/script: gcov.sh is implemented using Python
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
2024-12-21 20:49:37 +08:00
Tiago Medicci Serrano
7548db1980 arch/xtensa: Support __thread and thread_local keywords
Enable architecture-specific support for those keywords. This is a
"gcc-based" thread local storage implementation.
2024-12-21 20:49:07 +08:00
Masanari Iida
02828921db Documentation/guides: Fix typos in port_arm_cm4.rst
Some checks are pending
Build Documentation / build-html (push) Waiting to run
This patch fixes spelling typos in port_arm_cm4.rst
2024-12-20 23:09:40 -05:00
Kyle Wilson
e039fa039d Added comma to fix undefined bits struct member 2024-12-20 23:08:09 -05:00
yaojingwei
bbd6931d61 nuttx/audio: add fake audio driver.
The fake audio driver aims to easily simulate the functions of audio driver through reading and writing files.
With it, you can conveniently customize and define various capture or playback audio drivers for debugging or automated testing.

Signed-off-by: yaojingwei <yaojingwei@xiaomi.com>
2024-12-20 11:47:08 -03:00
guoshichao
a58d6552e6 fcntl: add sys/fcntl.h header file
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
1701ca1e11 sem: add sys/sem.h header file
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
0d4e36ce29 wait: add wait.h header file
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
0af01312fd sys/socket: add SOL_PACKET packet operation type definition
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
2badabfb67 signal: add include/sys/signal.h to the signal
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
8fcdae3544 sys/types.h: add loff_t data type definition
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
092f4a1b79 sys/mount: add mount flag definition
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
16789ed818 signal: add SA_NOMASK flag definition
according to linux kernel doc, "the SA_NOMASK is an obsolete,
nonstandard synonym for this SA_NODEFER" flag, and some ltp linux kernel
testcases need this flag, so we add this flag to make the testcases pass

Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
a8cdd63d56 proctl: add PR_SET_DUMPABLE support
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
203fb15c2e limits: add LINE_MAX limits definition
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
23e0b70290 sys/resource: add RLIMIT_NICE consntant
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
guoshichao
2b34c61c6e signal: add sa_restorer to struct sigaction
Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2024-12-20 11:46:14 -03:00
hujun5
67b95d0142 use small lock in following files
arch/arm/src/armv7-a/arm_gicv2.c
arch/arm/src/imx6/imx_serial.c
arch/arm/src/imxrt/imxrt_flexcan.c
arch/xtensa/src/esp32/esp32_himem.c
arch/xtensa/src/esp32s3/esp32s3_himem.c

Signed-off-by: hujun5 <hujun5@xiaomi.com>
2024-12-20 20:58:43 +08:00
wangjianyu3
0fe3aebd6a nuttx/uorb.h: Add carrier frequency for GNSS Satellite
The `struct sensor_gnss_satellite.cf` may be parsed from `GSV.signal_id`(e.g. NMEA 0183 v4.11) and `struct sensor_gnss_satellite.constellation`

Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2024-12-20 20:05:26 +08:00
Zhe Weng
035fdb4951 net: Refresh config dependency of NET_READAHEAD
ICMP(v6) uses IOB queue as readahead, but TCP/UDP don't now.

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
2024-12-20 20:01:19 +08:00
chao an
d36ddb5790 arm/modifyreg: Use common lock to protect the modify address to ensure consistency
Signed-off-by: chao an <anchao@lixiang.com>
2024-12-20 19:54:07 +08:00
59 changed files with 2102 additions and 421 deletions

View file

@ -85,7 +85,7 @@ And you can do distclean by following command.
Step4 : Compile
---------------
Try to buid with the implementation of Step1-2, you would face the error as following
Try to build with the implementation of Step1-2, you would face the error as following
if you implemented only directory / Kconfig / Make.defs / Makefile / defconfig about Step1-2.
.. code-block::
@ -178,7 +178,7 @@ Step6 : Implement
-----------------
There are some implementation items, major items are bellow listed. To pass the Linking,
try to implement these symboles.
try to implement these symbols.
+-----------------+------------------------+--------------------------------------------------------------------+
| Category | Item | Comment |
@ -201,7 +201,7 @@ try to implement these symboles.
.. _apache/nuttx/pull/12441: https://github.com/apache/nuttx/pull/12441
.. _sched/Kconfig: https://github.com/apache/nuttx/blob/master/sched/Kconfig
If got the pass of Linking, you would see follwoing result.
If got the pass of Linking, you would see following result.
.. code-block::
@ -216,7 +216,7 @@ If got the pass of Linking, you would see follwoing result.
Step7 : Verify
--------------
To execute and debug on the evalutaion board, add following configurations.
To execute and debug on the evaluation board, add following configurations.
.. code-block::
@ -232,7 +232,7 @@ If your implementations were good, you would see following logs.
nsh>
nsh>
After comfirming to boot NuttShell(NSH), try to execute "apps/testing/ostest".
After confirming to boot NuttShell(NSH), try to execute "apps/testing/ostest".
The "apps/testing/ostest" needs following configurations.
.. code-block::
@ -242,7 +242,7 @@ The "apps/testing/ostest" needs following configurations.
CONFIG_SCHED_WAITPID=y
CONFIG_TESTING_OSTEST=y
And one more test is recomended to check the timer implementation whether
And one more test is recommended to check the timer implementation whether
the kernel could count the time accurately or not.
I checked it by following code. About the function : cxd32_timerget(),
see `apache/nuttx/pull/12441`_
@ -406,7 +406,7 @@ Appendix : out-of-tree code
+ string "Program name"
+ default "time"
+ ---help---
+ This apps measures the elasped time of sleep system call to confirm the timer implementation.
+ This apps measures the elapsed time of sleep system call to confirm the timer implementation.
+
+config CXD32XX_APPS_TIME_PRIORITY
+ int "CXD32XX Time task priority"
@ -478,7 +478,7 @@ Appendix : out-of-tree code
+ uint32_t pre;
+ uint32_t post;
+
+ printf("measures the elasped time of sleep system call to confirm \
+ printf("measures the elapsed time of sleep system call to confirm \
+ the timer implementation.\n");
+
+ pre = cxd32_timerget();

View file

@ -158,6 +158,7 @@ config ARCH_XTENSA
select ARCH_HAVE_INTERRUPTSTACK
select ARCH_HAVE_STACKCHECK
select ARCH_HAVE_CUSTOMOPT
select ARCH_HAVE_THREAD_LOCAL
select ARCH_HAVE_TCBINFO
select ARCH_HAVE_STDARG_H
select ARCH_HAVE_SETJMP if ARCH_TOOLCHAIN_GNU

View file

@ -52,7 +52,7 @@
****************************************************************************/
#if defined(CONFIG_SMP) && CONFIG_SMP_NCPUS > 1
static volatile cpu_set_t g_gic_init_done;
static atomic_t g_gic_init_done;
#endif
/****************************************************************************
@ -72,11 +72,7 @@ static volatile cpu_set_t g_gic_init_done;
#if defined(CONFIG_SMP) && CONFIG_SMP_NCPUS > 1
static void arm_gic_init_done(void)
{
irqstate_t flags;
flags = spin_lock_irqsave(NULL);
CPU_SET(this_cpu(), &g_gic_init_done);
spin_unlock_irqrestore(NULL, flags);
atomic_fetch_or(&g_gic_init_done, 1 << this_cpu());
}
static void arm_gic_wait_done(cpu_set_t cpuset)
@ -85,7 +81,7 @@ static void arm_gic_wait_done(cpu_set_t cpuset)
do
{
CPU_AND(&tmpset, &g_gic_init_done, &cpuset);
tmpset = (cpu_set_t)atomic_read(&g_gic_init_done) & cpuset;
}
while (!CPU_EQUAL(&tmpset, &cpuset));
}

View file

@ -33,9 +33,7 @@ set(SRCS
arm_getintstack.c
arm_initialize.c
arm_lowputs.c
arm_modifyreg8.c
arm_modifyreg16.c
arm_modifyreg32.c
arm_modifyreg.c
arm_nputs.c
arm_releasestack.c
arm_registerdump.c

View file

@ -24,9 +24,8 @@
CMN_CSRCS += arm_allocateheap.c arm_createstack.c arm_exit.c
CMN_CSRCS += arm_getintstack.c arm_initialize.c arm_lowputs.c
CMN_CSRCS += arm_modifyreg8.c arm_modifyreg16.c arm_modifyreg32.c
CMN_CSRCS += arm_nputs.c arm_releasestack.c arm_registerdump.c
CMN_CSRCS += arm_stackframe.c
CMN_CSRCS += arm_stackframe.c arm_modifyreg.c
CMN_CSRCS += arm_usestack.c arm_fork.c
ifneq ($(CONFIG_ALARM_ARCH),y)

View file

@ -0,0 +1,107 @@
/****************************************************************************
* arch/arm/src/common/arm_modifyreg.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <debug.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_modifyreg_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: modifyreg8
*
* Description:
* Atomically modify the specified bits in a memory mapped register
*
****************************************************************************/
void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits)
{
irqstate_t flags;
uint8_t regval;
flags = spin_lock_irqsave(&g_modifyreg_lock);
regval = getreg8(addr);
regval &= ~clearbits;
regval |= setbits;
putreg8(regval, addr);
spin_unlock_irqrestore(&g_modifyreg_lock, flags);
}
/****************************************************************************
* Name: modifyreg16
*
* Description:
* Atomically modify the specified bits in a memory mapped register
*
****************************************************************************/
void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits)
{
irqstate_t flags;
uint16_t regval;
flags = spin_lock_irqsave(&g_modifyreg_lock);
regval = getreg16(addr);
regval &= ~clearbits;
regval |= setbits;
putreg16(regval, addr);
spin_unlock_irqrestore(&g_modifyreg_lock, flags);
}
/****************************************************************************
* Name: modifyreg32
*
* Description:
* Atomically modify the specified bits in a memory mapped register
*
****************************************************************************/
void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits)
{
irqstate_t flags;
uint32_t regval;
flags = spin_lock_irqsave(&g_modifyreg_lock);
regval = getreg32(addr);
regval &= ~clearbits;
regval |= setbits;
putreg32(regval, addr);
spin_unlock_irqrestore(&g_modifyreg_lock, flags);
}

View file

@ -196,6 +196,7 @@ struct imx_uart_s
uint32_t ucr1; /* Saved UCR1 value */
uint8_t irq; /* IRQ associated with this UART */
uint8_t parity; /* 0=none, 1=odd, 2=even */
spinlock_t lock; /* Spinlock */
uint8_t bits; /* Number of bits (7 or 8) */
uint8_t stopbits2:1; /* 1: Configure with 2 stop bits vs 1 */
#ifdef CONFIG_SERIAL_IFLOWCONTROL
@ -295,6 +296,7 @@ static struct imx_uart_s g_uart1priv =
.baud = CONFIG_UART1_BAUD,
.irq = IMX_IRQ_UART1,
.parity = CONFIG_UART1_PARITY,
.lock = SP_UNLOCKED,
.bits = CONFIG_UART1_BITS,
.stopbits2 = CONFIG_UART1_2STOP,
};
@ -325,6 +327,7 @@ static struct imx_uart_s g_uart2priv =
.baud = CONFIG_UART2_BAUD,
.irq = IMX_IRQ_UART2,
.parity = CONFIG_UART2_PARITY,
.lock = SP_UNLOCKED
.bits = CONFIG_UART2_BITS,
.stopbits2 = CONFIG_UART2_2STOP,
};
@ -353,6 +356,7 @@ static struct imx_uart_s g_uart3priv =
.baud = IMX_UART3_VBASE,
.irq = IMX_IRQ_UART3,
.parity = CONFIG_UART3_PARITY,
.lock = SP_UNLOCKED
.bits = CONFIG_UART3_BITS,
.stopbits2 = CONFIG_UART3_2STOP,
};
@ -381,6 +385,7 @@ static struct imx_uart_s g_uart4priv =
.baud = IMX_UART4_VBASE,
.irq = IMX_IRQ_UART4,
.parity = CONFIG_UART4_PARITY,
.lock = SP_UNLOCKED
.bits = CONFIG_UART4_BITS,
.stopbits2 = CONFIG_UART4_2STOP,
};
@ -409,6 +414,7 @@ static struct imx_uart_s g_uart5priv =
.baud = IMX_UART5_VBASE,
.irq = IMX_IRQ_UART5,
.parity = CONFIG_UART5_PARITY,
.lock = SP_UNLOCKED
.bits = CONFIG_UART5_BITS,
.stopbits2 = CONFIG_UART5_2STOP,
};
@ -877,7 +883,7 @@ static int imx_ioctl(struct file *filep, int cmd, unsigned long arg)
* implement TCSADRAIN / TCSAFLUSH
*/
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
imx_disableuartint(priv, &ie);
ret = imx_setup(dev);
@ -885,7 +891,7 @@ static int imx_ioctl(struct file *filep, int cmd, unsigned long arg)
imx_restoreuartint(priv, ie);
priv->ie = ie;
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
}
break;

View file

@ -267,6 +267,7 @@ struct imxrt_driver_s
bool bifup; /* true:ifup false:ifdown */
bool canfd_capable;
int mb_address_offset;
spinlock_t lock;
#ifdef TX_TIMEOUT_WQ
struct wdog_s txtimeout[TXMBCOUNT]; /* TX timeout timer */
#endif
@ -777,7 +778,7 @@ static int imxrt_txpoll(struct net_driver_s *dev)
* the field d_len is set to a value > 0.
*/
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
if (priv->dev.d_len > 0)
{
@ -793,12 +794,12 @@ static int imxrt_txpoll(struct net_driver_s *dev)
if (imxrt_txringfull(priv))
{
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
return -EBUSY;
}
}
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* If zero is returned, the polling will continue until all connections
* have been examined.
@ -2032,6 +2033,7 @@ int imxrt_caninitialize(int intf)
priv->dev.d_ioctl = imxrt_ioctl; /* Support CAN ioctl() calls */
#endif
priv->dev.d_private = (void *)priv; /* Used to recover private state from dev */
spin_lock_init(&priv->lock);
/* Put the interface in the down state. This usually amounts to resetting
* the device and/or calling imxrt_ifdown().

View file

@ -169,6 +169,7 @@ struct litex_emac_s
uint8_t phyaddr; /* PHY address (pre-defined by pins on reset) */
uint8_t txslot;
spinlock_t lock;
};
/****************************************************************************
@ -511,7 +512,7 @@ static int litex_transmit(struct litex_emac_s *priv)
/* Make the following operations atomic */
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
/* Now start transmission */
@ -528,7 +529,7 @@ static int litex_transmit(struct litex_emac_s *priv)
wd_start(&priv->txtimeout, LITEX_TXTIMEOUT,
litex_txtimeout_expiry, (wdparm_t)priv);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@ -1524,6 +1525,8 @@ static void litex_ethinitialize(void)
return;
}
spin_lock_init(&priv->lock);
nerr("ERROR: netdev_register() failed: %d\n", ret);
}

View file

@ -214,6 +214,8 @@ static void mpfs_callback(void *arg);
* Private Data
****************************************************************************/
static spinlock_t g_mpfs_modifyreg_lock = SP_UNLOCKED;
struct mpfs_dev_s g_coremmc_dev =
{
.dev =
@ -282,12 +284,12 @@ static void mpfs_modifyreg8(uintptr_t addr, uint8_t clearbits,
irqstate_t flags;
uint8_t regval;
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&g_mpfs_modifyreg_lock);
regval = getreg8(addr);
regval &= ~clearbits;
regval |= setbits;
putreg8(regval, addr);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&g_mpfs_modifyreg_lock, flags);
}
/****************************************************************************

View file

@ -224,6 +224,8 @@ static void mpfs_epset_reset(struct mpfs_usbdev_s *priv, uint16_t epset);
* Private Data
****************************************************************************/
static spinlock_t g_mpfs_modifyreg_lock = SP_UNLOCKED;
static struct mpfs_usbdev_s g_usbd;
static uint8_t g_clkrefs;
@ -297,12 +299,12 @@ static void mpfs_modifyreg16(uintptr_t addr, uint16_t clearbits,
DEBUGASSERT((addr >= MPFS_USB_BASE) && addr < (MPFS_USB_BASE +
MPFS_USB_REG_MAX));
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&g_mpfs_modifyreg_lock);
regval = getreg16(addr);
regval &= ~clearbits;
regval |= setbits;
putreg16(regval, addr);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&g_mpfs_modifyreg_lock, flags);
}
/****************************************************************************
@ -331,12 +333,12 @@ static void mpfs_modifyreg8(uintptr_t addr, uint8_t clearbits,
DEBUGASSERT((addr >= MPFS_USB_BASE) && addr < (MPFS_USB_BASE +
MPFS_USB_REG_MAX));
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&g_mpfs_modifyreg_lock);
regval = getreg8(addr);
regval &= ~clearbits;
regval |= setbits;
putreg8(regval, addr);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&g_mpfs_modifyreg_lock, flags);
}
/****************************************************************************

View file

@ -26,6 +26,7 @@
#include <nuttx/arch.h>
#include <nuttx/audio/audio.h>
#include <nuttx/audio/audio_fake.h>
#include <nuttx/kthread.h>
#include <nuttx/motor/foc/foc_dummy.h>
#include <nuttx/mtd/mtd.h>
@ -298,6 +299,12 @@ void up_initialize(void)
audio_register("mixer", sim_audio_initialize(false, false));
#ifdef CONFIG_AUDIO_FAKE
/* Register fake audio driver */
audio_fake_initialize();
#endif
#endif
#ifdef CONFIG_SIM_USB_DEV

View file

@ -94,8 +94,9 @@
#define REG_SAR (18)
#define REG_EXCCAUSE (19)
#define REG_EXCVADDR (20)
#define REG_THREADPTR (21)
#define _REG_EXTRA_START (21)
#define _REG_EXTRA_START (22)
#if XCHAL_HAVE_S32C1I != 0
# define REG_SCOMPARE1 (_REG_EXTRA_START + 0)

View file

@ -128,13 +128,14 @@
/* Tensilica-defined user registers: */
#define THREADPTR 231 /* threadptr option */
#if 0
#if 0
#define ... 21..24 /* (545CK) */
#define ... 140..143 /* (545CK) */
#endif
#define EXPSTATE 230 /* Diamond */
#define THREADPTR 231 /* threadptr option */
#define FCR 232 /* FPU */
#define FSR 233 /* FPU */
#define AE_OVF_SAR 240 /* HiFi2 */

View file

@ -54,6 +54,10 @@ ifeq ($(CONFIG_SCHED_BACKTRACE),y)
CMN_CSRCS += xtensa_backtrace.c
endif
ifeq ($(CONFIG_SCHED_THREAD_LOCAL),y)
CMN_CSRCS += xtensa_tls.c
endif
ifeq ($(CONFIG_SMP),y)
CMN_CSRCS += xtensa_smpcall.c
endif

View file

@ -144,6 +144,18 @@
#define INTSTACK_COLOR 0xdeadbeef
#define HEAP_COLOR 'h'
#define _START_TEXT _stext
#define _END_TEXT _etext
#define _START_BSS _sbss
#define _END_BSS _ebss
#define _DATA_INIT _eronly
#define _START_DATA _sdata
#define _END_DATA _edata
#define _START_TDATA _stdata
#define _END_TDATA _etdata
#define _START_TBSS _stbss
#define _END_TBSS _etbss
/****************************************************************************
* Public Types
****************************************************************************/
@ -177,6 +189,10 @@ extern uint8_t _sbss[]; /* Start of .bss */
extern uint8_t _ebss[]; /* End+1 of .bss */
extern uint8_t _sheap[]; /* Start of heap */
extern uint8_t _eheap[]; /* End+1 of heap */
extern uint8_t _stdata[]; /* Start of .tdata */
extern uint8_t _etdata[]; /* End+1 of .tdata */
extern uint8_t _stbss[]; /* Start of .tbss */
extern uint8_t _etbss[]; /* End+1 of .tbss */
extern uint8_t _sbss_extmem[]; /* start of external memory bss */
extern uint8_t _ebss_extmem[]; /* End+1 of external memory bss */

View file

@ -131,6 +131,9 @@ _xtensa_context_save:
s32i a15, sp, (4 * REG_A15)
#endif
rur a3, THREADPTR
s32i a3, sp, (4 * REG_THREADPTR)
rsr a3, SAR
s32i a3, sp, (4 * REG_SAR)
@ -276,6 +279,9 @@ _xtensa_context_restore:
wsr a3, SCOMPARE1
#endif
l32i a3, a2, (4 * REG_THREADPTR)
wur a3, THREADPTR
l32i a3, a2, (4 * REG_SAR)
wsr a3, SAR

View file

@ -31,6 +31,7 @@
#include <string.h>
#include <nuttx/arch.h>
#include <nuttx/nuttx.h>
#include <arch/irq.h>
#include <arch/xtensa/core.h>
#include <arch/chip/core-isa.h>
@ -39,6 +40,23 @@
#include "xtensa.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_SCHED_THREAD_LOCAL
# define TCB_SIZE 8
#endif
/****************************************************************************
* Public Data
****************************************************************************/
extern int _thread_local_start;
extern int _thread_local_end;
extern int _rodata_reserved_start;
extern int _rodata_reserved_align;
/****************************************************************************
* Public Functions
****************************************************************************/
@ -59,6 +77,10 @@
void up_initial_state(struct tcb_s *tcb)
{
struct xcptcontext *xcp = &tcb->xcp;
#ifdef CONFIG_SCHED_THREAD_LOCAL
const uint32_t base = ALIGN_UP((uint32_t)&_rodata_reserved_align,
TCB_SIZE);
#endif
/* Initialize the initial exception register context structure */
@ -100,6 +122,116 @@ void up_initial_state(struct tcb_s *tcb)
xcp->regs[REG_A1] = (uint32_t)tcb->stack_base_ptr + /* Physical top of stack frame */
tcb->adj_stack_size;
/* Each task access the TLS variables using the THREADPTR register plus an
* offset to obtain the address of the variable.
*
* TLS layout at link-time (on flash), where 0xNNN is the offset that the
* linker calculates to a particular TLS variable:
*
* LOW ADDRESS
* |---------------------------| Linker Symbols
* | Section | --------------
* | .flash.rodata |
* 0x0|---------------------------| <- _rodata_reserved_start
* ^ | Other Data |
* | |---------------------------| <- _thread_local_start
* | | .tdata | ^ ^
* | | | | |
* | | | | Offset from |
* | | | | TLS start |
* | | | | | tls_area_size
* V | | V |
* 0xNNN | int example; | |
* | | |
* | | |
* | .tbss | V
* |---------------------------| <- _thread_local_end
* | Other data |
* | ... |
* |---------------------------|
* HIGH ADDRESS
*
* Consider the TLS variable `example`. Its location is calculated as:
*
* &example = &_rodata_reserved_start + 0xNNN
*
* And the offset 0xNNN can be calculated as:
*
* 0xNNN = (&_thread_local_start - &_rodata_reserved_start) +
* Offset from TLS start
*
* Consider the following diagram for the stack layout:
*
* Note: the following diagram shows the stack layout for a particular task
* and the memory grows towards the stack base (lower memory addresses).
*
* HIGH ADDRESS
* |---------------------------| <- Top of the stack
* | |
* | |
* |---------------------------| <- Base of the stack
* | .tbss (*) |
* | |
* | |
* | int example; |
* ^ | | ^
* | | | | Offset from TLS start
* | | .tdata (*) | V
* | |---------------------------| <- Start of the TLS area
* 0xNNN | | | ^
* | | | |
* | | ... | | (_thread_local_start -
* | | | | _rodata_reserved_start)
* | | | | + align_up(TCB_SIZE,
* | | | | tls_section_align)
* | | | |
* | | | V
* V | | <- threadptr register's value
*
* LOW ADDRESS
*
* At run-time, each task accesses the TLS variables using the THREADPTR
* register plus an offset to obtain the address of the variable.
*
* &example = THREADPTR + 0xNNN (calculated at link-time)
*
* Similarly, example can be accessed as:
*
* &example = Start of the TLS area + Offset from TLS start
*
* The start of the TLS area is given by (check xtensa_tls.c):
*
* Start of the TLS area = tcb->stack_alloc_ptr +
* sizeof(struct tls_info_s)
*
* Calculate the THREADPTR register's initialization value based on the
* link-time offset and the TLS area allocated on the stack.
*
* THREADPTR = &example - 0xNNN
* THREADPTR = (tcb->stack_alloc_ptr + sizeof(struct tls_info_s)) +
* Offset from TLS start - 0xNNN
*
* And, finally, based on 0xNNN calculated at link-time:
*
* THREADPTR = (tcb->stack_alloc_ptr + sizeof(struct tls_info_s)) -
* (&_thread_local_start - &_rodata_reserved_start) - base
*
* Note: Xtensa is slightly different compared to the RISC-V port as there
* is an implicit aligned TCB_SIZE added to the offset.
* - "offset = address - tls_section_vma +
* align_up(TCB_SIZE, tls_section_align)"
* - TCB_SIZE is hardcoded to 8
* Refer to https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=bfd/
* elf32-xtensa.c;h=f078cbde7146675fd2ed82eb5102ae2596c20775;hb=HEAD#l1830
*/
#ifdef CONFIG_SCHED_THREAD_LOCAL
xcp->regs[REG_THREADPTR] = (uintptr_t)tcb->stack_alloc_ptr +
sizeof(struct tls_info_s) -
((uint32_t)&_thread_local_start -
(uint32_t)&_rodata_reserved_start) - base;
#endif
/* Set initial PS to int level 0, user mode. */
#ifdef __XTENSA_CALL0_ABI__

View file

@ -79,6 +79,8 @@ int up_saveusercontext(void *saveregs)
" s32i a14, %0, (4 * " STRINGIFY(REG_A14) ")\n"
" s32i a15, %0, (4 * " STRINGIFY(REG_A15) ")\n"
#endif
" rur a2, THREADPTR\n"
" s32i a2, %0, (4 * " STRINGIFY(THREADPTR) ")\n"
" rsr a2, SAR\n"
" s32i a2, %0, (4 * " STRINGIFY(REG_SAR) ")\n"
#if XCHAL_HAVE_S32C1I != 0

View file

@ -0,0 +1,74 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_tls.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/tls.h>
#include "xtensa.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_tls_size
*
* Description:
* Get TLS (sizeof(struct tls_info_s) + tdata + tbss) section size.
*
* Returned Value:
* Size of (sizeof(struct tls_info_s) + tdata + tbss).
*
****************************************************************************/
int up_tls_size(void)
{
size_t size_tls_info_s = sizeof(struct tls_info_s);
size_t size_tsec = (_END_TBSS - _START_TDATA);
return size_tls_info_s + size_tsec;
}
/****************************************************************************
* Name: up_tls_initialize
*
* Description:
* Initialize thread local region.
*
* Input Parameters:
* info - The TLS structure to initialize.
*
****************************************************************************/
void up_tls_initialize(struct tls_info_s *info)
{
uint8_t *tls_data = (uint8_t *)(info + 1);
uint32_t tdata_len = (_END_TDATA - _START_TDATA);
uint32_t tbss_len = (_END_TBSS - _START_TBSS);
memcpy(tls_data, _START_TDATA, tdata_len);
memset(tls_data + tdata_len, 0, tbss_len);
}

View file

@ -126,6 +126,7 @@ typedef struct
unsigned int ram_block: 16;
} rangeblock_t;
static spinlock_t g_descriptor_lock = SP_UNLOCKED;
static ramblock_t *g_ram_descriptor = NULL;
static rangeblock_t *g_range_descriptor = NULL;
static int g_ramblockcnt = 0;
@ -325,11 +326,11 @@ int esp_himem_alloc(size_t size, esp_himem_handle_t *handle_out)
goto nomem;
}
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
ok = allocate_blocks(blocks, r->block);
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
if (!ok)
{
goto nomem;
@ -365,13 +366,13 @@ int esp_himem_free(esp_himem_handle_t handle)
/* Mark blocks as free */
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < handle->block_ct; i++)
{
g_ram_descriptor[handle->block[i]].is_alloced = false;
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
/* Free handle */
@ -407,7 +408,7 @@ int esp_himem_alloc_map_range(size_t size,
r->block_start = -1;
start_free = 0;
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < g_rangeblockcnt; i++)
{
@ -431,10 +432,11 @@ int esp_himem_alloc_map_range(size_t size,
if (r->block_start == -1)
{
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
/* Couldn't find enough free blocks */
kmm_free(r);
spin_unlock_irqrestore(NULL, spinlock_flags);
return -ENOMEM;
}
@ -445,7 +447,7 @@ int esp_himem_alloc_map_range(size_t size,
g_range_descriptor[r->block_start + i].is_alloced = 1;
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
/* All done. */
@ -474,14 +476,14 @@ int esp_himem_free_map_range(esp_himem_rangehandle_t handle)
/* We should be good to free this. Mark blocks as free. */
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < handle->block_ct; i++)
{
g_range_descriptor[i + handle->block_start].is_alloced = 0;
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
kmm_free(handle);
return OK;
}
@ -537,7 +539,7 @@ int esp_himem_map(esp_himem_handle_t handle,
/* Map and mark as mapped */
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < blockcount; i++)
{
@ -548,7 +550,7 @@ int esp_himem_map(esp_himem_handle_t handle,
handle->block[i + ram_block];
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
for (i = 0; i < blockcount; i++)
{
@ -589,7 +591,7 @@ int esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr,
HIMEM_CHECK(range_block + blockcount > range->block_ct,
"range out of bounds for handle", -EINVAL);
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < blockcount; i++)
{
@ -602,7 +604,7 @@ int esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr,
}
esp_spiram_writeback_cache();
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
return OK;
}

View file

@ -89,6 +89,13 @@
#define EXPECTED_IDLE_TIME_US (800)
#define EARLY_WAKEUP_US (200)
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_PM
static spinlock_t g_esp32_idle_lock = SP_UNLOCKED;
#endif
/****************************************************************************
@ -109,7 +116,7 @@ static void esp32_idlepm(void)
irqstate_t flags;
#ifdef CONFIG_ESP32_AUTO_SLEEP
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&g_esp32_idle_lock);
if (esp32_pm_lockstatus() == 0)
{
uint64_t os_start_us;
@ -155,7 +162,7 @@ static void esp32_idlepm(void)
}
}
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&g_esp32_idle_lock, flags);
#else /* CONFIG_ESP32_AUTO_SLEEP */
static enum pm_state_e oldstate = PM_NORMAL;
enum pm_state_e newstate;
@ -169,7 +176,7 @@ static void esp32_idlepm(void)
if (newstate != oldstate)
{
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&g_esp32_idle_lock);
/* Perform board-specific, state-dependent logic here */
@ -191,7 +198,7 @@ static void esp32_idlepm(void)
oldstate = newstate;
}
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&g_esp32_idle_lock, flags);
/* MCU-specific power management logic */

View file

@ -61,6 +61,7 @@ struct esp32_lowerhalf_s
*/
const struct rtc_ops_s *ops;
spinlock_t lock;
#ifdef CONFIG_RTC_ALARM
/* Alarm callback information */
@ -116,6 +117,7 @@ static const struct rtc_ops_s g_rtc_ops =
static struct esp32_lowerhalf_s g_rtc_lowerhalf =
{
.ops = &g_rtc_ops,
.lock = SP_UNLOCKED
};
/****************************************************************************
@ -376,6 +378,7 @@ static int rtc_lh_setalarm(struct rtc_lowerhalf_s *lower,
static int rtc_lh_setrelative(struct rtc_lowerhalf_s *lower,
const struct lower_setrelative_s *alarminfo)
{
struct esp32_lowerhalf_s *priv = (struct esp32_lowerhalf_s *)lower;
struct lower_setalarm_s setalarm;
time_t seconds;
int ret = -EINVAL;
@ -387,7 +390,7 @@ static int rtc_lh_setrelative(struct rtc_lowerhalf_s *lower,
if (alarminfo->reltime > 0)
{
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
seconds = alarminfo->reltime;
gmtime_r(&seconds, (struct tm *)&setalarm.time);
@ -399,7 +402,7 @@ static int rtc_lh_setrelative(struct rtc_lowerhalf_s *lower,
setalarm.priv = alarminfo->priv;
ret = rtc_lh_setalarm(lower, &setalarm);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
return ret;
@ -466,6 +469,7 @@ static int rtc_lh_cancelalarm(struct rtc_lowerhalf_s *lower, int alarmid)
static int rtc_lh_rdalarm(struct rtc_lowerhalf_s *lower,
struct lower_rdalarm_s *alarminfo)
{
struct esp32_lowerhalf_s *priv = (struct esp32_lowerhalf_s *)lower;
struct timespec ts;
int ret;
irqstate_t flags;
@ -474,13 +478,13 @@ static int rtc_lh_rdalarm(struct rtc_lowerhalf_s *lower,
DEBUGASSERT((RTC_ALARM0 <= alarminfo->id) &&
(alarminfo->id < RTC_ALARM_LAST));
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
ret = up_rtc_rdalarm(&ts, alarminfo->id);
localtime_r((const time_t *)&ts.tv_sec,
(struct tm *)alarminfo->time);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}

View file

@ -58,6 +58,14 @@
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_PM
static spinlock_t g_esp32s2_idle_lock = SP_UNLOCKED;
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
@ -86,7 +94,7 @@ static void up_idlepm(void)
if (newstate != oldstate)
{
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&g_esp32s2_idle_lock);
/* Perform board-specific, state-dependent logic here */
@ -108,7 +116,7 @@ static void up_idlepm(void)
oldstate = newstate;
}
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&g_esp32s2_idle_lock, flags);
/* MCU-specific power management logic */

View file

@ -99,6 +99,7 @@ struct esp32s2_uart_s g_uart0_config =
.rs485_dir_polarity = true,
#endif
#endif
.lock = SP_UNLOCKED;
};
#endif /* CONFIG_ESP32S2_UART0 */
@ -146,6 +147,7 @@ struct esp32s2_uart_s g_uart1_config =
.rs485_dir_polarity = true,
#endif
#endif
.lock = SP_UNLOCKED;
};
#endif /* CONFIG_ESP32S2_UART1 */
@ -654,7 +656,7 @@ void esp32s2_lowputc_disable_all_uart_int(const struct esp32s2_uart_s *priv,
{
irqstate_t flags;
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
if (current_status != NULL)
{
@ -671,7 +673,7 @@ void esp32s2_lowputc_disable_all_uart_int(const struct esp32s2_uart_s *priv,
putreg32(UINT32_MAX, UART_INT_CLR_REG(priv->id));
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************

View file

@ -106,6 +106,7 @@ struct esp32s2_uart_s
uint8_t rs485_dir_gpio; /* UART RS-485 DIR GPIO pin cfg */
bool rs485_dir_polarity; /* UART RS-485 DIR TXEN polarity */
#endif
spinlock_t lock; /* Spinlock */
};
extern struct esp32s2_uart_s g_uart0_config;

View file

@ -61,6 +61,7 @@ struct esp32s2_lowerhalf_s
*/
const struct rtc_ops_s *ops;
spinlock_t lock;
#ifdef CONFIG_RTC_ALARM
/* Alarm callback information */
@ -115,6 +116,7 @@ static const struct rtc_ops_s g_rtc_ops =
static struct esp32s2_lowerhalf_s g_rtc_lowerhalf =
{
.ops = &g_rtc_ops,
.lock = SP_UNLOCKED,
};
/****************************************************************************
@ -375,6 +377,7 @@ static int rtc_lh_setalarm(struct rtc_lowerhalf_s *lower,
static int rtc_lh_setrelative(struct rtc_lowerhalf_s *lower,
const struct lower_setrelative_s *alarminfo)
{
struct esp32s2_lowerhalf_s *priv = (struct esp32s2_lowerhalf_s *)lower;
struct lower_setalarm_s setalarm;
time_t seconds;
int ret = -EINVAL;
@ -386,7 +389,7 @@ static int rtc_lh_setrelative(struct rtc_lowerhalf_s *lower,
if (alarminfo->reltime > 0)
{
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
seconds = alarminfo->reltime;
gmtime_r(&seconds, (struct tm *)&setalarm.time);
@ -398,7 +401,7 @@ static int rtc_lh_setrelative(struct rtc_lowerhalf_s *lower,
setalarm.priv = alarminfo->priv;
ret = rtc_lh_setalarm(lower, &setalarm);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
return ret;
@ -465,6 +468,7 @@ static int rtc_lh_cancelalarm(struct rtc_lowerhalf_s *lower, int alarmid)
static int rtc_lh_rdalarm(struct rtc_lowerhalf_s *lower,
struct lower_rdalarm_s *alarminfo)
{
struct esp32s2_lowerhalf_s *priv = (struct esp32s2_lowerhalf_s *)lower;
struct timespec ts;
int ret;
irqstate_t flags;
@ -473,13 +477,13 @@ static int rtc_lh_rdalarm(struct rtc_lowerhalf_s *lower,
DEBUGASSERT((RTC_ALARM0 <= alarminfo->id) &&
(alarminfo->id < RTC_ALARM_LAST));
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&priv->lock);
ret = up_rtc_rdalarm(&ts, alarminfo->id);
localtime_r((const time_t *)&ts.tv_sec,
(struct tm *)alarminfo->time);
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}

View file

@ -148,6 +148,7 @@ static int himem_ioctl(struct file *filep, int cmd,
* Private Data
****************************************************************************/
static spinlock_t g_descriptor_lock = SP_UNLOCKED;
static ramblock_t *g_ram_descriptor = NULL;
static rangeblock_t *g_range_descriptor = NULL;
static int g_ramblockcnt = 0;
@ -626,11 +627,11 @@ int esp_himem_alloc(size_t size, esp_himem_handle_t *handle_out)
goto nomem;
}
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
ok = allocate_blocks(blocks, r->block);
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
if (!ok)
{
goto nomem;
@ -682,13 +683,13 @@ int esp_himem_free(esp_himem_handle_t handle)
/* Mark blocks as free */
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < handle->block_ct; i++)
{
g_ram_descriptor[handle->block[i]].is_alloced = false;
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
/* Free handle */
@ -742,7 +743,7 @@ int esp_himem_alloc_map_range(size_t size, esp_himem_rangehandle_t
r->block_start = -1;
start_free = 0;
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < g_rangeblockcnt; i++)
{
@ -766,10 +767,11 @@ int esp_himem_alloc_map_range(size_t size, esp_himem_rangehandle_t
if (r->block_start == -1)
{
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
/* Couldn't find enough free blocks */
kmm_free(r);
spin_unlock_irqrestore(NULL, spinlock_flags);
return -ENOMEM;
}
@ -780,7 +782,7 @@ int esp_himem_alloc_map_range(size_t size, esp_himem_rangehandle_t
g_range_descriptor[r->block_start + i].is_alloced = 1;
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
/* All done. */
@ -826,14 +828,14 @@ int esp_himem_free_map_range(esp_himem_rangehandle_t handle)
/* We should be good to free this. Mark blocks as free. */
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < handle->block_ct; i++)
{
g_range_descriptor[i + handle->block_start].is_alloced = 0;
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
kmm_free(handle);
return OK;
}
@ -917,7 +919,7 @@ int esp_himem_map(esp_himem_handle_t handle,
/* Map and mark as mapped */
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < blockcount; i++)
{
@ -928,7 +930,7 @@ int esp_himem_map(esp_himem_handle_t handle,
handle->block[i + ram_block];
}
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
for (i = 0; i < blockcount; i++)
{
virt_bank = himem_mmu_start + range->block_start + i + range_block;
@ -983,7 +985,7 @@ int esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr, size_t len)
HIMEM_CHECK(range_block + blockcount > range->block_ct,
"range out of bounds for handle", -EINVAL);
spinlock_flags = spin_lock_irqsave(NULL);
spinlock_flags = spin_lock_irqsave(&g_descriptor_lock);
for (i = 0; i < blockcount; i++)
{
@ -996,7 +998,7 @@ int esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr, size_t len)
}
esp_spiram_writeback_cache();
spin_unlock_irqrestore(NULL, spinlock_flags);
spin_unlock_irqrestore(&g_descriptor_lock, spinlock_flags);
return OK;
}

View file

@ -63,6 +63,14 @@
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_PM
static spinlock_t g_esp32s3_idle_lock = SP_UNLOCKED;
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
@ -91,7 +99,7 @@ static void up_idlepm(void)
if (newstate != oldstate)
{
flags = spin_lock_irqsave(NULL);
flags = spin_lock_irqsave(&g_esp32s3_idle_lock);
/* Perform board-specific, state-dependent logic here */
@ -113,7 +121,7 @@ static void up_idlepm(void)
oldstate = newstate;
}
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&g_esp32s3_idle_lock, flags);
/* MCU-specific power management logic */

View file

@ -403,6 +403,7 @@ SECTIONS
.flash.rodata :
{
_rodata_reserved_start = ABSOLUTE(.);
. = ALIGN(4);
_srodata = ABSOLUTE(.);
*(EXCLUDE_FILE (*libarch.a:esp32_spiflash.* *libarch.a:esp32_spicache.*
@ -469,8 +470,24 @@ SECTIONS
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
/* TLS data. */
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
_stdata = ABSOLUTE(.);
*(.tdata .tdata.* .gnu.linkonce.td.*);
_etdata = ABSOLUTE(.);
_stbss = ABSOLUTE(.);
*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
_etbss = ABSOLUTE(.);
_thread_local_end = ABSOLUTE(.);
_rodata_reserved_end = ABSOLUTE(.);
} >default_rodata_seg AT>ROM
_rodata_reserved_align = ALIGNOF(.flash.rodata);
_image_irom_vma = ADDR(.flash.text);
_image_irom_lma = LOADADDR(.flash.text);

View file

@ -38,6 +38,7 @@ CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_THREAD_LOCAL=y
CONFIG_SCHED_WAITPID=y
CONFIG_SPI=y
CONFIG_START_DAY=6

View file

@ -315,6 +315,8 @@ SECTIONS
.flash.rodata :
{
_rodata_reserved_start = ABSOLUTE(.);
_srodata = ABSOLUTE(.);
*(EXCLUDE_FILE (esp32s2_start.*) .rodata)
*(EXCLUDE_FILE (esp32s2_start.*) .rodata.*)
@ -374,8 +376,23 @@ SECTIONS
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
/* TLS data. */
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
_stdata = ABSOLUTE(.);
*(.tdata .tdata.* .gnu.linkonce.td.*);
_etdata = ABSOLUTE(.);
_stbss = ABSOLUTE(.);
*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
_etbss = ABSOLUTE(.);
_thread_local_end = ABSOLUTE(.);
_rodata_reserved_end = ABSOLUTE(.);
} >default_rodata_seg AT>ROM
_rodata_reserved_align = ALIGNOF(.flash.rodata);
_image_irom_vma = ADDR(.flash.text);
_image_irom_lma = LOADADDR(.flash.text);

View file

@ -37,6 +37,7 @@ CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_THREAD_LOCAL=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12

View file

@ -523,9 +523,24 @@ SECTIONS
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
/* TLS data. */
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
_stdata = ABSOLUTE(.);
*(.tdata .tdata.* .gnu.linkonce.td.*);
_etdata = ABSOLUTE(.);
_stbss = ABSOLUTE(.);
*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
_etbss = ABSOLUTE(.);
_thread_local_end = ABSOLUTE(.);
_rodata_reserved_end = ABSOLUTE(.);
} >drom0_0_seg AT>ROM
_rodata_reserved_align = ALIGNOF(.flash.rodata);
_image_irom_vma = ADDR(.flash.text);
_image_irom_lma = LOADADDR(.flash.text);

View file

@ -40,6 +40,7 @@ CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_THREAD_LOCAL=y
CONFIG_SCHED_WAITPID=y
CONFIG_SMP=y
CONFIG_SMP_NCPUS=2

View file

@ -69,6 +69,7 @@ set(DEQUOTELIST
"CONFIG_TTY_LAUNCH_ENTRYPOINT" # Name of entry point from tty launch
"CONFIG_TTY_LAUNCH_ARGS" # Argument list of entry point from tty launch
"CONFIG_BOARD_MEMORY_RANGE" # Memory range for board
"CONFIG_FAKE_AUDIO_DEVICE_PARAMS" # Arguments for the fake audio device
# NxWidgets/NxWM
"CONFIG_NXWM_BACKGROUND_IMAGE" # Name of bitmap image class
"CONFIG_NXWM_CALIBRATION_ICON" # Name of bitmap image class

View file

@ -518,4 +518,52 @@ config AUDIO_DMA
depends on AUDIO
depends on DMA
config AUDIO_FAKE
bool "Fake audio device"
default n
depends on AUDIO
---help---
A fake audio device driver to simplify testing of audio
capture and playback.
if AUDIO_FAKE
config FAKE_AUDIO_DEVICE_PARAMS
string "fake audio device params"
default ""
---help---
This is a params for fake audio device. The format like:
{dev_name, playback, sample_rates[4], channels, format[4], period_time, periods}.
- dev_name (string): pcm2c or pcm2p or others.
- playback (bool): true or false.
- sample_rates(uint32 array): {16000, 32000}.
- channels (uint8, {min_chan, max_chan}): {1, 2}.
- format(uint8 array): {8,16,32}.
- period_time(uint32): 100, unit ms.
- periods (uint32): 4, buffer cnt.
e.g:
{"pcm2c", false, {8000, 16000, 44100}, {1, 2}, {16}, 100, 4},
{"pcm2p", true, {8000, 16000, 44100}, {1, 2}, {16}, 100, 4},
config FAKE_AUDIO_DATA_PATH
string "fake audio device data path"
default "/data/"
---help---
This dir is used to store the audio file for virtual capture or playback device.
The filename for capture device should comply with the format "devname_samplerate_channels_format.pcm".
e.g: pcm2c_16000_2_16.pcm.
The filename format of playback device is the same as capture device.
e.g: pcm2p_16000_2_16.pcm.
config AUDIO_FAKE_MSG_PRIO
int "Fake audio device message priority"
default 1
config AUDIO_FAKE_WORKER_STACKSIZE
int "Fake audio device worker thread stack size"
default 768
endif # AUDIO_FAKE
endif # DRIVERS_AUDIO

View file

@ -87,6 +87,10 @@ ifeq ($(CONFIG_AUDIO_NULL),y)
CSRCS += audio_null.c
endif
ifeq ($(CONFIG_AUDIO_FAKE),y)
CSRCS += audio_fake.c
endif
ifeq ($(CONFIG_AUDIO_TONE),y)
CSRCS += tone.c
endif

1149
drivers/audio/audio_fake.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -130,6 +130,7 @@
#define _POSIX_PIPE_BUF 512
#define _POSIX_STREAM_MAX 16
#define _POSIX_TZNAME_MAX 3
#define _POSIX2_LINE_MAX 80
#ifdef CONFIG_SMALL_MEMORY
@ -202,6 +203,7 @@
#define ARG_MAX _POSIX_ARG_MAX
#define CHILD_MAX _POSIX_CHILD_MAX
#define LINE_MAX _POSIX2_LINE_MAX
#define LINK_MAX _POSIX_LINK_MAX
#define MAX_CANON _POSIX_MAX_CANON
#define MAX_INPUT _POSIX_MAX_INPUT

View file

@ -0,0 +1,52 @@
/****************************************************************************
* include/nuttx/audio/audio_fake.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_AUDIO_AUDIO_FAKE_H
#define __INCLUDE_NUTTX_AUDIO_AUDIO_FAKE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#ifdef CONFIG_AUDIO_FAKE
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
int audio_fake_initialize(void);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_AUDIO_FAKE */
#endif /* __INCLUDE_NUTTX_AUDIO_AUDIO_FAKE_H */

View file

@ -914,6 +914,8 @@ struct sensor_gnss_satellite
uint32_t constellation;
float cf; /* Carrier Frequency(Hz), GSV.signal_id */
struct satellite
{
uint32_t svid; /* Space vehicle ID */

View file

@ -172,6 +172,8 @@
#define SIGSYS 31
#define SIGIOT SIGABRT
/* sigprocmask() "how" definitions.
* Only one of the following can be specified:
*/
@ -199,6 +201,10 @@
* is delivered */
#define SA_KERNELHAND (1 << 7) /* Invoke the handler in kernel space directly */
/* SA_NOMASK is a nonstandard synonym of SA_NODEFER */
#define SA_NOMASK SA_NODEFER
/* These are the possible values of the siginfo si_code field */
#define SI_USER 0 /* Signal sent from kill, raise, or abort */
@ -410,7 +416,11 @@ struct sigaction
} sa_u;
sigset_t sa_mask;
int sa_flags;
FAR void *sa_user; /* Passed to siginfo.si_user (non-standard) */
union
{
CODE void (*sa_restorer)(void);
FAR void *sa_user; /* Passed to siginfo.si_user (non-standard) */
};
};
/* Definitions that adjust the non-standard naming */
@ -427,6 +437,8 @@ typedef struct
size_t ss_size;
} stack_t;
typedef CODE void (*sig_t)(int);
/****************************************************************************
* Public Function Prototypes
****************************************************************************/

View file

@ -1,5 +1,5 @@
/****************************************************************************
* arch/arm/src/common/arm_modifyreg16.c
* include/sys/fcntl.h
*
* SPDX-License-Identifier: Apache-2.0
*
@ -20,46 +20,25 @@
*
****************************************************************************/
#ifndef __INCLUDE_SYS_FCNTL_H
#define __INCLUDE_SYS_FCNTL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <debug.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
#include <fcntl.h>
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_modifyreg_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Name: modifyreg16
*
* Description:
* Atomically modify the specified bits in a memory mapped register
*
* Public Type Definitions
****************************************************************************/
void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits)
{
irqstate_t flags;
uint16_t regval;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
flags = spin_lock_irqsave(&g_modifyreg_lock);
regval = getreg16(addr);
regval &= ~clearbits;
regval |= setbits;
putreg16(regval, addr);
spin_unlock_irqrestore(&g_modifyreg_lock, flags);
}
#endif /* __INCLUDE_SYS_FCNTL_H */

View file

@ -39,7 +39,16 @@
/* Mount flags */
#define MS_RDONLY 1 /* Mount file system read-only */
#define MS_RDONLY 1 /* Mount file system read-only */
#define MS_NOSUID 2 /* Ignore suid and sgid bits */
#define MS_NODEV 4 /* Disallow access to device special files */
#define MS_NOEXEC 8 /* Disallow program execution */
#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
#define MS_NOSYMFOLLOW 256 /* Do not follow symlinks */
#define MS_NOATIME 1024 /* Do not update access times. */
/* Un-mount flags
*

View file

@ -76,6 +76,9 @@
#define PR_SET_NAME_EXT 3
#define PR_GET_NAME_EXT 4
#define PR_SET_DUMPABLE 5
#define PR_GET_DUMPABLE 6
/****************************************************************************
* Public Type Definitions
****************************************************************************/

View file

@ -60,6 +60,7 @@
#define RLIMIT_STACK 6 /* Limit on stack size */
#define RLIMIT_AS 7 /* Limit on address space size */
#define RLIMIT_MEMLOCK 8 /* Limit on memory use */
#define RLIMIT_NICE 10 /* Limit on nice level */
/* Below are not implemented yet: */

View file

@ -1,5 +1,5 @@
/****************************************************************************
* arch/arm/src/common/arm_modifyreg8.c
* include/sys/sem.h
*
* SPDX-License-Identifier: Apache-2.0
*
@ -20,46 +20,25 @@
*
****************************************************************************/
#ifndef __INCLUDE_SYS_SEM_H
#define __INCLUDE_SYS_SEM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <debug.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_modifyreg_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Name: modifyreg8
*
* Description:
* Atomically modify the specified bits in a memory mapped register
*
* Public Type Definitions
****************************************************************************/
void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits)
{
irqstate_t flags;
uint8_t regval;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
flags = spin_lock_irqsave(&g_modifyreg_lock);
regval = getreg8(addr);
regval &= ~clearbits;
regval |= setbits;
putreg8(regval, addr);
spin_unlock_irqrestore(&g_modifyreg_lock, flags);
}
#endif /* __INCLUDE_SYS_SEM_H */

View file

@ -1,5 +1,5 @@
/****************************************************************************
* arch/arm/src/common/arm_modifyreg32.c
* include/sys/signal.h
*
* SPDX-License-Identifier: Apache-2.0
*
@ -20,46 +20,25 @@
*
****************************************************************************/
#ifndef __INCLUDE_SYS_SIGNAL_H
#define __INCLUDE_SYS_SIGNAL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <debug.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
#include <signal.h>
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_modifyreg_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Name: modifyreg32
*
* Description:
* Atomically modify the specified bits in a memory mapped register
*
* Public Type Definitions
****************************************************************************/
void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits)
{
irqstate_t flags;
uint32_t regval;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
flags = spin_lock_irqsave(&g_modifyreg_lock);
regval = getreg32(addr);
regval &= ~clearbits;
regval |= setbits;
putreg32(regval, addr);
spin_unlock_irqrestore(&g_modifyreg_lock, flags);
}
#endif /* __INCLUDE_SYS_VFS_H */

View file

@ -242,6 +242,8 @@
#define SOL_SCO 17 /* See options in include/netpacket/bluetooth.h */
#define SOL_RFCOMM 18 /* See options in include/netpacket/bluetooth.h */
#define SOL_PACKET 19
/* Protocol-level socket options may begin with this value */
#define __SO_PROTOCOL 16

View file

@ -232,6 +232,8 @@ typedef int32_t off_t;
typedef int32_t fpos_t;
#endif
typedef off_t loff_t;
/* blksize_t is a signed integer value used for file block sizes */
typedef int16_t blksize_t;

44
include/wait.h Normal file
View file

@ -0,0 +1,44 @@
/****************************************************************************
* include/wait.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_WAIT_H
#define __INCLUDE_WAIT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/wait.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#endif /* __INCLUDE_WAIT_H */

View file

@ -62,8 +62,8 @@ config IOB_NCHAINS
I/O buffer chain containers that also carry a payload of usage
specific information.
Note: TCP doesn't use this.
Note: UDP and CAN use this.
Note: TCP and UDP don't use this.
Note: ICMP/ICMPv6 and CAN use this.
config IOB_THROTTLE
int "I/O buffer throttle value"

View file

@ -37,7 +37,7 @@ config NET_ICMP_PMTU_TIMEOUT
config NET_ICMP_SOCKET
bool "IPPROTO_ICMP socket support"
default n
select MM_IOB
select NET_READAHEAD
---help---
Enable support for IPPROTO_ICMP sockets. These sockets are needed
for application level support for sending ECHO (ping) requests and

View file

@ -39,7 +39,7 @@ config NET_ICMPv6_PMTU_TIMEOUT
config NET_ICMPv6_SOCKET
bool "IPPROTO_ICMP6 socket support"
default n
select MM_IOB
select NET_READAHEAD
---help---
Enable support for IPPROTO_ICMP6 sockets. These sockets are needed
for application level support for sending ICMPv7 ECHO requests and

View file

@ -65,6 +65,7 @@ static const char *dequote_list[] =
"CONFIG_TTY_LAUNCH_ENTRYPOINT", /* Name of entry point from tty launch */
"CONFIG_TTY_LAUNCH_ARGS", /* Argument list of entry point from tty launch */
"CONFIG_BOARD_MEMORY_RANGE", /* Memory range for board */
"CONFIG_FAKE_AUDIO_DEVICE_PARAMS", /* Arguments for the fake audio device */
/* NxWidgets/NxWM */

204
tools/gcov.py Executable file
View file

@ -0,0 +1,204 @@
#!/usr/bin/env python3
# tools/gcov.py
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import os
import re
import shutil
import subprocess
import sys
def parse_gcda_data(path):
with open(path, "r") as file:
lines = file.read().strip().splitlines()
started = False
filename = ""
output = ""
size = 0
for line in lines:
if line.startswith("gcov start"):
started = True
match = re.search(r"filename:(.*?)\s+size:\s*(\d+)Byte", line)
if match:
filename = match.group(1)
size = int(match.group(2))
continue
if not started:
continue
if line.startswith("gcov end"):
started = False
if size != len(output) // 2:
print(
f"Size mismatch for {filename}: expected {size} bytes, got {len(output) // 2} bytes"
)
match = re.search(r"checksum:\s*(0x[0-9a-fA-F]+)", line)
if match:
checksum = int(match.group(1), 16)
output = bytearray.fromhex(output)
expected = sum(output) % 65536
if checksum != expected:
print(
f"Checksum mismatch for {filename}: expected {checksum}, got {expected}"
)
continue
with open(filename, "wb") as fp:
fp.write(output)
print(f"write {filename} success")
output = ""
else:
output += line.strip()
def copy_file_endswith(endswith, source_dir, target_dir):
print(f"Collect {endswith} files {source_dir} -> {target_dir}")
if not os.path.exists(target_dir):
os.makedirs(target_dir)
for root, _, files in os.walk(source_dir):
for file in files:
if file.endswith(endswith):
source_file = os.path.join(root, file)
target_file = os.path.join(target_dir, file)
shutil.copy2(source_file, target_file)
def arg_parser():
parser = argparse.ArgumentParser(
description="Code coverage generation tool.", add_help=False
)
parser.add_argument("-i", "--input", help="Input dump data")
parser.add_argument("-t", dest="gcov_tool", help="Path to gcov tool")
parser.add_argument("-s", dest="gcno_dir", help="Directory containing gcno files")
parser.add_argument("-a", dest="gcda_dir", help="Directory containing gcda files")
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
parser.add_argument(
"-x",
dest="only_copy",
action="store_true",
help="Only copy *.gcno and *.gcda files",
)
parser.add_argument(
"gcov_dir",
nargs="?",
default=os.getcwd(),
help="Directory to store gcov data and report",
)
return parser.parse_args()
def main():
args = arg_parser()
root_dir = os.getcwd()
gcov_dir = os.path.abspath(args.gcov_dir)
gcno_dir = os.path.abspath(args.gcno_dir) if args.gcno_dir else root_dir
gcda_dir = os.path.abspath(args.gcda_dir) if args.gcda_dir else root_dir
coverage_file = os.path.join(gcov_dir, "coverage.info")
result_dir = os.path.join(gcov_dir, "result")
gcov_data_dir = os.path.join(gcov_dir, "data")
if args.debug:
debug_file = os.path.join(gcov_dir, "debug.log")
sys.stdout = open(debug_file, "w+")
if args.input:
parse_gcda_data(os.path.join(root_dir, args.input))
os.makedirs(os.path.join(gcov_dir, "data"), exist_ok=True)
# Collect gcno, gcda files
copy_file_endswith(".gcno", gcno_dir, gcov_data_dir)
copy_file_endswith(".gcda", gcda_dir, gcov_data_dir)
# Only copy files
if args.only_copy:
sys.exit(0)
# lcov tool is required
if shutil.which("lcov") is None:
print(
"Error: Code coverage generation tool is not detected, please install lcov."
)
sys.exit(1)
try:
# lcov collect coverage data to coverage_file
subprocess.run(
[
"lcov",
"-c",
"-d",
gcov_data_dir,
"-o",
coverage_file,
"--rc",
"lcov_branch_coverage=1",
"--gcov-tool",
args.gcov_tool,
"--ignore-errors",
"gcov",
],
check=True,
stdout=sys.stdout,
stderr=sys.stdout,
)
# genhtml generate coverage report
subprocess.run(
[
"genhtml",
"--branch-coverage",
"-o",
result_dir,
coverage_file,
"--ignore-errors",
"source",
],
check=True,
stdout=sys.stdout,
stderr=sys.stdout,
)
print(
"Copy the following link and open it in the browser to view the coverage report:"
)
print(f"file://{os.path.join(result_dir, 'index.html')}")
except subprocess.CalledProcessError:
print("Failed to generate coverage file.")
sys.exit(1)
shutil.rmtree(gcov_data_dir)
os.remove(coverage_file)
if __name__ == "__main__":
main()

View file

@ -1,147 +0,0 @@
#!/usr/bin/env bash
# tools/gcov.sh
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to you under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
ROOT_DIR=$(pwd)
GCNO_DIR=$ROOT_DIR
GCDA_DIR=$ROOT_DIR
show_help() {
echo "Usage: $0 [-t gcov_tool] [-s gcno_dir] [-a gcda_dir] [-x] [gcov_dir]"
echo " -t gcov_tool: path to gcov tool, e.g. ./nuttx/tools/gcov.sh -t arm-none-eabi-gcov"
echo " -s gcno_dir: directory containing gcno files (relative or absolute path allowed)"
echo " -a gcda_dir: directory containing gcda files (relative or absolute path allowed)"
echo " -x: only copy *.gcno and *.gcda files"
echo " gcov_dir: directory to store gcov data and report (optional)"
exit 1
}
convert_to_absolute_path() {
local dir_path=$1
if [ -z "$dir_path" ]; then
echo "Error: Directory path is empty."
exit 1
fi
# Convert to absolute path if not already
if [ ! "${dir_path:0:1}" = "/" ]; then
dir_path=$(realpath "$dir_path" 2>/dev/null)
fi
echo "$dir_path"
}
while getopts "a:s:t:xh" opt
do
case $opt in
a)
GCDA_DIR=$(convert_to_absolute_path "$OPTARG")
if [ ! -d "$GCDA_DIR" ]; then
echo "Error: Invalid gcda directory: $OPTARG"
exit 1
fi
;;
s)
GCNO_DIR=$(convert_to_absolute_path "$OPTARG")
if [ ! -d "$GCNO_DIR" ]; then
echo "Error: Invalid gcno directory: $OPTARG"
exit 1
fi
;;
t)
GCOV_TOOL="--gcov-tool $OPTARG"
;;
x)
ONLY_COPY=1
;;
h)
show_help
;;
?)
show_help
;;
esac
done
# Handle gcov_dir as the last positional argument
shift $((OPTIND - 1))
if [ $# -gt 1 ]; then
echo "Error: Too many arguments."
show_help
fi
if [ $# -eq 1 ]; then
GCOV_DIR=$(convert_to_absolute_path "$1")
else
GCOV_DIR=${ROOT_DIR}/gcov
fi
mkdir -p ${GCOV_DIR} ${GCOV_DIR}/data
cd ${GCOV_DIR}
# Collect gcno files
find ${GCNO_DIR}/ -name "*.gcno" -exec cp {} ${GCOV_DIR}/data > /dev/null 2>&1 \;
# Collect gcda files
find ${GCDA_DIR}/ -name "*.gcda" -exec cp {} ${GCOV_DIR}/data > /dev/null 2>&1 \;
# Ensure ONLY_COPY is initialized as an integer
ONLY_COPY=${ONLY_COPY:-0}
if [ "$ONLY_COPY" -eq 1 ]; then
exit 0
fi
if [ -z "$GCOV_TOOL" ]; then
echo "Error: -t is a required option."
show_help
exit 1
fi
type lcov > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Code coverage generation tool is not detected, please install lcov"
exit 1
fi
files=$(find ${GCOV_DIR}/data -name "*.gcda" 2> /dev/null | wc -l)
if [ "$files" == "0" ] ;then
echo "gcda file not found in directory ${ROOT_DIR}"
echo "Please run ./nuttx before using gcov.sh to generate the coverage report"
echo "Or copy the gcda file in the device to ${ROOT_DIR}"
exit 1
fi
# Generate coverage text report
lcov -c -d ${GCOV_DIR}/data -o coverage.info --rc lcov_branch_coverage=1 ${GCOV_TOOL} --ignore-errors gcov
# Generate coverage page report
genhtml --branch-coverage -o result coverage.info --ignore-errors source
if [ $? -ne 0 ]; then
echo "Failed to generate coverage file"
exit 1
fi
echo -e "Copy the following link and open it in the browser to view the coverage report"
echo "file://${GCOV_DIR}/result/index.html"

View file

@ -1,94 +0,0 @@
#!/usr/bin/env python3
############################################################################
# tools/gcov_convert.py
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
import argparse
import re
# Parse gcda data from stdout dump format to binary format
# The stdout dump format is:
# gcov start filename:<filename> size: <size>Byte
# <hex dump data>
# gcov end filename:<filename> checksum: <checksum>
#
# The hex dump data will be converted to binary and written to <filename>
# The checksum is calculated by summing all bytes and taking modulo 65536
def parse_gcda_data(input_file):
with open(input_file, "r") as file:
lines = file.read().strip().splitlines()
for line in lines:
if not line.startswith("gcov start"):
continue
match = re.search(r"filename:(.*?)\s+size:\s*(\d+)Byte", line)
if not match:
continue
hex_dump = ""
filename = match.group(1)
size = int(match.group(2))
# Read the hex dump until the end of the file
next_line_index = lines.index(line) + 1
while next_line_index < len(lines) and not lines[next_line_index].startswith(
"gcov end"
):
hex_dump += lines[next_line_index].strip()
next_line_index += 1
if size != len(hex_dump) // 2:
print(
f"Size mismatch for {filename}: expected {size} bytes, got {len(hex_dump) // 2} bytes"
)
checksum_match = (
re.search(r"checksum:\s*(0x[0-9a-fA-F]+)", lines[next_line_index])
if next_line_index < len(lines)
else None
)
if not checksum_match:
continue
checksum = int(checksum_match.group(1), 16)
calculated_checksum = sum(bytearray.fromhex(hex_dump)) % 65536
if calculated_checksum != checksum:
print(
f"Checksum mismatch for {filename}: expected {checksum}, got {calculated_checksum}"
)
continue
with open(filename, "wb") as fp:
fp.write(bytes.fromhex(hex_dump))
print(f"write {filename} success")
print(
"Execute the 'nuttx/tools/gcov.sh -t arm-none-eabi-gcov' command to view the coverage report"
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input", required=True, help="Input dump data")
args = parser.parse_args()
parse_gcda_data(args.input)