Compare commits

...

17 commits

Author SHA1 Message Date
hujun5
f041ae5ca8 pthread: remove enter_critical_section in pthread_mutex
reason:
We would like to replace the critical section with a small lock.

Signed-off-by: hujun5 <hujun5@xiaomi.com>
2025-01-12 10:16:34 +08:00
wangmingrong1
aa0aecbd80 mempool: addbacktrace should be before kasan_unpoison
If thread 1 is executing kasan_unpoison but a scheduling occurs and the block is trampled upon, the displayed backtracking may still be from the previously allocated backtracking

Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
2025-01-12 01:29:14 +08:00
rongyichang
39780fdae1 drivers/vhost-rng: fix compile error in vhost-rng.
vhost/vhost-rng.c:154:9: error: too few arguments to function 'virtio_create_virtqueues'
  154 |   ret = vhost_create_virtqueues(hdev, 0, 1, vqnames, callback);

Signed-off-by: rongyichang <rongyichang@xiaomi.com>
2025-01-12 00:06:12 +08:00
rongyichang
ee2f3df2ff drivers/vhost: fix compile error while get vhost status.
vhost/vhost.c: In function 'vhost_status_driver_ok':
vhost/vhost.c:86:20: error: too few arguments to function 'virtio_get_status'
   86 |   uint8_t status = vhost_get_status(hdev);

Signed-off-by: rongyichang <rongyichang@xiaomi.com>
2025-01-12 00:06:12 +08:00
Yanfeng Liu
ff488133c9 qemu-armv7a: allows ELF_EXECUTABLE
This allows using BINFMT_ELF_EXECUTABLE for qemu-armv7a target.

Signed-off-by: Yanfeng Liu <p-liuyanfeng9@xiaomi.com>
2025-01-11 18:54:36 +08:00
Yanfeng Liu
48846954d8 arm/Toolchain.defs: skip -r for ELF_EXECUTABLE
This avoids using `-r` option when linking executable programs.

Signed-off-by: Yanfeng Liu <p-liuyanfeng9@xiaomi.com>
2025-01-11 18:54:36 +08:00
Yanfeng Liu
657247bda8 libc/modlib: preprocess gnu-elf.ld
This generates gnu-elf.ld via preprocessing of gnu-elf.ld.in so
that to reduce board specific app linker scripts in kernel mode
when BINFMT_ELF_EXECUTABLE is enabled.

Signed-off-by: Yanfeng Liu <p-liuyanfeng9@xiaomi.com>
2025-01-11 18:54:36 +08:00
Yanfeng Liu
be40c01ddd nuttx/addrenv.h: revise assembly guard
This allows the header file to be useful from non-C sources such as
assembly code or linker scripts.

Signed-off-by: Yanfeng Liu <p-liuyanfeng9@xiaomi.com>
2025-01-11 18:54:36 +08:00
wangmingrong1
91c71ed00a mm: Add mm_lock_irq, mm_unlock_iq
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
2025-01-11 12:28:30 +08:00
wangmingrong1
1d8ce18d7f macro/align: Fix ALIGN_UP and ALIGN_DOWN
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
2025-01-11 12:13:10 +08:00
Kyle Wilson
558fe83f6d Add Timer Support to STM32H5 ADC Driver
Added support for using timers with ADCs. Updated Kconfig to support TRGO2, although driver support for TRGO and TRGO2 not developed yet. Updated hardware/stm32_tim.h with missing CCER bits needed for compilation.
2025-01-11 12:04:48 +08:00
wangmingrong1
7c7a64c84c kconfiglib/mark: It should use pip instead of apt install
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
2025-01-10 15:27:06 -03:00
Huang Qi
f2a88059e7 tools/nxstyle.c: Add missing zlib function names to white list
The zlib compression functions are used in network utilities
for compression/decompression. These functions need to be added to
the nxstyle white list to prevent style checking errors since they
follow the zlib naming convention rather than NuttX's style guide.

Specifically, these functions are used in:
- apps/netutils/telnetc/telnetc.c for compressed data handling

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
2025-01-10 15:26:39 -03:00
hujun5
4bd8d9eac7 sched: remove spin_lock_irqsave(NULL) support
Signed-off-by: hujun5 <hujun5@xiaomi.com>
2025-01-10 22:35:14 +08:00
hujun5
69ee240b45 rp2040_pio: remove spin_lock_irqsave(NULL) in arch/arm/src/rp2040/rp2040_pio.c
Signed-off-by: hujun5 <hujun5@xiaomi.com>
2025-01-10 22:35:14 +08:00
wangzhi16
b9837bed08 use small lock to protect g_ram_vectors, involving armv6-m, armv7-m, armv8-m.
Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
2025-01-10 21:33:23 +08:00
wangzhi16
d84ba608a1 use small lock in following files:
arch/arm/src/am335x/am335x_can.c
    arch/arm/src/am335x/am335x_gpio.c
    arch/arm/src/am335x/am335x_i2c.c
    arch/arm/src/am335x/am335x_irq.c
    arch/arm/src/am335x/am335x_serial.c
    arch/arm64/src/imx9/imx9_gpio.c
    arch/arm64/src/imx9/imx9_lpi2c.c
    arch/arm64/src/imx9/imx9_lpspi.c
    arch/arm64/src/imx9/imx9_usbdev.c
    arch/x86_64/src/intel64/intel64_tsc_tickless.c

Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
2025-01-10 21:32:23 +08:00
47 changed files with 1430 additions and 267 deletions

View file

@ -87,7 +87,7 @@ find_program(KCONFIGLIB olddefconfig)
if(NOT KCONFIGLIB)
message(
FATAL_ERROR "Kconfig environment depends on kconfiglib, Please install:
$ sudo apt install python3-kconfiglib")
$ sudo pip3 install kconfiglib")
endif()
# BOARD CONFIG can be set to directory path, or <board-name>[/:]<config-name>

View file

@ -27,9 +27,11 @@
#include <nuttx/config.h>
#include <assert.h>
#include <sched.h>
#include <arch/board/board.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <nuttx/arch.h>
#include <nuttx/can/can.h>
@ -205,6 +207,8 @@ static struct can_dev_s g_can1dev =
};
#endif
static spinlock_t g_can_lock = SP_UNLOCKED;
/****************************************************************************
* Private Functions
****************************************************************************/
@ -1079,7 +1083,8 @@ struct can_dev_s *am335x_can_initialize(int port)
syslog(LOG_DEBUG, "CAN%d\n", port);
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_can_lock);
sched_lock();
#ifdef CONFIG_AM335X_CAN0
if (port == 0)
@ -1109,11 +1114,13 @@ struct can_dev_s *am335x_can_initialize(int port)
{
canerr("Unsupported port: %d\n", port);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_can_lock, flags);
sched_unlock();
return NULL;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_can_lock, flags);
sched_unlock();
return candev;
}
@ -1124,7 +1131,8 @@ void am335x_can_uninitialize(struct can_dev_s *dev)
DEBUGASSERT(dev);
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_can_lock);
sched_lock();
#ifdef CONFIG_AM335X_CAN0
if (dev == &g_can0dev)
@ -1151,7 +1159,8 @@ void am335x_can_uninitialize(struct can_dev_s *dev)
canerr("Not a CAN device: %p\n", dev);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_can_lock, flags);
sched_unlock();
}
#endif

View file

@ -31,6 +31,7 @@
#include <errno.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include "chip.h"
#include "arm_internal.h"
@ -219,6 +220,8 @@ static const uint8_t *g_gpio_padctl[AM335X_GPIO_NPORTS] =
g_gpio3_padctl, /* GPIO3 */
};
static spinlock_t g_gpio_lock = SP_UNLOCKED;
/****************************************************************************
* Private Functions
****************************************************************************/
@ -364,7 +367,7 @@ int am335x_gpio_config(gpio_pinset_t pinset)
/* Configure the pin as an input initially to avoid any spurious outputs */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
/* Configure based upon the pin mode */
@ -407,7 +410,7 @@ int am335x_gpio_config(gpio_pinset_t pinset)
break;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
return ret;
}
@ -425,9 +428,9 @@ void am335x_gpio_write(gpio_pinset_t pinset, bool value)
int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
am335x_gpio_setoutput(port, pin, value);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
}
/****************************************************************************
@ -445,9 +448,9 @@ bool am335x_gpio_read(gpio_pinset_t pinset)
int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
bool value;
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
value = am335x_gpio_getinput(port, pin);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
return value;
}

View file

@ -37,6 +37,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <nuttx/clock.h>
#include <nuttx/mutex.h>
#include <nuttx/semaphore.h>
@ -185,6 +186,7 @@ struct am335x_i2c_priv_s
int refs; /* Reference count */
mutex_t lock; /* Mutual exclusion mutex */
spinlock_t spinlock; /* Spinlock */
#ifndef CONFIG_I2C_POLLED
sem_t sem_isr; /* Interrupt wait semaphore */
#endif
@ -317,6 +319,7 @@ static struct am335x_i2c_priv_s am335x_i2c0_priv =
.config = &am335x_i2c0_config,
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
.spinlock = SP_UNLOCKED,
#ifndef CONFIG_I2C_POLLED
.sem_isr = SEM_INITIALIZER(0),
#endif
@ -352,6 +355,7 @@ static struct am335x_i2c_priv_s am335x_i2c1_priv =
.config = &am335x_i2c1_config,
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
.spinlock = SP_UNLOCKED,
#ifndef CONFIG_I2C_POLLED
.sem_isr = SEM_INITIALIZER(0),
#endif
@ -387,6 +391,7 @@ static struct am335x_i2c_priv_s am335x_i2c2_priv =
.config = &am335x_i2c2_config,
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
.spinlock = SP_UNLOCKED,
#ifndef CONFIG_I2C_POLLED
.sem_isr = SEM_INITIALIZER(0),
#endif
@ -492,7 +497,7 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv)
uint32_t regval;
int ret;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->spinlock);
/* Enable Interrupts when master mode */
@ -529,6 +534,8 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv)
*/
priv->intstate = INTSTATE_WAITING;
spin_unlock_irqrestore(&priv->spinlock, flags);
do
{
/* Wait until either the transfer is complete or the timeout expires */
@ -551,6 +558,8 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv)
}
}
flags = spin_lock_irqsave(&priv->spinlock);
/* Loop until the interrupt level transfer is complete. */
while (priv->intstate != INTSTATE_DONE);
@ -563,7 +572,7 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv)
am335x_i2c_putreg(priv, AM335X_I2C_IRQ_EN_CLR_OFFSET, I2C_ICR_CLEARMASK);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
return ret;
}
#else
@ -992,7 +1001,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv)
*/
#ifdef CONFIG_I2C_POLLED
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->spinlock);
#endif
/* Transmit a byte */
@ -1001,7 +1010,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv)
priv->dcnt--;
#ifdef CONFIG_I2C_POLLED
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
#endif
if ((priv->dcnt == 0) && ((priv->flags & I2C_M_NOSTOP) == 0))
{
@ -1026,7 +1035,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv)
*/
#ifdef CONFIG_I2C_POLLED
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->spinlock);
#endif
/* Receive a byte */
@ -1036,7 +1045,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv)
priv->dcnt--;
#ifdef CONFIG_I2C_POLLED
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
#endif
if ((priv->msgc <= 0) && (priv->dcnt == 0))
{
@ -1100,7 +1109,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv)
*/
#ifdef CONFIG_I2C_POLLED
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->spinlock);
#endif
/* Transmit a byte */
@ -1109,7 +1118,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv)
priv->dcnt--;
#ifdef CONFIG_I2C_POLLED
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
#endif
if ((priv->dcnt == 0) && ((priv->flags & I2C_M_NOSTOP) == 0))
{

View file

@ -29,6 +29,7 @@
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
#include "sctlr.h"
@ -36,6 +37,13 @@
#include "am335x_gpio.h"
#include "am335x_irq.h"
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_ARCH_IRQPRIO
static spinlock_t g_irq_lock = SP_UNLOCKED;
#endif
/****************************************************************************
* Public Data
****************************************************************************/
@ -328,7 +336,7 @@ int up_prioritize_irq(int irq, int priority)
{
/* These operations must be atomic */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
#if 0 // TODO
/* Set the new priority */
@ -340,7 +348,7 @@ int up_prioritize_irq(int irq, int priority)
putreg32(regval, regaddr);
#endif
leave_critical_section(flags);
spin_unlock_irqrestore(&g_irq_lock, flags);
return OK;
}

View file

@ -39,6 +39,7 @@
#endif
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <nuttx/arch.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/serial/serial.h>
@ -76,13 +77,14 @@
struct up_dev_s
{
uint32_t uartbase; /* Base address of UART registers */
uint32_t baud; /* Configured baud */
uint32_t ier; /* Saved IER value */
uint8_t irq; /* IRQ associated with this UART */
uint8_t parity; /* 0=none, 1=odd, 2=even */
uint8_t bits; /* Number of bits (7 or 8) */
bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
uint32_t uartbase; /* Base address of UART registers */
uint32_t baud; /* Configured baud */
uint32_t ier; /* Saved IER value */
uint8_t irq; /* IRQ associated with this UART */
uint8_t parity; /* 0=none, 1=odd, 2=even */
uint8_t bits; /* Number of bits (7 or 8) */
bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
spinlock_t spinlock; /* Spinlock */
};
/****************************************************************************
@ -169,6 +171,7 @@ static struct up_dev_s g_uart0priv =
.parity = CONFIG_UART0_PARITY,
.bits = CONFIG_UART0_BITS,
.stopbits2 = CONFIG_UART0_2STOP,
.spinlock = SP_UNLOCKED,
};
static uart_dev_t g_uart0port =
@ -200,6 +203,7 @@ static struct up_dev_s g_uart1priv =
.parity = CONFIG_UART1_PARITY,
.bits = CONFIG_UART1_BITS,
.stopbits2 = CONFIG_UART1_2STOP,
.spinlock = SP_UNLOCKED,
};
static uart_dev_t g_uart1port =
@ -230,6 +234,7 @@ static struct up_dev_s g_uart2priv =
.parity = CONFIG_UART2_PARITY,
.bits = CONFIG_UART2_BITS,
.stopbits2 = CONFIG_UART2_2STOP,
.spinlock = SP_UNLOCKED,
};
static uart_dev_t g_uart2port =
@ -260,6 +265,7 @@ static struct up_dev_s g_uart3priv =
.parity = CONFIG_UART3_PARITY,
.bits = CONFIG_UART3_BITS,
.stopbits2 = CONFIG_UART3_2STOP,
.spinlock = SP_UNLOCKED,
};
static uart_dev_t g_uart3port =
@ -290,6 +296,7 @@ static struct up_dev_s g_uart4priv =
.parity = CONFIG_UART4_PARITY,
.bits = CONFIG_UART4_BITS,
.stopbits2 = CONFIG_UART4_2STOP,
.spinlock = SP_UNLOCKED,
};
static uart_dev_t g_uart4port =
@ -320,6 +327,7 @@ static struct up_dev_s g_uart5priv =
.parity = CONFIG_UART5_PARITY,
.bits = CONFIG_UART5_BITS,
.stopbits2 = CONFIG_UART5_2STOP,
.spinlock = SP_UNLOCKED,
};
static uart_dev_t g_uart5port =
@ -484,6 +492,10 @@ static uart_dev_t g_uart5port =
# define UART5_ASSIGNED 1
#endif
/* Spinlock */
static spinlock_t g_gpio_lock = SP_UNLOCKED;
/****************************************************************************
* Inline Functions
****************************************************************************/
@ -567,7 +579,7 @@ static inline void am335x_uart0config(void)
/* Step 1: Enable power to UART0 */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
#warning Missing logic
/* Step 2: Enable clocking to UART0 */
@ -577,7 +589,7 @@ static inline void am335x_uart0config(void)
am335x_gpio_config(GPIO_UART0_TXD);
am335x_gpio_config(GPIO_UART0_RXD);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
};
#endif
@ -588,7 +600,7 @@ static inline void am335x_uart1config(void)
/* Step 1: Enable power to UART1 */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
#warning Missing logic
/* Step 2: Enable clocking to UART1 */
@ -598,7 +610,7 @@ static inline void am335x_uart1config(void)
am335x_gpio_config(GPIO_UART1_TXD);
am335x_gpio_config(GPIO_UART1_RXD);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
};
#endif
@ -609,7 +621,7 @@ static inline void am335x_uart2config(void)
/* Step 1: Enable power to UART2 */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
#warning Missing logic
/* Step 2: Enable clocking on UART2 */
@ -619,7 +631,7 @@ static inline void am335x_uart2config(void)
am335x_gpio_config(GPIO_UART2_TXD);
am335x_gpio_config(GPIO_UART2_RXD);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
};
#endif
@ -630,7 +642,7 @@ static inline void am335x_uart3config(void)
/* Step 1: Enable power to UART3 */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
#warning Missing logic
/* Step 2: Enable clocking to UART3 */
@ -640,7 +652,7 @@ static inline void am335x_uart3config(void)
am335x_gpio_config(GPIO_UART3_TXD);
am335x_gpio_config(GPIO_UART3_RXD);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
};
#endif
@ -651,7 +663,7 @@ static inline void am335x_uart4config(void)
/* Step 1: Enable power to UART4 */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
#warning Missing logic
/* Step 2: Enable clocking to UART4 */
@ -661,7 +673,7 @@ static inline void am335x_uart4config(void)
am335x_gpio_config(GPIO_UART4_TXD);
am335x_gpio_config(GPIO_UART4_RXD);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
};
#endif
@ -672,7 +684,7 @@ static inline void am335x_uart5config(void)
/* Step 1: Enable power to UART5 */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
#warning Missing logic
/* Step 2: Enable clocking to UART5 */
@ -682,7 +694,7 @@ static inline void am335x_uart5config(void)
am335x_gpio_config(GPIO_UART5_TXD);
am335x_gpio_config(GPIO_UART5_RXD);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
};
#endif
@ -1029,18 +1041,18 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->spinlock);
up_enablebreaks(priv, true);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
}
break;
case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
{
irqstate_t flags;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->spinlock);
up_enablebreaks(priv, false);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
}
break;
@ -1204,13 +1216,15 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
irqstate_t flags;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->spinlock);
if (enable)
{
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
priv->ier |= UART_IER_THR;
up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier);
spin_unlock_irqrestore(&priv->spinlock, flags);
/* Fake a TX interrupt here by just calling uart_xmitchars() with
* interrupts disabled (note this may recurse).
*/
@ -1222,9 +1236,9 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
{
priv->ier &= ~UART_IER_THR;
up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
}
}
/****************************************************************************

View file

@ -31,11 +31,18 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include "ram_vectors.h"
#ifdef CONFIG_ARCH_RAMVECTORS
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_ramvec_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
****************************************************************************/
@ -68,7 +75,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector)
* common exception handler.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_ramvec_lock);
if (vector == NULL)
{
/* Disable the interrupt if we can before detaching it. We might
@ -87,7 +94,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector)
/* Save the new vector in the vector table */
g_ram_vectors[irq] = vector;
leave_critical_section(flags);
spin_unlock_irqrestore(&g_ramvec_lock, flags);
ret = OK;
}

View file

@ -31,11 +31,18 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include "ram_vectors.h"
#ifdef CONFIG_ARCH_RAMVECTORS
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_ramvec_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
****************************************************************************/
@ -68,7 +75,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector)
* common exception handler.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_ramvec_lock);
if (vector == NULL)
{
/* Disable the interrupt if we can before detaching it. We might
@ -87,7 +94,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector)
/* Save the new vector in the vector table */
g_ram_vectors[irq] = vector;
leave_critical_section(flags);
spin_unlock_irqrestore(&g_ramvec_lock, flags);
ret = OK;
}

View file

@ -31,11 +31,18 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include "ram_vectors.h"
#ifdef CONFIG_ARCH_RAMVECTORS
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_ramvec_lock = SP_UNLOCKED;
/****************************************************************************
* Public Functions
****************************************************************************/
@ -68,7 +75,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector)
* common exception handler.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_ramvec_lock);
if (vector == NULL)
{
/* Disable the interrupt if we can before detaching it. We might
@ -87,7 +94,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector)
/* Save the new vector in the vector table */
g_ram_vectors[irq] = vector;
leave_critical_section(flags);
spin_unlock_irqrestore(&g_ramvec_lock, flags);
ret = OK;
}

View file

@ -546,7 +546,9 @@ ifeq ($(CONFIG_PIC),y)
# Generate an executable elf, need to ignore undefined symbols
LDELFFLAGS += --unresolved-symbols=ignore-in-object-files --emit-relocs
else
LDELFFLAGS += -r
ifneq ($(CONFIG_BINFMT_ELF_EXECUTABLE),y)
LDELFFLAGS += -r
endif
endif
LDELFFLAGS += -e main -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -15,6 +15,7 @@ config ARCH_CHIP_QEMU_CORTEXA7
bool "Qemu virtual Processor (cortex-a7)"
select ARCH_CORTEXA7
select ARCH_HAVE_ADDRENV
select ARCH_HAVE_ELF_EXECUTABLE
select ARCH_HAVE_LOWVECTORS
select ARCH_HAVE_MULTICPU
select ARCH_NEED_ADDRENV_MAPPING

View file

@ -59,8 +59,8 @@
#define hw_claim_lock() spin_lock_irqsave(&pio_lock)
#define hw_claim_unlock(save) spin_unlock_irqrestore(&pio_lock, save)
#else
#define hw_claim_lock() spin_lock_irqsave(NULL)
#define hw_claim_unlock(save) spin_unlock_irqrestore(NULL, save)
#define hw_claim_lock() up_irq_save()
#define hw_claim_unlock(save) up_irq_restore(save)
#endif
/****************************************************************************

View file

@ -2920,10 +2920,10 @@ config STM32H5_ADC1_SAMPLE_FREQUENCY
config STM32H5_ADC1_TIMTRIG
int "ADC1 Timer Trigger"
default 0
range 0 4
range 0 5
depends on STM32H5_HAVE_ADC1_TIMER
---help---
Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO 5:TRGO2
config STM32H5_ADC2_SAMPLE_FREQUENCY
int "ADC2 Sampling Frequency"
@ -2935,10 +2935,10 @@ config STM32H5_ADC2_SAMPLE_FREQUENCY
config STM32H5_ADC2_TIMTRIG
int "ADC2 Timer Trigger"
default 0
range 0 4
range 0 5
depends on STM32H5_HAVE_ADC2_TIMER
---help---
Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO 5:TRGO2
config STM32H5_TIM1_CAP
bool "TIM1 Capture"

View file

@ -363,6 +363,26 @@
#define STM32_TIM16_DCR (STM32_TIM16_BASE+STM32_GTIM_DCR_OFFSET)
#define STM32_TIM16_DMAR (STM32_TIM16_BASE+STM32_GTIM_DMAR_OFFSET)
#define STM32_TIM17_CR1 (STM32_TIM17_BASE+STM32_GTIM_CR1_OFFSET)
#define STM32_TIM17_CR2 (STM32_TIM17_BASE+STM32_GTIM_CR2_OFFSET)
#define STM32_TIM17_DIER (STM32_TIM17_BASE+STM32_GTIM_DIER_OFFSET)
#define STM32_TIM17_SR (STM32_TIM17_BASE+STM32_GTIM_SR_OFFSET)
#define STM32_TIM17_EGR (STM32_TIM17_BASE+STM32_GTIM_EGR_OFFSET)
#define STM32_TIM17_CCMR1 (STM32_TIM17_BASE+STM32_GTIM_CCMR1_OFFSET)
#define STM32_TIM17_CCER (STM32_TIM17_BASE+STM32_GTIM_CCER_OFFSET)
#define STM32_TIM17_CNT (STM32_TIM17_BASE+STM32_GTIM_CNT_OFFSET)
#define STM32_TIM17_PSC (STM32_TIM17_BASE+STM32_GTIM_PSC_OFFSET)
#define STM32_TIM17_ARR (STM32_TIM17_BASE+STM32_GTIM_ARR_OFFSET)
#define STM32_TIM17_RCR (STM32_TIM17_BASE+STM32_GTIM_RCR_OFFSET)
#define STM32_TIM17_CCR1 (STM32_TIM17_BASE+STM32_GTIM_CCR1_OFFSET)
#define STM32_TIM17_BDTR (STM32_TIM17_BASE+STM32_GTIM_BDTR_OFFSET)
#define STM32_TIM17_DTR2 (STM32_TIM17_BASE+STM32_GTIM_DTR2_OFFSET)
#define STM32_TIM17_TISEL (STM32_TIM17_BASE+STM32_GTIM_TISEL_OFFSET)
#define STM32_TIM17_AF1 (STM32_TIM17_BASE+STM32_GTIM_AF1_OFFSET)
#define STM32_TIM17_AF2 (STM32_TIM17_BASE+STM32_GTIM_AF2_OFFSET)
#define STM32_TIM17_DCR (STM32_TIM17_BASE+STM32_GTIM_DCR_OFFSET)
#define STM32_TIM17_DMAR (STM32_TIM17_BASE+STM32_GTIM_DMAR_OFFSET)
/* Register Bitfield Definitions ********************************************/
/* Basic Timers - TIM6 and TIM7 */
@ -764,6 +784,12 @@
#define ATIM_CCER_CC4E (1 << 12) /* Bit 12: Capture/Compare 4 output enable */
#define ATIM_CCER_CC4P (1 << 13) /* Bit 13: Capture/Compare 4 output Polarity */
#define ATIM_CCER_CC4NE (1 << 14) /* Bit 14: Capture/compare 4 Complementary output enable */
#define ATIM_CCER_CC4NP (1 << 15) /* Bit 15: Capture/Compare 4 Complementary output polarity */
#define ATIM_CCER_CC5E (1 << 16) /* Bit 16: Capture/Compare 5 output enable */
#define ATIM_CCER_CC5P (1 << 17) /* Bit 17: Capture/Compare 5 output Polarity */
#define ATIM_CCER_CC6E (1 << 20) /* Bit 20: Capture/Compare 6 output enable */
#define ATIM_CCER_CC6P (1 << 21) /* Bit 21: Capture/Compare 6 output Polarity */
#define ATIM_CCER_CCXBASE(ch) ((ch) << 2) /* Each channel uses 4-bits */
/* Counter Register */

View file

@ -47,6 +47,7 @@
#include "chip.h"
#include "stm32_adc.h"
#include "stm32_tim.h"
#include "stm32_rcc.h"
#ifdef CONFIG_ADC
@ -166,6 +167,16 @@ static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value);
static void adc_modifyreg(struct stm32_dev_s *priv, int offset,
uint32_t clrbits, uint32_t setbits);
#ifdef ADC_HAVE_TIMER
static uint16_t tim_getreg(struct stm32_dev_s *priv, int offset);
static void tim_putreg(struct stm32_dev_s *priv, int offset,
uint16_t value);
static void tim_modifyreg(struct stm32_dev_s *priv, int offset,
uint16_t clrbits, uint16_t setbits);
static void tim_dumpregs(struct stm32_dev_s *priv,
const char *msg);
#endif
/* ADC Miscellaneous Helpers */
static void adc_rccreset(struct stm32_dev_s *priv, bool reset);
@ -178,6 +189,11 @@ static bool adc_internal(struct stm32_dev_s * priv, uint32_t *adc_ccr);
static void adc_startconv(struct stm32_dev_s *priv, bool enable);
static void adc_wdog_enable(struct stm32_dev_s *priv);
#ifdef ADC_HAVE_TIMER
static void adc_timstart(struct stm32_dev_s *priv, bool enable);
static int adc_timinit(struct stm32_dev_s *priv);
#endif
/* ADC Interrupt Handler */
static int adc_interrupt(struct adc_dev_s *dev, uint32_t regval);
@ -220,6 +236,15 @@ static struct stm32_dev_s g_adcpriv1 =
.base = STM32_ADC1_BASE,
.mbase = STM32_ADC1_BASE,
.initialized = false,
#ifdef ADC1_HAVE_TIMER
.trigger = CONFIG_STM32H5_ADC1_TIMTRIG,
.tbase = ADC1_TIMER_BASE,
.trcc_enr = ADC1_TIMER_RCC_ENR,
.trcc_en = ADC1_TIMER_RCC_EN,
.extsel = ADC1_EXTSEL_VALUE,
.pclck = ADC1_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32H5_ADC1_SAMPLE_FREQUENCY,
#endif
};
static struct adc_dev_s g_adcdev1 =
@ -240,6 +265,15 @@ static struct stm32_dev_s g_adcpriv2 =
.base = STM32_ADC2_BASE,
.mbase = STM32_ADC2_BASE,
.initialized = false,
#ifdef ADC2_HAVE_TIMER
.trigger = CONFIG_STM32H5_ADC2_TIMTRIG,
.tbase = ADC2_TIMER_BASE,
.trcc_enr = ADC2_TIMER_RCC_ENR,
.trcc_en = ADC2_TIMER_RCC_EN,
.extsel = ADC2_EXTSEL_VALUE,
.pclck = ADC2_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32H5_ADC2_SAMPLE_FREQUENCY,
#endif
};
static struct adc_dev_s g_adcdev2 =
@ -1212,7 +1246,7 @@ static int adc_interrupt(struct adc_dev_s *dev, uint32_t adcisr)
if ((adcisr & ADC_INT_EOC) != 0)
{
/* Read from the ADC_DR register until 8 stage FIFO is empty.
* The FIFO is first mentioned in STM32H7 Reference Manual
* The FIFO is first mentioned in STM32H5 Reference Manual
* rev. 7, though, not yet indicated in the block diagram!
*/
@ -1307,6 +1341,521 @@ static int adc12_interrupt(int irq, void *context, void *arg)
}
#endif
/****************************************************************************
* Name: tim_getreg
*
* Description:
* Read the value of an ADC timer register.
*
* Input Parameters:
* priv - A reference to the ADC block status
* offset - The offset to the register to read
*
* Returned Value:
* The current contents of the specified register
*
****************************************************************************/
#ifdef ADC_HAVE_TIMER
static uint16_t tim_getreg(struct stm32_dev_s *priv, int offset)
{
return getreg16(priv->tbase + offset);
}
#endif
/****************************************************************************
* Name: tim_putreg
*
* Description:
* Write a value to an ADC timer register.
*
* Input Parameters:
* priv - A reference to the ADC block status
* offset - The offset to the register to write to
* value - The value to write to the register
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef ADC_HAVE_TIMER
static void tim_putreg(struct stm32_dev_s *priv, int offset,
uint16_t value)
{
putreg16(value, priv->tbase + offset);
}
#endif
/****************************************************************************
* Name: tim_modifyreg
*
* Description:
* Modify the value of an ADC timer register (not atomic).
*
* Input Parameters:
* priv - A reference to the ADC block status
* offset - The offset to the register to modify
* clrbits - The bits to clear
* setbits - The bits to set
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef ADC_HAVE_TIMER
static void tim_modifyreg(struct stm32_dev_s *priv, int offset,
uint16_t clrbits, uint16_t setbits)
{
tim_putreg(priv, offset, (tim_getreg(priv, offset) & ~clrbits) | setbits);
}
#endif
/****************************************************************************
* Name: tim_dumpregs
*
* Description:
* Dump all timer registers.
*
* Input Parameters:
* priv - A reference to the ADC block status
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef ADC_HAVE_TIMER
static void tim_dumpregs(struct stm32_dev_s *priv, const char *msg)
{
ainfo("%s:\n", msg);
ainfo(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n",
tim_getreg(priv, STM32_GTIM_CR1_OFFSET),
tim_getreg(priv, STM32_GTIM_CR2_OFFSET),
tim_getreg(priv, STM32_GTIM_SMCR_OFFSET),
tim_getreg(priv, STM32_GTIM_DIER_OFFSET));
ainfo(" SR: %04x EGR: 0000 CCMR1: %04x CCMR2: %04x\n",
tim_getreg(priv, STM32_GTIM_SR_OFFSET),
tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET),
tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET));
ainfo(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n",
tim_getreg(priv, STM32_GTIM_CCER_OFFSET),
tim_getreg(priv, STM32_GTIM_CNT_OFFSET),
tim_getreg(priv, STM32_GTIM_PSC_OFFSET),
tim_getreg(priv, STM32_GTIM_ARR_OFFSET));
ainfo(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n",
tim_getreg(priv, STM32_GTIM_CCR1_OFFSET),
tim_getreg(priv, STM32_GTIM_CCR2_OFFSET),
tim_getreg(priv, STM32_GTIM_CCR3_OFFSET),
tim_getreg(priv, STM32_GTIM_CCR4_OFFSET));
if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE)
{
ainfo(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n",
tim_getreg(priv, STM32_ATIM_RCR_OFFSET),
tim_getreg(priv, STM32_ATIM_BDTR_OFFSET),
tim_getreg(priv, STM32_ATIM_DCR_OFFSET),
tim_getreg(priv, STM32_ATIM_DMAR_OFFSET));
}
else
{
ainfo(" DCR: %04x DMAR: %04x\n",
tim_getreg(priv, STM32_GTIM_DCR_OFFSET),
tim_getreg(priv, STM32_GTIM_DMAR_OFFSET));
}
}
#endif
/****************************************************************************
* Name: adc_timstart
*
* Description:
* Start (or stop) the timer counter
*
* Input Parameters:
* priv - A reference to the ADC block status
* enable - True: Start conversion
*
* Returned Value:
*
****************************************************************************/
#ifdef ADC_HAVE_TIMER
static void adc_timstart(struct stm32_dev_s *priv, bool enable)
{
ainfo("enable: %d\n", enable ? 1 : 0);
if (enable)
{
/* Start the counter */
tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, 0, GTIM_CR1_CEN);
}
else
{
/* Disable the counter */
tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, GTIM_CR1_CEN, 0);
}
}
#endif
/****************************************************************************
* Name: adc_timinit
*
* Description:
* Initialize the timer that drivers the ADC sampling for this channel
* using the pre-calculated timer divider definitions.
*
* Input Parameters:
* priv - A reference to the ADC block status
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef ADC_HAVE_TIMER
static int adc_timinit(struct stm32_dev_s *priv)
{
uint32_t prescaler;
uint32_t reload;
uint32_t timclk;
uint16_t clrbits = 0;
uint16_t setbits = 0;
uint16_t cr2;
uint16_t ccmr1;
uint16_t ccmr2;
uint16_t ocmode1;
uint16_t ocmode2;
uint16_t ccenable;
uint16_t ccer;
uint16_t egr;
/* If the timer base address is zero, then this ADC was not configured to
* use a timer.
*/
if (priv->tbase == 0)
{
return ERROR;
}
/* EXTSEL selection: These bits select the external event used to trigger
* the start of conversion of a regular group. NOTE:
*
* - The position with of the EXTSEL field varies from one STM32 MCU
* to another.
* - The width of the EXTSEL field varies from one STM32 MCU to another.
* - The value in priv->extsel is already shifted into the correct bit
* position.
*/
ainfo("Initializing timers extsel = 0x%08" PRIx32 "\n", priv->extsel);
adc_modifyreg(priv, STM32_ADC_CFGR_OFFSET,
ADC_CFGR_EXTEN_MASK | ADC_CFGR_EXTSEL_MASK,
ADC_CFGR_EXTEN_RISING | priv->extsel);
/* Configure the timer channel to drive the ADC */
/* Enable Timer clocking */
modifyreg32(priv->trcc_enr, 0, priv->trcc_en);
/* Calculate optimal values for the timer prescaler and for the timer
* reload register. If freq is the desired frequency, then
*
* reload = timclk / freq
* reload = (pclck / prescaler) / freq
*
* There are many solutions to do this, but the best solution will be the
* one that has the largest reload value and the smallest prescaler value.
* That is the solution that should give us the most accuracy in the timer
* control. Subject to:
*
* 0 <= prescaler <= 65536
* 1 <= reload <= 65535
*
* So ( prescaler = pclck / 65535 / freq ) would be optimal.
*/
prescaler = (priv->pclck / priv->freq + 65534) / 65535;
/* We need to decrement the prescaler value by one, but only, the value
* does not underflow.
*/
if (prescaler < 1)
{
awarn("WARNING: Prescaler underflowed.\n");
prescaler = 1;
}
/* Check for overflow */
else if (prescaler > 65536)
{
awarn("WARNING: Prescaler overflowed.\n");
prescaler = 65536;
}
timclk = priv->pclck / prescaler;
reload = timclk / priv->freq;
if (reload < 1)
{
awarn("WARNING: Reload value underflowed.\n");
reload = 1;
}
else if (reload > 65535)
{
awarn("WARNING: Reload value overflowed.\n");
reload = 65535;
}
/* Disable the timer until we get it configured */
adc_timstart(priv, false);
/* Set up the timer CR1 register.
*
* Select the Counter Mode == count up:
*
* ATIM_CR1_EDGE: The counter counts up or down depending on the
* direction bit(DIR).
* ATIM_CR1_DIR: 0: count up, 1: count down
*
* Set the clock division to zero for all
*/
clrbits = GTIM_CR1_DIR | GTIM_CR1_CMS_MASK | GTIM_CR1_CKD_MASK;
setbits = GTIM_CR1_EDGE;
tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, clrbits, setbits);
/* Set the reload and prescaler values */
tim_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler - 1);
tim_putreg(priv, STM32_GTIM_ARR_OFFSET, reload);
/* Clear the advanced timers repetition counter in TIM1 */
if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE)
{
tim_putreg(priv, STM32_ATIM_RCR_OFFSET, 0);
tim_putreg(priv, STM32_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */
}
/* TIMx event generation: Bit 0 UG: Update generation */
tim_putreg(priv, STM32_GTIM_EGR_OFFSET, GTIM_EGR_UG);
/* Handle channel specific setup */
ocmode1 = 0;
ocmode2 = 0;
switch (priv->trigger)
{
case 0: /* TimerX CC1 event */
{
ccenable = ATIM_CCER_CC1E;
ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) |
ATIM_CCMR1_OC1PE;
/* Set the event CC1 */
egr = ATIM_EGR_CC1G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR1_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 1: /* TimerX CC2 event */
{
ccenable = ATIM_CCER_CC2E;
ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) |
ATIM_CCMR1_OC2PE;
/* Set the event CC2 */
egr = ATIM_EGR_CC2G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR2_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 2: /* TimerX CC3 event */
{
ccenable = ATIM_CCER_CC3E;
ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) |
ATIM_CCMR2_OC3PE;
/* Set the event CC3 */
egr = ATIM_EGR_CC3G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR3_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 3: /* TimerX CC4 event */
{
ccenable = ATIM_CCER_CC4E;
ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) |
ATIM_CCMR2_OC4PE;
/* Set the event CC4 */
egr = ATIM_EGR_CC4G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 4: /* TimerX TRGO event */
{
/* TODO: TRGO support not yet implemented */
/* Set the event TRGO */
ccenable = 0;
egr = GTIM_EGR_TG;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 5: /* TimerX TRGO2 event */
{
/* TODO: TRGO2 support not yet implemented */
/* Set the event TRGO2 */
ccenable = 0;
egr = GTIM_EGR_TG;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
}
break;
default:
aerr("ERROR: No such trigger: %d\n", priv->trigger);
return -EINVAL;
}
/* Disable the Channel by resetting the CCxE Bit in the CCER register */
ccer = tim_getreg(priv, STM32_GTIM_CCER_OFFSET);
ccer &= ~ccenable;
tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
/* Fetch the CR2, CCMR1, and CCMR2 register (already have ccer) */
cr2 = tim_getreg(priv, STM32_GTIM_CR2_OFFSET);
ccmr1 = tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET);
ccmr2 = tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET);
/* Reset the Output Compare Mode Bits and set the select output compare
* mode
*/
ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE |
ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE);
ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE |
ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE);
ccmr1 |= ocmode1;
ccmr2 |= ocmode2;
/* Reset the output polarity level of all channels (selects high
* polarity)
*/
ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P |
ATIM_CCER_CC3P | ATIM_CCER_CC4P);
/* Enable the output state of the selected channel (only) */
ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E |
ATIM_CCER_CC3E | ATIM_CCER_CC4E);
ccer |= ccenable;
if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE)
{
/* Reset output N polarity level, output N state, output compare state,
* output compare N idle state.
*/
ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP |
ATIM_CCER_CC2NE | ATIM_CCER_CC2NP |
ATIM_CCER_CC3NE | ATIM_CCER_CC3NP |
ATIM_CCER_CC4NP);
/* Reset the output compare and output compare N IDLE State */
cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N |
ATIM_CR2_OIS2 | ATIM_CR2_OIS2N |
ATIM_CR2_OIS3 | ATIM_CR2_OIS3N |
ATIM_CR2_OIS4);
}
else
{
ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP);
}
/* Save the modified register values */
tim_putreg(priv, STM32_GTIM_CR2_OFFSET, cr2);
tim_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
tim_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2);
tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
tim_putreg(priv, STM32_GTIM_EGR_OFFSET, egr);
/* Set the ARR Preload Bit */
tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, 0, GTIM_CR1_ARPE);
/* Enable the timer counter */
adc_timstart(priv, true);
tim_dumpregs(priv, "After starting timers");
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -1368,4 +1917,5 @@ struct adc_dev_s *stm32h5_adc_initialize(int intf,
return dev;
}
#endif /* CONFIG_STM32H5_ADC1 || CONFIG_STM32H5_ADC2 */
#endif /* CONFIG_ADC */
#endif /* CONFIG_ADC */

View file

@ -38,6 +38,462 @@
#if defined(CONFIG_STM32H5_ADC1) || defined(CONFIG_STM32H5_ADC2)
/* Configuration ************************************************************/
/* Timer devices may be used for different purposes. One special purpose is
* to control periodic ADC sampling. If CONFIG_STM32H5_TIMn is defined then
* CONFIG_STM32H5_TIMn_ADC must also be defined to indicate that timer "n"
* is intended to be used for that purpose. Timers 1,2,3,6 and 15 may be
* used on STM32H5X3, while STM32H5X6 adds support for timers 4 and 8 as
* well.
*/
#ifndef CONFIG_STM32H5_TIM1
# undef CONFIG_STM32H5_TIM1_ADC
# undef CONFIG_STM32H5_TIM1_ADC1
# undef CONFIG_STM32H5_TIM1_ADC2
# undef CONFIG_STM32H5_TIM1_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM2
# undef CONFIG_STM32H5_TIM2_ADC
# undef CONFIG_STM32H5_TIM2_ADC1
# undef CONFIG_STM32H5_TIM2_ADC2
# undef CONFIG_STM32H5_TIM2_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM3
# undef CONFIG_STM32H5_TIM3_ADC
# undef CONFIG_STM32H5_TIM3_ADC1
# undef CONFIG_STM32H5_TIM3_ADC2
# undef CONFIG_STM32H5_TIM3_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM4
# undef CONFIG_STM32H5_TIM4_ADC
# undef CONFIG_STM32H5_TIM4_ADC1
# undef CONFIG_STM32H5_TIM4_ADC2
# undef CONFIG_STM32H5_TIM4_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM6
# undef CONFIG_STM32H5_TIM6_ADC
# undef CONFIG_STM32H5_TIM6_ADC1
# undef CONFIG_STM32H5_TIM6_ADC2
# undef CONFIG_STM32H5_TIM6_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM8
# undef CONFIG_STM32H5_TIM8_ADC
# undef CONFIG_STM32H5_TIM8_ADC1
# undef CONFIG_STM32H5_TIM8_ADC2
# undef CONFIG_STM32H5_TIM8_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM15
# undef CONFIG_STM32H5_TIM15_ADC
# undef CONFIG_STM32H5_TIM15_ADC1
# undef CONFIG_STM32H5_TIM15_ADC2
# undef CONFIG_STM32H5_TIM15_ADC3
#endif
/* Timer configuration: If a timer trigger is specified, then get
* information about the timer.
*/
#if defined(CONFIG_STM32H5_TIM1_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM1_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN
# define ADC1_TIMER_RCC_ENR STM32_RCC_APB2ENR
# define ADC1_TIMER_RCC_EN RCC_APB2ENR_TIM1EN
#elif defined(CONFIG_STM32H5_TIM2_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM2_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN
# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM2EN
#elif defined(CONFIG_STM32H5_TIM3_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM3_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN
# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM3EN
#elif defined(CONFIG_STM32H5_TIM4_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM4_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN
# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM4EN
#elif defined(CONFIG_STM32H5_TIM6_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM6_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN
# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM6EN
#elif defined(CONFIG_STM32H5_TIM8_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM8_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN
# define ADC1_TIMER_RCC_ENR STM32_RCC_APB2ENR
# define ADC1_TIMER_RCC_EN RCC_APB2ENR_TIM8EN
#elif defined(CONFIG_STM32H5_TIM15_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM15_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM15_CLKIN
# define ADC1_TIMER_RCC_ENR STM32_RCC_APB2ENR
# define ADC1_TIMER_RCC_EN RCC_APB2ENR_TIM15EN
#else
# undef ADC1_HAVE_TIMER
#endif
#ifdef ADC1_HAVE_TIMER
# ifndef CONFIG_STM32H5_ADC1_SAMPLE_FREQUENCY
# error "CONFIG_STM32H5_ADC1_SAMPLE_FREQUENCY not defined"
# endif
# ifndef CONFIG_STM32H5_ADC1_TIMTRIG
# error "CONFIG_STM32H5_ADC1_TIMTRIG not defined"
# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO"
# endif
#endif
#if defined(CONFIG_STM32H5_TIM1_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32_TIM1_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN
# define ADC2_TIMER_RCC_ENR STM32_RCC_APB2ENR
# define ADC2_TIMER_RCC_EN RCC_APB2ENR_TIM1EN
#elif defined(CONFIG_STM32H5_TIM2_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32_TIM2_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN
# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM2EN
#elif defined(CONFIG_STM32H5_TIM3_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32_TIM3_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN
# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM3EN
#elif defined(CONFIG_STM32H5_TIM4_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32_TIM4_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN
# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM4EN
#elif defined(CONFIG_STM32H5_TIM6_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32_TIM6_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN
# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR
# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM6EN
#elif defined(CONFIG_STM32H5_TIM8_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32_TIM8_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN
# define ADC2_TIMER_RCC_ENR STM32_RCC_APB2ENR
# define ADC2_TIMER_RCC_EN RCC_APB2ENR_TIM8EN
#elif defined(CONFIG_STM32H5_TIM15_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32_TIM15_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM15_CLKIN
# define ADC2_TIMER_RCC_ENR STM32_RCC_APB2ENR
# define ADC2_TIMER_RCC_EN RCC_APB2ENR_TIM15EN
#else
# undef ADC2_HAVE_TIMER
#endif
#ifdef ADC2_HAVE_TIMER
# ifndef CONFIG_STM32H5_ADC2_SAMPLE_FREQUENCY
# error "CONFIG_STM32H5_ADC2_SAMPLE_FREQUENCY not defined"
# endif
# ifndef CONFIG_STM32H5_ADC2_TIMTRIG
# error "CONFIG_STM32H5_ADC2_TIMTRIG not defined"
# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO"
# endif
#endif
#if defined(ADC1_HAVE_TIMER) || defined(ADC2_HAVE_TIMER)
# define ADC_HAVE_TIMER 1
#else
# undef ADC_HAVE_TIMER
#endif
/* Timer 1 */
#define ADC1_EXTSEL_T1CC1 ADC_CFGR_EXTSEL_T1CC1
#define ADC1_EXTSEL_T1CC2 ADC_CFGR_EXTSEL_T1CC2
#define ADC1_EXTSEL_T1CC3 ADC_CFGR_EXTSEL_T1CC3
#define ADC1_EXTSEL_T1CC4 ADC_CFGR_EXTSEL_T1CC4
#define ADC1_EXTSEL_T1TRGO ADC_CFGR_EXTSEL_T1TRGO
#define ADC1_EXTSEL_T1TRGO2 ADC_CFGR_EXTSEL_T1TRGO2
#define ADC2_EXTSEL_T1CC1 ADC_CFGR_EXTSEL_T1CC1
#define ADC2_EXTSEL_T1CC2 ADC_CFGR_EXTSEL_T1CC2
#define ADC2_EXTSEL_T1CC3 ADC_CFGR_EXTSEL_T1CC3
#define ADC2_EXTSEL_T1CC4 ADC_CFGR_EXTSEL_T1CC4
#define ADC2_EXTSEL_T1TRGO ADC_CFGR_EXTSEL_T1TRGO
#define ADC2_EXTSEL_T1TRGO2 ADC_CFGR_EXTSEL_T1TRGO2
/* Timer 2 */
#define ADC1_EXTSEL_T2CC2 ADC_CFGR_EXTSEL_T2CC2
#define ADC1_EXTSEL_T2TRGO ADC_CFGR_EXTSEL_T2TRGO
#define ADC2_EXTSEL_T2CC2 ADC_CFGR_EXTSEL_T2CC2
#define ADC2_EXTSEL_T2TRGO ADC_CFGR_EXTSEL_T2TRGO
/* Timer 3 */
#define ADC1_EXTSEL_T3CC4 ADC_CFGR_EXTSEL_T3CC4
#define ADC1_EXTSEL_T3TRGO ADC_CFGR_EXTSEL_T3TRGO
#define ADC2_EXTSEL_T3CC4 ADC_CFGR_EXTSEL_T3CC4
#define ADC2_EXTSEL_T3TRGO ADC_CFGR_EXTSEL_T3TRGO
/* Timer 4 */
#define ADC1_EXTSEL_T4CC4 ADC_CFGR_EXTSEL_T4CC4
#define ADC1_EXTSEL_T4TRGO ADC_CFGR_EXTSEL_T4TRGO
#define ADC2_EXTSEL_T4CC4 ADC_CFGR_EXTSEL_T4CC4
#define ADC2_EXTSEL_T4TRGO ADC_CFGR_EXTSEL_T4TRGO
/* Timer 6 */
#define ADC1_EXTSEL_T6TRGO ADC_CFGR_EXTSEL_T6TRGO
#define ADC2_EXTSEL_T6TRGO ADC_CFGR_EXTSEL_T6TRGO
/* Timer 8 */
#define ADC1_EXTSEL_T8TRGO ADC_CFGR_EXTSEL_T8TRGO
#define ADC1_EXTSEL_T8TRGO2 ADC_CFGR_EXTSEL_T8TRGO2
#define ADC2_EXTSEL_T8TRGO ADC_CFGR_EXTSEL_T8TRGO
#define ADC2_EXTSEL_T8TRGO2 ADC_CFGR_EXTSEL_T8TRGO2
/* Timer 15 */
#define ADC1_EXTSEL_T15TRGO ADC_CFGR_EXTSEL_T15TRGO
#define ADC2_EXTSEL_T15TRGO ADC_CFGR_EXTSEL_T15TRGO
#if defined(CONFIG_STM32H5_TIM1_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC1
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC2
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC3
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC4
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO2
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM1)"
# endif
#elif defined(CONFIG_STM32H5_TIM2_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC2
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM2)"
# endif
#elif defined(CONFIG_STM32H5_TIM3_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC4
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM3)"
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM3)"
# endif
#elif defined(CONFIG_STM32H5_TIM4_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC4
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM4)"
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM4)"
# endif
#elif defined(CONFIG_STM32H5_TIM6_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM6)"
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM6)"
# endif
#elif defined(CONFIG_STM32H5_TIM8_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO2
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM8)"
# endif
#elif defined(CONFIG_STM32H5_TIM15_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM15)"
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM15)"
# endif
#endif
#if defined(CONFIG_STM32H5_TIM1_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC1
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC2
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC3
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC4
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO2
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM1)"
# endif
#elif defined(CONFIG_STM32H5_TIM2_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC2
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM2)"
# endif
#elif defined(CONFIG_STM32H5_TIM3_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC4
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM3)"
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM3)"
# endif
#elif defined(CONFIG_STM32H5_TIM4_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC4
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM4)"
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM4)"
# endif
#elif defined(CONFIG_STM32H5_TIM6_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM6)"
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM6)"
# endif
#elif defined(CONFIG_STM32H5_TIM8_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO2
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM8)"
# endif
#elif defined(CONFIG_STM32H5_TIM15_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T15TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM15)"
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM15)"
# endif
#endif
/****************************************************************************
* Public Types
****************************************************************************/

View file

@ -33,6 +33,7 @@
#include <errno.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <imx9_gpiobase.c>
@ -45,6 +46,10 @@
* Private Functions
****************************************************************************/
/* Spinlock */
static spinlock_t g_gpio_lock = SP_UNLOCKED;
/****************************************************************************
* Name: imx9_gpio_dirout
****************************************************************************/
@ -174,7 +179,7 @@ int imx9_config_gpio(gpio_pinset_t pinset)
/* Configure the pin as an input initially to avoid any spurious outputs */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
/* Configure based upon the pin mode */
@ -223,7 +228,7 @@ int imx9_config_gpio(gpio_pinset_t pinset)
break;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
return ret;
}
@ -243,9 +248,9 @@ void imx9_gpio_write(gpio_pinset_t pinset, bool value)
DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS);
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
imx9_gpio_setoutput(port, pin, value);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
}
/****************************************************************************
@ -265,7 +270,7 @@ bool imx9_gpio_read(gpio_pinset_t pinset)
DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS);
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_gpio_lock);
if ((pinset & (GPIO_OUTPUT)) == (GPIO_OUTPUT))
{
value = imx9_gpio_get_pinstatus(port, pin);
@ -275,6 +280,6 @@ bool imx9_gpio_read(gpio_pinset_t pinset)
value = imx9_gpio_getinput(port, pin);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_gpio_lock, flags);
return value;
}

View file

@ -2438,7 +2438,7 @@ int imx9_i2cbus_uninitialize(struct i2c_master_s *dev)
if (--priv->refs > 0)
{
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->spinlock, flags);
return OK;
}

View file

@ -1798,8 +1798,6 @@ struct spi_dev_s *imx9_lpspibus_initialize(int bus)
{
struct imx9_lpspidev_s *priv = NULL;
irqstate_t flags = enter_critical_section();
#ifdef CONFIG_IMX9_LPSPI1
if (bus == 1)
{
@ -2017,7 +2015,6 @@ struct spi_dev_s *imx9_lpspibus_initialize(int bus)
else
#endif
{
leave_critical_section(flags);
spierr("ERROR: Unsupported SPI bus: %d\n", bus);
return NULL;
}
@ -2061,7 +2058,6 @@ struct spi_dev_s *imx9_lpspibus_initialize(int bus)
}
#endif
leave_critical_section(flags);
return (struct spi_dev_s *)priv;
}

View file

@ -2319,9 +2319,9 @@ static int imx9_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
spin_unlock_irqrestore(&privep->spinlock, flags);
imx9_cancelrequests(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->spinlock, flags);
return OK;
}

View file

@ -57,6 +57,7 @@
#include <nuttx/arch.h>
#include <nuttx/clock.h>
#include <nuttx/spinlock.h>
#ifdef CONFIG_SCHED_TICKLESS
@ -90,6 +91,7 @@ static uint32_t g_timer_active;
static irqstate_t g_tmr_sync_count;
static irqstate_t g_tmr_flags;
static spinlock_t g_tmr_lock = SP_UNLOCKED;
/****************************************************************************
* Private Functions
@ -161,7 +163,7 @@ static inline void up_tmr_sync_up(void)
{
if (!g_tmr_sync_count)
{
g_tmr_flags = enter_critical_section();
g_tmr_flags = spin_lock_irqsave(&g_tmr_lock);
}
g_tmr_sync_count++;
@ -171,7 +173,7 @@ static inline void up_tmr_sync_down(void)
{
if (g_tmr_sync_count == 1)
{
leave_critical_section(g_tmr_flags);
spin_unlock_irqrestore(&g_tmr_lock, g_tmr_flags);
}
if (g_tmr_sync_count > 0)

View file

@ -30,6 +30,7 @@
#include <stdlib.h>
#include <nuttx/kmalloc.h>
#include <nuttx/spinlock.h>
#include <nuttx/vhost/vhost.h>
#include <nuttx/wqueue.h>
@ -151,7 +152,7 @@ static int vhost_rng_probe(FAR struct vhost_device *hdev)
vqnames[0] = "virtio_rng";
callback[0] = vhost_rng_handler;
ret = vhost_create_virtqueues(hdev, 0, 1, vqnames, callback);
ret = vhost_create_virtqueues(hdev, 0, 1, vqnames, callback, NULL);
if (ret < 0)
{
vhosterr("virtio_device_create_virtqueue failed, ret=%d\n", ret);

View file

@ -83,8 +83,15 @@ static struct vhost_bus_s g_vhost_bus =
static bool vhost_status_driver_ok(FAR struct vhost_device *hdev)
{
uint8_t status = vhost_get_status(hdev);
bool driver_ok = false;
uint8_t status;
int ret;
ret = vhost_get_status(hdev, &status);
if (ret)
{
return driver_ok;
}
/* Busy wait until the remote is ready */

View file

@ -29,6 +29,8 @@
#include <nuttx/config.h>
#ifndef __ASSEMBLY__
#ifdef CONFIG_BUILD_KERNEL
# include <signal.h>
#endif
@ -40,6 +42,8 @@
#include <arch/arch.h>
#endif /* __ASSEMBLY__ */
#ifdef CONFIG_ARCH_ADDRENV
/****************************************************************************
@ -241,6 +245,9 @@
(CONFIG_ARCH_PGPOOL_VBASE + CONFIG_ARCH_PGPOOL_SIZE)
#endif
#ifndef __ASSEMBLY__
/****************************************************************************
* Public Type Definitions
****************************************************************************/
@ -251,8 +258,6 @@ struct tcb_s; /* Forward reference to TCB */
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
struct addrenv_s
{
struct arch_addrenv_s addrenv; /* The address environment page directory */

View file

@ -48,7 +48,7 @@
#endif
#ifndef ALIGN_UP
# define ALIGN_UP(x,a) (((x) + ((a) - 1)) & ~((a) - 1))
# define ALIGN_UP(x,a) ((((x) + (a) - 1) / (a)) * (a))
#endif
#ifndef ALIGN_UP_MASK
@ -56,7 +56,7 @@
#endif
#ifndef ALIGN_DOWN
# define ALIGN_DOWN(x,a) ((x) & (~((a) - 1)))
# define ALIGN_DOWN(x,a) (((x) / (a)) * (a))
#endif
#ifndef ALIGN_DOWN_MASK

View file

@ -48,6 +48,7 @@
#include <nuttx/net/net.h>
#include <nuttx/mm/map.h>
#include <nuttx/tls.h>
#include <nuttx/spinlock_type.h>
#include <arch/arch.h>
@ -737,6 +738,10 @@ struct tcb_s
size_t level_deepest;
size_t level;
#endif
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
spinlock_t mutex_lock;
#endif
};
/* struct task_tcb_s ********************************************************/

View file

@ -106,14 +106,6 @@ void sched_note_spinlock_unlock(FAR volatile spinlock_t *spinlock);
* Public Data Types
****************************************************************************/
/* Used for access control */
extern volatile spinlock_t g_irq_spin;
/* Handles nested calls to spin_lock_irqsave and spin_unlock_irqrestore */
extern volatile uint8_t g_irq_spin_count[CONFIG_SMP_NCPUS];
/****************************************************************************
* Name: up_testset
*
@ -448,26 +440,12 @@ static inline_function void spin_unlock(FAR volatile spinlock_t *lock)
static inline_function
irqstate_t spin_lock_irqsave_wo_note(FAR volatile spinlock_t *lock)
{
irqstate_t ret;
ret = up_irq_save();
irqstate_t flags;
flags = up_irq_save();
if (NULL == lock)
{
int me = this_cpu();
if (0 == g_irq_spin_count[me])
{
spin_lock_wo_note(&g_irq_spin);
}
spin_lock_wo_note(lock);
g_irq_spin_count[me]++;
DEBUGASSERT(0 != g_irq_spin_count[me]);
}
else
{
spin_lock_wo_note(lock);
}
return ret;
return flags;
}
#else
# define spin_lock_irqsave_wo_note(l) ((void)(l), up_irq_save())
@ -478,14 +456,7 @@ irqstate_t spin_lock_irqsave_wo_note(FAR volatile spinlock_t *lock)
*
* Description:
* If SMP is enabled:
* If the argument lock is not specified (i.e. NULL),
* disable local interrupts and take the global spinlock (g_irq_spin)
* if the call counter (g_irq_spin_count[cpu]) equals to 0. Then the
* counter on the CPU is incremented to allow nested calls and return
* the interrupt state.
*
* If the argument lock is specified,
* disable local interrupts and take the lock spinlock and return
* Disable local interrupts and take the lock spinlock and return
* the interrupt state.
*
* NOTE: This API is very simple to protect data (e.g. H/W register
@ -496,9 +467,7 @@ irqstate_t spin_lock_irqsave_wo_note(FAR volatile spinlock_t *lock)
* This function is equivalent to up_irq_save().
*
* Input Parameters:
* lock - Caller specific spinlock. If specified NULL, g_irq_spin is used
* and can be nested. Otherwise, nested call for the same lock
* would cause a deadlock
* lock - Caller specific spinlock. not NULL.
*
* Returned Value:
* An opaque, architecture-specific value that represents the state of
@ -618,21 +587,7 @@ static inline_function
void spin_unlock_irqrestore_wo_note(FAR volatile spinlock_t *lock,
irqstate_t flags)
{
if (NULL == lock)
{
int me = this_cpu();
DEBUGASSERT(0 < g_irq_spin_count[me]);
g_irq_spin_count[me]--;
if (0 == g_irq_spin_count[me])
{
spin_unlock_wo_note(&g_irq_spin);
}
}
else
{
spin_unlock_wo_note(lock);
}
spin_unlock_wo_note(lock);
up_irq_restore(flags);
}
@ -645,21 +600,14 @@ void spin_unlock_irqrestore_wo_note(FAR volatile spinlock_t *lock,
*
* Description:
* If SMP is enabled:
* If the argument lock is not specified (i.e. NULL),
* decrement the call counter (g_irq_spin_count[cpu]) and if it
* decrements to zero then release the spinlock (g_irq_spin) and
* restore the interrupt state as it was prior to the previous call to
* spin_lock_irqsave(NULL).
*
* If the argument lock is specified, release the lock and
* restore the interrupt state as it was prior to the previous call to
* spin_lock_irqsave(lock).
* Release the lock and restore the interrupt state as it was prior
* to the previous call to spin_lock_irqsave(lock).
*
* If SMP is not enabled:
* This function is equivalent to up_irq_restore().
*
* Input Parameters:
* lock - Caller specific spinlock. If specified NULL, g_irq_spin is used.
* lock - Caller specific spinlock. not NULL
*
* flags - The architecture-specific value that represents the state of
* the interrupts prior to the call to spin_lock_irqsave(lock);

View file

@ -1,2 +1,3 @@
/exec_symtab.c
/modlib_symtab.c
modlib/gnu-elf.ld

View file

@ -183,6 +183,10 @@ context:: bin kbin
ifeq ($(CONFIG_LIBC_ZONEINFO_ROMFS),y)
$(Q) $(MAKE) -C zoneinfo context BIN=$(BIN)
endif
ifeq ($(CONFIG_LIBC_MODLIB),y)
$(Q) $(MAKE) -C modlib context
endif
# Dependencies
@ -210,6 +214,7 @@ depend:: .depend
clean::
$(Q) $(MAKE) -C zoneinfo clean BIN=$(BIN)
$(Q) $(MAKE) -C modlib clean
$(call DELFILE, $(BIN))
$(call DELFILE, $(KBIN))
$(call CLEAN)
@ -218,6 +223,7 @@ clean::
distclean:: clean
$(Q) $(MAKE) -C zoneinfo distclean BIN=$(BIN)
$(Q) $(MAKE) -C modlib distclean
$(call DELFILE, exec_symtab.c)
$(call DELFILE, .depend)
$(call DELDIR, bin)

40
libs/libc/modlib/Makefile Normal file
View file

@ -0,0 +1,40 @@
############################################################################
# libs/libc/modlib/Makefile
#
# 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.
#
############################################################################
include $(TOPDIR)/Make.defs
# Generate gnu-elf.ld from gnu-elf.ld.in
gnu-elf.ld: gnu-elf.ld.in
$(call PREPROCESS, $<, $@)
# Create initial context
context: gnu-elf.ld
.PHONY: context clean distclean
clean:
$(call CLEAN)
distclean: clean
$(call DELFILE, gnu-elf.ld)

View file

@ -1,5 +1,5 @@
/****************************************************************************
* libs/libc/modlib/gnu-elf.ld
* libs/libc/modlib/gnu-elf.ld.in
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@ -18,9 +18,23 @@
*
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_BINFMT_ELF_EXECUTABLE)
# define __ASSEMBLY__
# include <nuttx/addrenv.h>
# define TEXT CONFIG_ARCH_TEXT_VBASE
# define DATA CONFIG_ARCH_DATA_VBASE + ARCH_DATA_RESERVE_SIZE
#else
# define TEXT 0x0
# define DATA
#endif
SECTIONS
{
.text 0x00000000 :
.text TEXT :
{
_stext = . ;
*(.text)
@ -58,7 +72,7 @@ SECTIONS
_erodata = . ;
}
.data :
.data DATA :
{
_sdata = . ;
*(.data)

View file

@ -397,16 +397,17 @@ retry:
pool->nalloc++;
spin_unlock_irqrestore(&pool->lock, flags);
blk = kasan_unpoison(blk, pool->blocksize);
#ifdef CONFIG_MM_FILL_ALLOCATIONS
memset(blk, MM_ALLOC_MAGIC, pool->blocksize);
#endif
#if CONFIG_MM_BACKTRACE >= 0
mempool_add_backtrace(pool, (FAR struct mempool_backtrace_s *)
((FAR char *)blk + pool->blocksize));
#endif
blk = kasan_unpoison(blk, pool->blocksize);
#ifdef CONFIG_MM_FILL_ALLOCATIONS
memset(blk, MM_ALLOC_MAGIC, pool->blocksize);
#endif
return blk;
}

View file

@ -282,6 +282,8 @@ typedef CODE void (*mm_node_handler_t)(FAR struct mm_allocnode_s *node,
int mm_lock(FAR struct mm_heap_s *heap);
void mm_unlock(FAR struct mm_heap_s *heap);
irqstate_t mm_lock_irq(FAR struct mm_heap_s *heap);
void mm_unlock_irq(FAR struct mm_heap_s *heap, irqstate_t state);
/* Functions contained in mm_shrinkchunk.c **********************************/

View file

@ -49,7 +49,7 @@ static void add_delaylist(FAR struct mm_heap_s *heap, FAR void *mem)
/* Delay the deallocation until a more appropriate time. */
flags = up_irq_save();
flags = mm_lock_irq(heap);
# ifdef CONFIG_DEBUG_ASSERTIONS
FAR struct mm_freenode_s *node;
@ -65,7 +65,7 @@ static void add_delaylist(FAR struct mm_heap_s *heap, FAR void *mem)
heap->mm_delaycount[this_cpu()]++;
#endif
up_irq_restore(flags);
mm_unlock_irq(heap, flags);
#endif
}

View file

@ -117,3 +117,31 @@ void mm_unlock(FAR struct mm_heap_s *heap)
DEBUGVERIFY(nxmutex_unlock(&heap->mm_lock));
}
/****************************************************************************
* Name: mm_lock_irq
*
* Description:
* Locking by pausing interruption
*
****************************************************************************/
irqstate_t mm_lock_irq(FAR struct mm_heap_s *heap)
{
UNUSED(heap);
return up_irq_save();
}
/****************************************************************************
* Name: mm_unlock_irq
*
* Description:
* Release the lock by resuming the interrupt
*
****************************************************************************/
void mm_unlock_irq(FAR struct mm_heap_s *heap, irqstate_t state)
{
UNUSED(heap);
up_irq_restore(state);
}

View file

@ -65,7 +65,7 @@ static bool free_delaylist(FAR struct mm_heap_s *heap, bool force)
/* Move the delay list to local */
flags = up_irq_save();
flags = mm_lock_irq(heap);
tmp = heap->mm_delaylist[this_cpu()];
@ -74,7 +74,7 @@ static bool free_delaylist(FAR struct mm_heap_s *heap, bool force)
(!force &&
heap->mm_delaycount[this_cpu()] < CONFIG_MM_FREE_DELAYCOUNT_MAX))
{
up_irq_restore(flags);
mm_unlock_irq(heap, flags);
return false;
}
@ -83,7 +83,7 @@ static bool free_delaylist(FAR struct mm_heap_s *heap, bool force)
heap->mm_delaylist[this_cpu()] = NULL;
up_irq_restore(flags);
mm_unlock_irq(heap, flags);
/* Test if the delayed is empty */

View file

@ -181,6 +181,34 @@ static void mm_delayfree(struct mm_heap_s *heap, void *mem, bool delay);
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mm_lock_irq
*
* Description:
* Locking by pausing interruption
*
****************************************************************************/
static irqstate_t mm_lock_irq(FAR struct mm_heap_s *heap)
{
UNUSED(heap);
return up_irq_save();
}
/****************************************************************************
* Name: mm_unlock_irq
*
* Description:
* Release the lock by resuming the interrupt
*
****************************************************************************/
static void mm_unlock_irq(FAR struct mm_heap_s *heap, irqstate_t state)
{
UNUSED(heap);
up_irq_restore(state);
}
static void memdump_allocnode(FAR void *ptr, size_t size)
{
#if CONFIG_MM_BACKTRACE < 0
@ -301,7 +329,7 @@ static void add_delaylist(FAR struct mm_heap_s *heap, FAR void *mem)
/* Delay the deallocation until a more appropriate time. */
flags = up_irq_save();
flags = mm_lock_irq(heap);
tmp->flink = heap->mm_delaylist[this_cpu()];
heap->mm_delaylist[this_cpu()] = tmp;
@ -310,7 +338,7 @@ static void add_delaylist(FAR struct mm_heap_s *heap, FAR void *mem)
heap->mm_delaycount[this_cpu()]++;
#endif
up_irq_restore(flags);
mm_unlock_irq(heap, flags);
#endif
}
@ -327,7 +355,7 @@ static bool free_delaylist(FAR struct mm_heap_s *heap, bool force)
/* Move the delay list to local */
flags = up_irq_save();
flags = mm_lock_irq(heap);
tmp = heap->mm_delaylist[this_cpu()];
@ -336,7 +364,7 @@ static bool free_delaylist(FAR struct mm_heap_s *heap, bool force)
(!force &&
heap->mm_delaycount[this_cpu()] < CONFIG_MM_FREE_DELAYCOUNT_MAX))
{
up_irq_restore(flags);
mm_unlock_irq(heap, flags);
return false;
}
@ -345,7 +373,7 @@ static bool free_delaylist(FAR struct mm_heap_s *heap, bool force)
heap->mm_delaylist[this_cpu()] = NULL;
up_irq_restore(flags);
mm_unlock_irq(heap, flags);
/* Test if the delayed is empty */

View file

@ -469,6 +469,10 @@ static void idle_group_initialize(void)
nxtask_joininit(tcb);
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
spin_lock_init(&tcb->mutex_lock);
#endif
#ifdef CONFIG_SMP
/* Create a stack for all CPU IDLE threads (except CPU0 which already
* has a stack).

View file

@ -39,14 +39,6 @@
* Public Data
****************************************************************************/
/* Used for access control */
volatile spinlock_t g_irq_spin = SP_UNLOCKED;
/* Handles nested calls to spin_lock_irqsave and spin_unlock_irqrestore */
volatile uint8_t g_irq_spin_count[CONFIG_SMP_NCPUS];
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -46,8 +46,7 @@ if(NOT CONFIG_DISABLE_PTHREAD)
pthread_setschedprio.c)
if(NOT CONFIG_PTHREAD_MUTEX_UNSAFE)
list(APPEND SRCS pthread_mutex.c pthread_mutexconsistent.c
pthread_mutexinconsistent.c)
list(APPEND SRCS pthread_mutex.c pthread_mutexconsistent.c)
endif()
if(CONFIG_SMP)

View file

@ -32,7 +32,7 @@ CSRCS += pthread_completejoin.c pthread_findjoininfo.c
CSRCS += pthread_release.c pthread_setschedprio.c
ifneq ($(CONFIG_PTHREAD_MUTEX_UNSAFE),y)
CSRCS += pthread_mutex.c pthread_mutexconsistent.c pthread_mutexinconsistent.c
CSRCS += pthread_mutex.c pthread_mutexconsistent.c
endif
ifeq ($(CONFIG_SMP),y)

View file

@ -222,6 +222,10 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
nxtask_joininit(&ptcb->cmn);
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
spin_lock_init(&ptcb->cmn.mutex_lock);
#endif
/* Bind the parent's group to the new TCB (we have not yet joined the
* group).
*/

View file

@ -65,10 +65,10 @@ static void pthread_mutex_add(FAR struct pthread_mutex_s *mutex)
/* Add the mutex to the list of mutexes held by this pthread */
flags = enter_critical_section();
flags = spin_lock_irqsave(&rtcb->mutex_lock);
mutex->flink = rtcb->mhead;
rtcb->mhead = mutex;
leave_critical_section(flags);
spin_unlock_irqrestore(&rtcb->mutex_lock, flags);
}
/****************************************************************************
@ -92,7 +92,7 @@ static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex)
FAR struct pthread_mutex_s *prev;
irqstate_t flags;
flags = enter_critical_section();
flags = spin_lock_irqsave(&rtcb->mutex_lock);
/* Remove the mutex from the list of mutexes held by this task */
@ -118,7 +118,7 @@ static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex)
}
mutex->flink = NULL;
leave_critical_section(flags);
spin_unlock_irqrestore(&rtcb->mutex_lock, flags);
}
/****************************************************************************
@ -346,3 +346,49 @@ int pthread_mutex_restorelock(FAR struct pthread_mutex_s *mutex,
return ret;
}
/****************************************************************************
* Name: pthread_mutex_inconsistent
*
* Description:
* This function is called when a pthread is terminated via either
* pthread_exit() or pthread_cancel(). It will check for any mutexes
* held by exitting thread. It will mark them as inconsistent and
* then wake up the highest priority waiter for the mutex. That
* instance of pthread_mutex_lock() will then return EOWNERDEAD.
*
* Input Parameters:
* tcb -- a reference to the TCB of the exitting pthread.
*
* Returned Value:
* None.
*
****************************************************************************/
void pthread_mutex_inconsistent(FAR struct tcb_s *tcb)
{
FAR struct pthread_mutex_s *mutex;
irqstate_t flags;
DEBUGASSERT(tcb != NULL);
flags = spin_lock_irqsave(&tcb->mutex_lock);
/* Remove and process each mutex held by this task */
while (tcb->mhead != NULL)
{
/* Remove the mutex from the TCB list */
mutex = tcb->mhead;
tcb->mhead = mutex->flink;
mutex->flink = NULL;
/* Mark the mutex as INCONSISTENT and wake up any waiting thread */
mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT;
mutex_unlock(&mutex->mutex);
}
spin_unlock_irqrestore(&tcb->mutex_lock, flags);
}

View file

@ -1,89 +0,0 @@
/****************************************************************************
* sched/pthread/pthread_mutexinconsistent.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 <pthread.h>
#include <sched.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/sched.h>
#include <nuttx/semaphore.h>
#include "pthread/pthread.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pthread_mutex_inconsistent
*
* Description:
* This function is called when a pthread is terminated via either
* pthread_exit() or pthread_cancel(). It will check for any mutexes
* held by exitting thread. It will mark them as inconsistent and
* then wake up the highest priority waiter for the mutex. That
* instance of pthread_mutex_lock() will then return EOWNERDEAD.
*
* Input Parameters:
* tcb -- a reference to the TCB of the exitting pthread.
*
* Returned Value:
* None.
*
****************************************************************************/
void pthread_mutex_inconsistent(FAR struct tcb_s *tcb)
{
FAR struct pthread_mutex_s *mutex;
irqstate_t flags;
DEBUGASSERT(tcb != NULL);
sched_lock();
/* Remove and process each mutex held by this task */
while (tcb->mhead != NULL)
{
/* Remove the mutex from the TCB list */
flags = enter_critical_section();
mutex = tcb->mhead;
tcb->mhead = mutex->flink;
mutex->flink = NULL;
leave_critical_section(flags);
/* Mark the mutex as INCONSISTENT and wake up any waiting thread */
mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT;
mutex_unlock(&mutex->mutex);
}
sched_unlock();
}

View file

@ -164,6 +164,10 @@ FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr)
nxtask_joininit(&child->cmn);
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
spin_lock_init(&child->cmn.mutex_lock);
#endif
/* Allocate a new task group with the same privileges as the parent */
ret = group_initialize(child, ttype);

View file

@ -126,6 +126,10 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
nxtask_joininit(&tcb->cmn);
#endif
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
spin_lock_init(&tcb->cmn.mutex_lock);
#endif
/* Duplicate the parent tasks environment */
ret = env_dup(tcb->cmn.group, envp);

View file

@ -617,6 +617,17 @@ static const char *g_white_content_list[] =
"unzGetCurrentFileInfo64",
"unzGoToNextFile",
"unzGoToFirstFile",
/* Ref:
* apps/netutils/telnetc/telnetc.c
*/
"deflateInit",
"deflateEnd",
"inflateInit",
"inflateEnd",
"zError",
NULL
};