mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 01:38:36 +08:00
Compare commits
27 commits
247f89d1b8
...
93af2c0480
Author | SHA1 | Date | |
---|---|---|---|
|
93af2c0480 | ||
|
63c8de5f03 | ||
|
43797ea6cc | ||
|
aa0aecbd80 | ||
|
39780fdae1 | ||
|
ee2f3df2ff | ||
|
ff488133c9 | ||
|
48846954d8 | ||
|
657247bda8 | ||
|
be40c01ddd | ||
|
91c71ed00a | ||
|
1d8ce18d7f | ||
|
558fe83f6d | ||
|
7c7a64c84c | ||
|
f2a88059e7 | ||
|
4bd8d9eac7 | ||
|
69ee240b45 | ||
|
b9837bed08 | ||
|
d84ba608a1 | ||
|
58c95f5d85 | ||
|
f179cb81b5 | ||
|
575c608be8 | ||
|
af6147fb2c | ||
|
b2735751d1 | ||
|
6dbdfb3cd5 | ||
|
f2934935d0 | ||
|
9783c88425 |
58 changed files with 7361 additions and 418 deletions
|
@ -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>
|
||||
|
@ -727,6 +727,7 @@ else()
|
|||
OUTPUT nuttx.rel
|
||||
COMMAND
|
||||
${CMAKE_C_COMPILER} ARGS -r $<$<BOOL:${CONFIG_SIM_M32}>:-m32>
|
||||
$<$<BOOL:${CONFIG_HOST_LINUX}>:-Wl,-z,noexecstack>
|
||||
$<TARGET_OBJECTS:sim_head> $<$<NOT:$<BOOL:${APPLE}>>:-Wl,--start-group>
|
||||
${nuttx_libs_paths} $<$<NOT:$<BOOL:${APPLE}>>:-Wl,--end-group> -o
|
||||
nuttx.rel
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
@ -83,6 +84,7 @@ struct up_dev_s
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ else ifeq ($(CONFIG_ARCH_CORTEXA9),y)
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARM_THUMB),y)
|
||||
LLVM_ARCHTYPE := thumbv7
|
||||
LLVM_ARCHTYPE := thumbv7a
|
||||
else
|
||||
LLVM_ARCHTYPE := armv7a
|
||||
endif
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "barriers.h"
|
||||
|
@ -225,6 +226,12 @@
|
|||
|
||||
#define PL310_GULP_SIZE 4096
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static spinlock_t g_l2cc_lock = SP_UNLOCKED;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -262,6 +269,66 @@ static void pl310_flush_all(void)
|
|||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_disable_nolock
|
||||
*
|
||||
* Description:
|
||||
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_disable_nolock(void)
|
||||
{
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
pl310_flush_all();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_invalidate_all_nolock
|
||||
*
|
||||
* Description:
|
||||
* Invalidate all ways using the Invalidate Way Register (IWR).
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_invalidate_all_nolock(void)
|
||||
{
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -457,18 +524,18 @@ void l2cc_enable(void)
|
|||
|
||||
/* Invalidate and enable the cache (must be disabled to do this!) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0)
|
||||
{
|
||||
l2cc_disable();
|
||||
l2cc_disable_nolock();
|
||||
}
|
||||
|
||||
l2cc_invalidate_all();
|
||||
l2cc_invalidate_all_nolock();
|
||||
putreg32(L2CC_CR_L2CEN, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -489,17 +556,11 @@ void l2cc_disable(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
pl310_flush_all();
|
||||
l2cc_disable_nolock();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -525,9 +586,9 @@ void l2cc_sync(void)
|
|||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -548,27 +609,11 @@ void l2cc_invalidate_all(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Invalidate all ways */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
l2cc_invalidate_all_nolock();
|
||||
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Check if the start address is aligned with a cacheline */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
if ((startaddr & PL310_CACHE_LINE_MASK) != 0)
|
||||
{
|
||||
/* No.. align down and flush the cache line by writing the address to
|
||||
|
@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
putreg32(endaddr, L2CC_CIPALR);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
|
||||
/* Loop, invalidated the address range by cache line. Interrupts are re-
|
||||
* enabled momentarily every PL310_GULP_SIZE bytes.
|
||||
|
@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and invalidate the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Invalidate the cache line by writing the address to the
|
||||
|
@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -690,7 +735,7 @@ void l2cc_clean_all(void)
|
|||
* Ways Register (CWR).
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(PL310_WAY_MASK, L2CC_CWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
@ -702,7 +747,7 @@ void l2cc_clean_all(void)
|
|||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and clean the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Clean the cache line by writing the address to the Clean
|
||||
|
@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -806,9 +851,9 @@ void l2cc_flush_all(void)
|
|||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
pl310_flush_all();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Disable interrupts and flush the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Flush the cache line by writing the address to the Clean
|
||||
|
@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV7A_L2CC_PL310 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "barriers.h"
|
||||
|
@ -225,6 +226,12 @@
|
|||
|
||||
#define PL310_GULP_SIZE 4096
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static volatile spinlock_t g_l2cc_lock = SP_UNLOCKED;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -262,6 +269,66 @@ static void pl310_flush_all(void)
|
|||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_disable_nolock
|
||||
*
|
||||
* Description:
|
||||
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_disable_nolock(void)
|
||||
{
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
pl310_flush_all();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_invalidate_all_nolock
|
||||
*
|
||||
* Description:
|
||||
* Invalidate all ways using the Invalidate Way Register (IWR).
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_invalidate_all_nolock(void)
|
||||
{
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -457,18 +524,18 @@ void l2cc_enable(void)
|
|||
|
||||
/* Invalidate and enable the cache (must be disabled to do this!) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0)
|
||||
{
|
||||
l2cc_disable();
|
||||
l2cc_disable_nolock();
|
||||
}
|
||||
|
||||
l2cc_invalidate_all();
|
||||
l2cc_invalidate_all_nolock();
|
||||
putreg32(L2CC_CR_L2CEN, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -489,17 +556,11 @@ void l2cc_disable(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
pl310_flush_all();
|
||||
l2cc_disable_nolock();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -525,9 +586,9 @@ void l2cc_sync(void)
|
|||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -548,27 +609,11 @@ void l2cc_invalidate_all(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Invalidate all ways */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
l2cc_invalidate_all_nolock();
|
||||
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Check if the start address is aligned with a cacheline */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
if ((startaddr & PL310_CACHE_LINE_MASK) != 0)
|
||||
{
|
||||
/* No.. align down and flush the cache line by writing the address to
|
||||
|
@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
putreg32(endaddr, L2CC_CIPALR);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
|
||||
/* Loop, invalidated the address range by cache line. Interrupts are re-
|
||||
* enabled momentarily every PL310_GULP_SIZE bytes.
|
||||
|
@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and invalidate the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Invalidate the cache line by writing the address to the
|
||||
|
@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -690,7 +735,7 @@ void l2cc_clean_all(void)
|
|||
* Ways Register (CWR).
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(PL310_WAY_MASK, L2CC_CWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
@ -702,7 +747,7 @@ void l2cc_clean_all(void)
|
|||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and clean the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Clean the cache line by writing the address to the Clean
|
||||
|
@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -806,9 +851,9 @@ void l2cc_flush_all(void)
|
|||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
pl310_flush_all();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Disable interrupts and flush the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Flush the cache line by writing the address to the Clean
|
||||
|
@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV7R_L2CC_PL310 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "barriers.h"
|
||||
|
@ -225,6 +226,12 @@
|
|||
|
||||
#define PL310_GULP_SIZE 4096
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static volatile spinlock_t g_l2cc_lock = SP_UNLOCKED;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -262,6 +269,66 @@ static void pl310_flush_all(void)
|
|||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_disable_nolock
|
||||
*
|
||||
* Description:
|
||||
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_disable_nolock(void)
|
||||
{
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
pl310_flush_all();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_invalidate_all_nolock
|
||||
*
|
||||
* Description:
|
||||
* Invalidate all ways using the Invalidate Way Register (IWR).
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_invalidate_all_nolock(void)
|
||||
{
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -457,18 +524,18 @@ void l2cc_enable(void)
|
|||
|
||||
/* Invalidate and enable the cache (must be disabled to do this!) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0)
|
||||
{
|
||||
l2cc_disable();
|
||||
l2cc_disable_nolock();
|
||||
}
|
||||
|
||||
l2cc_invalidate_all();
|
||||
l2cc_invalidate_all_nolock();
|
||||
putreg32(L2CC_CR_L2CEN, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -489,17 +556,11 @@ void l2cc_disable(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
pl310_flush_all();
|
||||
l2cc_disable_nolock();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -525,9 +586,9 @@ void l2cc_sync(void)
|
|||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -548,27 +609,11 @@ void l2cc_invalidate_all(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Invalidate all ways */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
l2cc_invalidate_all_nolock();
|
||||
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Check if the start address is aligned with a cacheline */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
if ((startaddr & PL310_CACHE_LINE_MASK) != 0)
|
||||
{
|
||||
/* No.. align down and flush the cache line by writing the address to
|
||||
|
@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
putreg32(endaddr, L2CC_CIPALR);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
|
||||
/* Loop, invalidated the address range by cache line. Interrupts are re-
|
||||
* enabled momentarily every PL310_GULP_SIZE bytes.
|
||||
|
@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and invalidate the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Invalidate the cache line by writing the address to the
|
||||
|
@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -690,7 +735,7 @@ void l2cc_clean_all(void)
|
|||
* Ways Register (CWR).
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(PL310_WAY_MASK, L2CC_CWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
@ -702,7 +747,7 @@ void l2cc_clean_all(void)
|
|||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and clean the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Clean the cache line by writing the address to the Clean
|
||||
|
@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -806,9 +851,9 @@ void l2cc_flush_all(void)
|
|||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
pl310_flush_all();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Disable interrupts and flush the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Flush the cache line by writing the address to the Clean
|
||||
|
@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV8R_L2CC_PL310 */
|
||||
|
|
|
@ -21,3 +21,8 @@
|
|||
# ##############################################################################
|
||||
|
||||
add_compile_options(-mcpu=cortex-m0 -mthumb -mfloat-abi=soft)
|
||||
|
||||
# LLVM Configuration
|
||||
set(LLVM_ARCHTYPE thumbv6m)
|
||||
set(LLVM_ABITYPE eabi)
|
||||
set(LLVM_CPUTYPE cortex-m0)
|
||||
|
|
|
@ -24,24 +24,43 @@ set(PLATFORM_FLAGS)
|
|||
|
||||
if(CONFIG_ARCH_CORTEXA5)
|
||||
list(APPEND PLATFORM_FLAGS -mcpu=cortex-a5)
|
||||
set(LLVM_CPUTYPE cortex-a5)
|
||||
elseif(CONFIG_ARCH_CORTEXA7)
|
||||
list(APPEND PLATFORM_FLAGS -mcpu=cortex-a7)
|
||||
set(LLVM_CPUTYPE cortex-a7)
|
||||
elseif(CONFIG_ARCH_CORTEXA8)
|
||||
list(APPEND PLATFORM_FLAGS -mcpu=cortex-a8)
|
||||
set(LLVM_CPUTYPE cortex-a8)
|
||||
elseif(CONFIG_ARCH_CORTEXA9)
|
||||
list(APPEND PLATFORM_FLAGS -mcpu=cortex-a9)
|
||||
set(LLVM_CPUTYPE cortex-a9)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARM_THUMB)
|
||||
set(LLVM_ARCHTYPE thumbv7a)
|
||||
else()
|
||||
set(LLVM_ARCHTYPE armv7-a)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_FPU)
|
||||
set(LLVM_ABITYPE eabihf)
|
||||
else()
|
||||
set(LLVM_ABITYPE eabi)
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_ARM_DPFPU32)
|
||||
set(ARCHFPUD16 -d16)
|
||||
endif()
|
||||
|
||||
# Cortex-A5 | -mfpu=vfpv4-fp16 | -mfpu=vfpv4-d16-fp16 | -mfpu=neon-fp16
|
||||
# Cortex-A7 | -mfpu=vfpv4 | -mfpu=vfpv4-d16 | -mfpu=neon-vfpv4
|
||||
# Cortex-A8 | -mfpu=vfpv3 | | -mfpu=neon (alias for
|
||||
# neon-vfpv3) Cortex-A9 | -mfpu=vfpv3-fp16 | -mfpu=vfpv3-d16-fp16 |
|
||||
# -mfpu=neon-fp16 Cortex-A15 | -mfpu=vfpv4 | |
|
||||
# -mfpu=neon-vfpv4
|
||||
# ~~~
|
||||
# | Cortex | FPU Option 1 | FPU Option 2 | FPU Option 3 |
|
||||
# |--------|--------------------|------------------------|-----------------------|
|
||||
# | A5 | -mfpu=vfpv4-fp16 | -mfpu=vfpv4-d16-fp16 | -mfpu=neon-fp16 |
|
||||
# | A7 | -mfpu=vfpv4 | -mfpu=vfpv4-d16 | -mfpu=neon-vfpv4 |
|
||||
# | A8 | -mfpu=vfpv3 | | -mfpu=neon (alias for neon-vfpv3) |
|
||||
# | A9 | -mfpu=vfpv3-fp16 | -mfpu=vfpv3-d16-fp16 | -mfpu=neon-fp16 |
|
||||
# | A15 | -mfpu=vfpv4 | | -mfpu=neon-vfpv4 |
|
||||
# ~~~
|
||||
|
||||
if(CONFIG_ARCH_FPU)
|
||||
if(CONFIG_ARM_FPU_ABI_SOFT)
|
||||
|
|
|
@ -38,4 +38,23 @@ else() # gcc
|
|||
set(TOOLCHAIN_ARCH_FILE armv7-m_gcc)
|
||||
endif()
|
||||
|
||||
# LLVM Configuration
|
||||
if(CONFIG_ARCH_CORTEXM3)
|
||||
set(LLVM_ARCHTYPE thumbv7m)
|
||||
set(LLVM_CPUTYPE cortex-m3)
|
||||
else()
|
||||
set(LLVM_ARCHTYPE thumbv7em)
|
||||
if(CONFIG_ARCH_CORTEXM4)
|
||||
set(LLVM_CPUTYPE cortex-m4)
|
||||
elseif(CONFIG_ARCH_CORTEXM7)
|
||||
set(LLVM_CPUTYPE cortex-m7)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_FPU)
|
||||
set(LLVM_ABITYPE eabihf)
|
||||
else()
|
||||
set(LLVM_ABITYPE eabi)
|
||||
endif()
|
||||
|
||||
include(${TOOLCHAIN_ARCH_FILE})
|
||||
|
|
|
@ -22,6 +22,31 @@
|
|||
|
||||
set(PLATFORM_FLAGS)
|
||||
|
||||
# LLVM Configuration
|
||||
if(CONFIG_ARCH_CORTEXM23)
|
||||
set(LLVM_ARCHTYPE thumbv8m.base)
|
||||
set(LLVM_CPUTYPE cortex-m23)
|
||||
elseif(CONFIG_ARCH_CORTEXM33)
|
||||
set(LLVM_ARCHTYPE thumbv8m.main)
|
||||
set(LLVM_CPUTYPE cortex-m33)
|
||||
elseif(CONFIG_ARCH_CORTEXM35P)
|
||||
set(LLVM_ARCHTYPE thumbv8m.main)
|
||||
set(LLVM_CPUTYPE cortex-m35p)
|
||||
elseif(CONFIG_ARCH_CORTEXM55)
|
||||
set(LLVM_ARCHTYPE thumbv8.1m.main)
|
||||
set(LLVM_CPUTYPE cortex-m55)
|
||||
elseif(CONFIG_ARCH_CORTEXM85)
|
||||
set(LLVM_ARCHTYPE thumbv8.1m.main)
|
||||
set(LLVM_CPUTYPE cortex-m85)
|
||||
endif()
|
||||
|
||||
# Set ABI type based on FPU configuration
|
||||
if(CONFIG_ARCH_FPU)
|
||||
set(LLVM_ABITYPE eabihf)
|
||||
else()
|
||||
set(LLVM_ABITYPE eabi)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARM_DSP)
|
||||
set(EXTCPUFLAGS +dsp)
|
||||
endif()
|
||||
|
|
|
@ -546,8 +546,10 @@ ifeq ($(CONFIG_PIC),y)
|
|||
# Generate an executable elf, need to ignore undefined symbols
|
||||
LDELFFLAGS += --unresolved-symbols=ignore-in-object-files --emit-relocs
|
||||
else
|
||||
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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/****************************************************************************
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -43,7 +43,7 @@ CHIP_CSRCS += stm32_idle.c
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_TIMER),y)
|
||||
CHIP_CSRCS += stm32h5_tim_lowerhalf.c
|
||||
CHIP_CSRCS += stm32_tim_lowerhalf.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_STM32H5_I2C),y)
|
||||
|
@ -66,6 +66,10 @@ ifeq ($(CONFIG_STM32H5_QSPI1),y)
|
|||
CHIP_CSRCS += stm32_qspi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_STM32H5_TIM),y)
|
||||
CHIP_CSRCS += stm32_tim.c
|
||||
endif
|
||||
|
||||
# Required chip type specific files
|
||||
|
||||
ifeq ($(CONFIG_STM32H5_STM32H5XXXX),y)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
@ -1369,3 +1918,4 @@ struct adc_dev_s *stm32h5_adc_initialize(int intf,
|
|||
}
|
||||
#endif /* CONFIG_STM32H5_ADC1 || CONFIG_STM32H5_ADC2 */
|
||||
#endif /* CONFIG_ADC */
|
||||
|
||||
|
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
1553
arch/arm/src/stm32h5/stm32_tim.c
Normal file
1553
arch/arm/src/stm32h5/stm32_tim.c
Normal file
File diff suppressed because it is too large
Load diff
223
arch/arm/src/stm32h5/stm32_tim.h
Normal file
223
arch/arm/src/stm32h5/stm32_tim.h
Normal file
|
@ -0,0 +1,223 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/stm32h5/stm32_tim.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 __ARCH_ARM_SRC_STM32H5_STM32_TIM_H
|
||||
#define __ARCH_ARM_SRC_STM32H5_STM32_TIM_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "hardware/stm32_tim.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Helpers ******************************************************************/
|
||||
|
||||
#define STM32_TIM_ENABLE(d) ((d)->ops->enable(d))
|
||||
#define STM32_TIM_DISABLE(d) ((d)->ops->disable(d))
|
||||
#define STM32_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode))
|
||||
#define STM32_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq))
|
||||
#define STM32_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
|
||||
#define STM32_TIM_GETCOUNTER(d) ((d)->ops->getcounter(d))
|
||||
#define STM32_TIM_SETCOUNTER(d,c) ((d)->ops->setcounter(d,c))
|
||||
#define STM32_TIM_GETWIDTH(d) ((d)->ops->getwidth(d))
|
||||
#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode))
|
||||
#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp))
|
||||
#define STM32_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch))
|
||||
#define STM32_TIM_SETISR(d,hnd,arg,s) ((d)->ops->setisr(d,hnd,arg,s))
|
||||
#define STM32_TIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s))
|
||||
#define STM32_TIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s))
|
||||
#define STM32_TIM_ACKINT(d,s) ((d)->ops->ackint(d,s))
|
||||
#define STM32_TIM_CHECKINT(d,s) ((d)->ops->checkint(d,s))
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* TIM Device Structure */
|
||||
|
||||
struct stm32_tim_dev_s
|
||||
{
|
||||
struct stm32_tim_ops_s *ops;
|
||||
};
|
||||
|
||||
/* TIM Modes of Operation */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STM32_TIM_MODE_UNUSED = -1,
|
||||
|
||||
/* One of the following */
|
||||
|
||||
STM32_TIM_MODE_MASK = 0x0310,
|
||||
STM32_TIM_MODE_DISABLED = 0x0000,
|
||||
STM32_TIM_MODE_UP = 0x0100,
|
||||
STM32_TIM_MODE_DOWN = 0x0110,
|
||||
STM32_TIM_MODE_UPDOWN = 0x0200,
|
||||
STM32_TIM_MODE_PULSE = 0x0300,
|
||||
|
||||
/* One of the following */
|
||||
|
||||
STM32_TIM_MODE_CK_INT = 0x0000,
|
||||
#if 0
|
||||
STM32_TIM_MODE_CK_INT_TRIG = 0x0400,
|
||||
STM32_TIM_MODE_CK_EXT = 0x0800,
|
||||
STM32_TIM_MODE_CK_EXT_TRIG = 0x0c00,
|
||||
|
||||
/* Clock sources, OR'ed with CK_EXT */
|
||||
|
||||
STM32_TIM_MODE_CK_CHINVALID = 0x0000,
|
||||
STM32_TIM_MODE_CK_CH1 = 0x0001,
|
||||
STM32_TIM_MODE_CK_CH2 = 0x0002,
|
||||
STM32_TIM_MODE_CK_CH3 = 0x0003,
|
||||
STM32_TIM_MODE_CK_CH4 = 0x0004
|
||||
#endif
|
||||
|
||||
/* Todo: external trigger block */
|
||||
} stm32_tim_mode_t;
|
||||
|
||||
/* TIM Channel Modes */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STM32_TIM_CH_DISABLED = 0x00,
|
||||
|
||||
/* Common configuration */
|
||||
|
||||
STM32_TIM_CH_POLARITY_POS = 0x00,
|
||||
STM32_TIM_CH_POLARITY_NEG = 0x01,
|
||||
|
||||
/* MODES: */
|
||||
|
||||
STM32_TIM_CH_MODE_MASK = 0x0e,
|
||||
|
||||
/* Output Compare Modes */
|
||||
|
||||
/* Enable standard PWM mode, active high when counter < compare */
|
||||
|
||||
STM32_TIM_CH_OUTPWM = 0x04,
|
||||
|
||||
/* Toggle TIM_CHx output on UEV */
|
||||
|
||||
STM32_TIM_CH_OUTTOGGLE = 0x08,
|
||||
#if 0
|
||||
STM32_TIM_CH_OUTCOMPARE = 0x06,
|
||||
|
||||
/* TODO other modes ... as PWM capture, ENCODER and Hall Sensor */
|
||||
|
||||
STM32_TIM_CH_INCAPTURE = 0x10,
|
||||
STM32_TIM_CH_INPWM = 0x20
|
||||
STM32_TIM_CH_DRIVE_OC - open collector mode
|
||||
#endif
|
||||
} stm32_tim_channel_t;
|
||||
|
||||
/* TIM Operations */
|
||||
|
||||
struct stm32_tim_ops_s
|
||||
{
|
||||
/* Basic Timers */
|
||||
|
||||
void (*enable)(struct stm32_tim_dev_s *dev);
|
||||
void (*disable)(struct stm32_tim_dev_s *dev);
|
||||
int (*setmode)(struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode);
|
||||
int (*setclock)(struct stm32_tim_dev_s *dev, uint32_t freq);
|
||||
void (*setperiod)(struct stm32_tim_dev_s *dev, uint32_t period);
|
||||
uint32_t (*getcounter)(struct stm32_tim_dev_s *dev);
|
||||
void (*setcounter)(struct stm32_tim_dev_s *dev, uint32_t count);
|
||||
|
||||
/* General and Advanced Timers Adds */
|
||||
|
||||
int (*getwidth)(struct stm32_tim_dev_s *dev);
|
||||
int (*setchannel)(struct stm32_tim_dev_s *dev, uint8_t channel,
|
||||
stm32_tim_channel_t mode);
|
||||
int (*setcompare)(struct stm32_tim_dev_s *dev, uint8_t channel,
|
||||
uint32_t compare);
|
||||
int (*getcapture)(struct stm32_tim_dev_s *dev, uint8_t channel);
|
||||
|
||||
/* Timer interrupts */
|
||||
|
||||
int (*setisr)(struct stm32_tim_dev_s *dev, xcpt_t handler, void *arg,
|
||||
int source);
|
||||
void (*enableint)(struct stm32_tim_dev_s *dev, int source);
|
||||
void (*disableint)(struct stm32_tim_dev_s *dev, int source);
|
||||
void (*ackint)(struct stm32_tim_dev_s *dev, int source);
|
||||
int (*checkint)(struct stm32_tim_dev_s *dev, int source);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Power-up timer and get its structure */
|
||||
|
||||
struct stm32_tim_dev_s *stm32_tim_init(int timer);
|
||||
|
||||
/* Power-down timer, mark it as unused */
|
||||
|
||||
int stm32_tim_deinit(struct stm32_tim_dev_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_timer_initialize
|
||||
*
|
||||
* Description:
|
||||
* Bind the configuration timer to a timer lower half instance and
|
||||
* register the timer drivers at 'devpath'
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the timer device. This should be of the
|
||||
* form /dev/timer0
|
||||
* timer - the timer number.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned
|
||||
* to indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
int stm32_timer_initialize(const char *devpath, int timer);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_ARM_SRC_STM32H5_STM32_TIM_H */
|
586
arch/arm/src/stm32h5/stm32_tim_lowerhalf.c
Normal file
586
arch/arm/src/stm32h5/stm32_tim_lowerhalf.c
Normal file
|
@ -0,0 +1,586 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/stm32h5/stm32_tim_lowerhalf.c
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* SPDX-FileCopyrightText: 2023 Max Kriegleder. All rights reserved.
|
||||
* SPDX-FileCopyrightText: 2015 Wail Khemir. All rights reserved.
|
||||
* SPDX-FileCopyrightText: 2015 Omni Hoverboards Inc. All rights reserved.
|
||||
* SPDX-FileContributor: Wail Khemir <khemirwail@gmail.com>
|
||||
* SPDX-FileContributor: Paul Alexander Patience <paul-a.patience@polymtl.ca>
|
||||
* SPDX-FileContributor: Max Kriegleder <max.kriegleder@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/timers/timer.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "stm32_tim.h"
|
||||
|
||||
#if defined(CONFIG_TIMER) && \
|
||||
(defined(CONFIG_STM32H5_TIM1) || defined(CONFIG_STM32H5_TIM2) || \
|
||||
defined(CONFIG_STM32H5_TIM3) || defined(CONFIG_STM32H5_TIM4) || \
|
||||
defined(CONFIG_STM32H5_TIM5) || defined(CONFIG_STM32H5_TIM6) || \
|
||||
defined(CONFIG_STM32H5_TIM7) || defined(CONFIG_STM32H5_TIM8) || \
|
||||
defined(CONFIG_STM32H5_TIM12) || defined(CONFIG_STM32H5_TIM13) || \
|
||||
defined(CONFIG_STM32H5_TIM14) || defined(CONFIG_STM32H5_TIM15) || \
|
||||
defined(CONFIG_STM32H5_TIM16) || defined(CONFIG_STM32H5_TIM17))
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define STM32_TIM1_RES 16
|
||||
#define STM32_TIM2_RES 32
|
||||
#define STM32_TIM3_RES 16
|
||||
#define STM32_TIM4_RES 16
|
||||
#define STM32_TIM5_RES 32
|
||||
#define STM32_TIM6_RES 16
|
||||
#define STM32_TIM7_RES 16
|
||||
#define STM32_TIM8_RES 16
|
||||
#define STM32_TIM12_RES 16
|
||||
#define STM32_TIM13_RES 16
|
||||
#define STM32_TIM14_RES 16
|
||||
#define STM32_TIM15_RES 16
|
||||
#define STM32_TIM16_RES 16
|
||||
#define STM32_TIM17_RES 16
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure provides the private representation of the "lower-half"
|
||||
* driver state structure. This structure must be cast-compatible with the
|
||||
* timer_lowerhalf_s structure.
|
||||
*/
|
||||
|
||||
struct stm32_lowerhalf_s
|
||||
{
|
||||
const struct timer_ops_s *ops; /* Lower half operations */
|
||||
struct stm32_tim_dev_s *tim; /* stm32 timer driver */
|
||||
tccb_t callback; /* Current user interrupt callback */
|
||||
void *arg; /* Argument passed to upper half callback */
|
||||
bool started; /* True: Timer has been started */
|
||||
const uint8_t resolution; /* Number of bits in the timer (16 or 32 bits) */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_timer_handler(int irq, void * context, void * arg);
|
||||
|
||||
/* "Lower half" driver methods **********************************************/
|
||||
|
||||
static int stm32_start(struct timer_lowerhalf_s *lower);
|
||||
static int stm32_stop(struct timer_lowerhalf_s *lower);
|
||||
static int stm32_settimeout(struct timer_lowerhalf_s *lower,
|
||||
uint32_t timeout);
|
||||
static void stm32_setcallback(struct timer_lowerhalf_s *lower,
|
||||
tccb_t callback, void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* "Lower half" driver methods */
|
||||
|
||||
static const struct timer_ops_s g_timer_ops =
|
||||
{
|
||||
.start = stm32_start,
|
||||
.stop = stm32_stop,
|
||||
.getstatus = NULL,
|
||||
.settimeout = stm32_settimeout,
|
||||
.setcallback = stm32_setcallback,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM1
|
||||
static struct stm32_lowerhalf_s g_tim1_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM1_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM2
|
||||
static struct stm32_lowerhalf_s g_tim2_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM2_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM3
|
||||
static struct stm32_lowerhalf_s g_tim3_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM3_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM4
|
||||
static struct stm32_lowerhalf_s g_tim4_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM4_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM5
|
||||
static struct stm32_lowerhalf_s g_tim5_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM5_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM6
|
||||
static struct stm32_lowerhalf_s g_tim6_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM6_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM7
|
||||
static struct stm32_lowerhalf_s g_tim7_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM7_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM8
|
||||
static struct stm32_lowerhalf_s g_tim8_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM8_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM12
|
||||
static struct stm32_lowerhalf_s g_tim12_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM12_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM13
|
||||
static struct stm32_lowerhalf_s g_tim13_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM13_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM14
|
||||
static struct stm32_lowerhalf_s g_tim14_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM14_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM15
|
||||
static struct stm32_lowerhalf_s g_tim15_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM15_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM16
|
||||
static struct stm32_lowerhalf_s g_tim16_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM16_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM17
|
||||
static struct stm32_lowerhalf_s g_tim17_lowerhalf =
|
||||
{
|
||||
.ops = &g_timer_ops,
|
||||
.resolution = STM32_TIM17_RES,
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_timer_handler
|
||||
*
|
||||
* Description:
|
||||
* timer interrupt handler
|
||||
*
|
||||
* Input Parameters:
|
||||
*
|
||||
* Returned Value:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_timer_handler(int irq, void * context, void * arg)
|
||||
{
|
||||
struct stm32_lowerhalf_s *lower = (struct stm32_lowerhalf_s *) arg;
|
||||
uint32_t next_interval_us = 0;
|
||||
|
||||
STM32_TIM_ACKINT(lower->tim, ATIM_DIER_UIE);
|
||||
|
||||
if (lower->callback(&next_interval_us, lower->arg))
|
||||
{
|
||||
if (next_interval_us > 0)
|
||||
{
|
||||
STM32_TIM_SETPERIOD(lower->tim, next_interval_us);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stm32_stop((struct timer_lowerhalf_s *)lower);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_start
|
||||
*
|
||||
* Description:
|
||||
* Start the timer, resetting the time to the current timeout,
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_start(struct timer_lowerhalf_s *lower)
|
||||
{
|
||||
struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower;
|
||||
|
||||
if (!priv->started)
|
||||
{
|
||||
STM32_TIM_SETMODE(priv->tim, STM32_TIM_MODE_UP);
|
||||
|
||||
if (priv->callback != NULL)
|
||||
{
|
||||
STM32_TIM_SETISR(priv->tim, stm32_timer_handler, priv, 0);
|
||||
STM32_TIM_ENABLEINT(priv->tim, ATIM_DIER_UIE);
|
||||
}
|
||||
|
||||
priv->started = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Return EBUSY to indicate that the timer was already running */
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_stop
|
||||
*
|
||||
* Description:
|
||||
* Stop the timer
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_stop(struct timer_lowerhalf_s *lower)
|
||||
{
|
||||
struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower;
|
||||
|
||||
if (priv->started)
|
||||
{
|
||||
STM32_TIM_SETMODE(priv->tim, STM32_TIM_MODE_DISABLED);
|
||||
STM32_TIM_DISABLEINT(priv->tim, ATIM_DIER_UIE);
|
||||
STM32_TIM_SETISR(priv->tim, NULL, NULL, 0);
|
||||
priv->started = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Return ENODEV to indicate that the timer was not running */
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_settimeout
|
||||
*
|
||||
* Description:
|
||||
* Set a new timeout value (and reset the timer)
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
* timeout - The new timeout value in microseconds.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_settimeout(struct timer_lowerhalf_s *lower,
|
||||
uint32_t timeout)
|
||||
{
|
||||
struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower;
|
||||
uint64_t maxtimeout;
|
||||
|
||||
if (priv->started)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
maxtimeout = (1 << priv->resolution) - 1;
|
||||
if (timeout > maxtimeout)
|
||||
{
|
||||
uint64_t freq = (maxtimeout * 1000000) / timeout;
|
||||
STM32_TIM_SETCLOCK(priv->tim, freq);
|
||||
STM32_TIM_SETPERIOD(priv->tim, maxtimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
STM32_TIM_SETCLOCK(priv->tim, 1000000);
|
||||
STM32_TIM_SETPERIOD(priv->tim, timeout);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_setcallback
|
||||
*
|
||||
* Description:
|
||||
* Call this user provided timeout callback.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
* callback - The new timer expiration function pointer. If this
|
||||
* function pointer is NULL, then the reset-on-expiration
|
||||
* behavior is restored,
|
||||
* arg - Argument that will be provided in the callback
|
||||
*
|
||||
* Returned Value:
|
||||
* The previous timer expiration function pointer or NULL is there was
|
||||
* no previous function pointer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_setcallback(struct timer_lowerhalf_s *lower,
|
||||
tccb_t callback, void *arg)
|
||||
{
|
||||
struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower;
|
||||
|
||||
irqstate_t flags = enter_critical_section();
|
||||
|
||||
/* Save the new callback */
|
||||
|
||||
priv->callback = callback;
|
||||
priv->arg = arg;
|
||||
|
||||
if (callback != NULL && priv->started)
|
||||
{
|
||||
STM32_TIM_SETISR(priv->tim, stm32_timer_handler, priv, 0);
|
||||
STM32_TIM_ENABLEINT(priv->tim, ATIM_DIER_UIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
STM32_TIM_DISABLEINT(priv->tim, ATIM_DIER_UIE);
|
||||
STM32_TIM_SETISR(priv->tim, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_timer_initialize
|
||||
*
|
||||
* Description:
|
||||
* Bind the configuration timer to a timer lower half instance and
|
||||
* register the timer drivers at 'devpath'
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the timer device. This should be of the
|
||||
* form /dev/timer0
|
||||
* timer - the timer's number.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned
|
||||
* to indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int stm32_timer_initialize(const char *devpath, int timer)
|
||||
{
|
||||
struct stm32_lowerhalf_s *lower;
|
||||
|
||||
switch (timer)
|
||||
{
|
||||
#ifdef CONFIG_STM32H5_TIM1
|
||||
case 1:
|
||||
lower = &g_tim1_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM2
|
||||
case 2:
|
||||
lower = &g_tim2_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM3
|
||||
case 3:
|
||||
lower = &g_tim3_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM4
|
||||
case 4:
|
||||
lower = &g_tim4_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM5
|
||||
case 5:
|
||||
lower = &g_tim5_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM6
|
||||
case 6:
|
||||
lower = &g_tim6_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM7
|
||||
case 7:
|
||||
lower = &g_tim7_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM8
|
||||
case 8:
|
||||
lower = &g_tim8_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM12
|
||||
case 12:
|
||||
lower = &g_tim12_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM13
|
||||
case 13:
|
||||
lower = &g_tim13_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32H5_TIM14
|
||||
case 14:
|
||||
lower = &g_tim14_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM15
|
||||
case 15:
|
||||
lower = &g_tim15_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM16
|
||||
case 16:
|
||||
lower = &g_tim16_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM17
|
||||
case 17:
|
||||
lower = &g_tim17_lowerhalf;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Initialize the elements of lower half state structure */
|
||||
|
||||
lower->started = false;
|
||||
lower->callback = NULL;
|
||||
lower->tim = stm32_tim_init(timer);
|
||||
|
||||
if (lower->tim == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Register the timer driver as /dev/timerX. The returned value from
|
||||
* timer_register is a handle that could be used with timer_unregister().
|
||||
* REVISIT: The returned handle is discard here.
|
||||
*/
|
||||
|
||||
void *drvr = timer_register(devpath,
|
||||
(struct timer_lowerhalf_s *)lower);
|
||||
if (drvr == NULL)
|
||||
{
|
||||
/* The actual cause of the failure may have been a failure to allocate
|
||||
* perhaps a failure to register the timer driver (such as if the
|
||||
* 'depath' were not unique). We know here but we return EEXIST to
|
||||
* indicate the failure (implying the non-unique devpath).
|
||||
*/
|
||||
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TIMER */
|
|
@ -355,60 +355,6 @@ static inline void rcc_enableapb1l(void)
|
|||
|
||||
regval = getreg32(STM32_RCC_APB1LENR);
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM2
|
||||
/* Bit 0: TIM2 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM2EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM3
|
||||
/* Bit 1: TIM3 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM3EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM4
|
||||
/* Bit 2: TIM4 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM4EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM5
|
||||
/* Bit 3: TIM5 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM5EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM6
|
||||
/* Bit 4: TIM6 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM6EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM7
|
||||
/* Bit 5: TIM7 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM7EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM12
|
||||
/* Bit 5: TIM12 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM12EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM13
|
||||
/* Bit 5: TIM13 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM13EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM14
|
||||
/* Bit 5: TIM14 clock enable */
|
||||
|
||||
regval |= RCC_APB1LENR_TIM14EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_SPI2
|
||||
/* Bit 14: SPI2 clock enable */
|
||||
|
||||
|
@ -588,48 +534,18 @@ static inline void rcc_enableapb2(void)
|
|||
|
||||
regval = getreg32(STM32_RCC_APB2ENR);
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM1
|
||||
/* TIM1 clock enable */
|
||||
|
||||
regval |= RCC_APB2ENR_TIM1EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_SPI1
|
||||
/* SPI1 clock enable */
|
||||
|
||||
regval |= RCC_APB2ENR_SPI1EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM8
|
||||
/* TIM8 clock enable */
|
||||
|
||||
regval |= RCC_APB2ENR_TIM8EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_USART1
|
||||
/* USART1 clock enable */
|
||||
|
||||
regval |= RCC_APB2ENR_USART1EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM15
|
||||
/* TIM15 clock enable */
|
||||
|
||||
regval |= RCC_APB2ENR_TIM15EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM16
|
||||
/* TIM16 clock enable */
|
||||
|
||||
regval |= RCC_APB2ENR_TIM16EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_TIM17
|
||||
/* TIM17 clock enable */
|
||||
|
||||
regval |= RCC_APB2ENR_TIM17EN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32H5_SPI4
|
||||
/* SPI4 clock enable */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -200,3 +200,7 @@ else()
|
|||
add_link_options(-Wl,--gc-sections)
|
||||
add_link_options(-Wl,-Ttext-segment=0x40000000)
|
||||
endif()
|
||||
|
||||
if(CONFIG_HOST_LINUX)
|
||||
add_link_options(-Wl,-z,noexecstack)
|
||||
endif()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -484,7 +484,7 @@ int esp_gpio_init(void)
|
|||
/* Configure the pins that will be used as output */
|
||||
|
||||
esp_gpio_matrix_out(g_gpiooutputs[i], SIG_GPIO_OUT_IDX, 0, 0);
|
||||
esp_configgpio(g_gpiooutputs[i], OUTPUT_FUNCTION_1 | INPUT_FUNCTION_1);
|
||||
esp_configgpio(g_gpiooutputs[i], OUTPUT_FUNCTION_2 | INPUT_FUNCTION_2);
|
||||
esp_gpiowrite(g_gpiooutputs[i], 0);
|
||||
|
||||
pincount++;
|
||||
|
@ -503,7 +503,7 @@ int esp_gpio_init(void)
|
|||
|
||||
/* Configure the pins that will be used as interrupt input */
|
||||
|
||||
esp_configgpio(g_gpiointinputs[i], INPUT_FUNCTION_1 | PULLDOWN);
|
||||
esp_configgpio(g_gpiointinputs[i], INPUT_FUNCTION_2 | PULLDOWN);
|
||||
|
||||
pincount++;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ CONFIG_START_YEAR=2021
|
|||
CONFIG_SYMTAB_ORDEREDBYNAME=y
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_SYSTEM_POPEN=y
|
||||
CONFIG_SYSTEM_POPEN_STACKSIZE=3072
|
||||
CONFIG_TESTING_GETPRIME=y
|
||||
CONFIG_TESTING_MM=y
|
||||
CONFIG_TESTING_OSTEST=y
|
||||
|
|
|
@ -439,6 +439,14 @@ menuconfig WATCHDOG_AUTOMONITOR
|
|||
|
||||
if WATCHDOG_AUTOMONITOR
|
||||
|
||||
config WATCHDOG_TIMEOUT_NOTIFIER
|
||||
bool "Enable watchdog timeout notifier"
|
||||
default n
|
||||
---help---
|
||||
The watchdog timeout notifier chain mechanism supports users registering
|
||||
custom callback functions, which will be called when the watchdog timer
|
||||
managed by Auto-monitor times out.
|
||||
|
||||
choice
|
||||
prompt "Auto-monitor keepalive by"
|
||||
default WATCHDOG_AUTOMONITOR_BY_WDOG
|
||||
|
|
|
@ -71,6 +71,20 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_ONESHOT)
|
||||
# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_ONESHOT
|
||||
#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER)
|
||||
# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_TIMER
|
||||
#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG)
|
||||
# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_WDOG
|
||||
#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER)
|
||||
# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_WORKER
|
||||
#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE)
|
||||
# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_CAPTURE
|
||||
#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE)
|
||||
# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_IDLE
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Definitions
|
||||
****************************************************************************/
|
||||
|
@ -135,6 +149,10 @@ static const struct file_operations g_wdogops =
|
|||
wdog_ioctl, /* ioctl */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER
|
||||
static ATOMIC_NOTIFIER_HEAD(g_watchdog_notifier_list);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -699,6 +717,55 @@ static int wdog_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER
|
||||
/****************************************************************************
|
||||
* Name: watchdog_notifier_chain_register
|
||||
*
|
||||
* Description:
|
||||
* Add notifier to the watchdog notifier chain
|
||||
*
|
||||
* Input Parameters:
|
||||
* nb - New entry in notifier chain
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void watchdog_notifier_chain_register(FAR struct notifier_block *nb)
|
||||
{
|
||||
atomic_notifier_chain_register(&g_watchdog_notifier_list, nb);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: watchdog_notifier_chain_unregister
|
||||
*
|
||||
* Description:
|
||||
* Remove notifier from the watchdog notifier chain
|
||||
*
|
||||
* Input Parameters:
|
||||
* nb - Entry to remove from notifier chain
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void watchdog_notifier_chain_unregister(FAR struct notifier_block *nb)
|
||||
{
|
||||
atomic_notifier_chain_unregister(&g_watchdog_notifier_list, nb);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: watchdog_automonitor_timeout
|
||||
*
|
||||
* Description:
|
||||
* This function can be called in the watchdog timeout interrupt handler.
|
||||
* If so, callbacks on the watchdog timer notify chain are called when the
|
||||
* watchdog timer times out.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void watchdog_automonitor_timeout(void)
|
||||
{
|
||||
atomic_notifier_call_chain(&g_watchdog_notifier_list, action, data);
|
||||
}
|
||||
#endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: watchdog_register
|
||||
*
|
||||
|
|
|
@ -2618,6 +2618,13 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev)
|
|||
#endif
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (dev->disconnected)
|
||||
{
|
||||
leave_critical_section(flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
priv->ispolling = true;
|
||||
EP_POLL(ep);
|
||||
priv->ispolling = false;
|
||||
|
@ -3012,6 +3019,10 @@ void cdcacm_uninitialize(FAR struct usbdevclass_driver_s *classdev)
|
|||
char devname[CDCACM_DEVNAME_SIZE];
|
||||
int ret;
|
||||
|
||||
/* Disconnect in case we are connected */
|
||||
|
||||
cdcacm_disconnect(classdev, priv->usbdev);
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
usbdev_unregister(&drvr->drvr);
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -617,22 +586,8 @@ irqstate_t spin_lock_irqsave(FAR volatile spinlock_t *lock)
|
|||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <nuttx/compiler.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/notifier.h>
|
||||
|
||||
#ifdef CONFIG_WATCHDOG
|
||||
|
||||
|
@ -88,6 +89,35 @@
|
|||
#define WDFLAGS_CAPTURE (1 << 2) /* 1=Call the user function when the
|
||||
* watchdog timer expires */
|
||||
|
||||
/* Keepalive Actions ********************************************************/
|
||||
|
||||
/* According to the keepalive action specified by the Auto-monitor, callback
|
||||
* functions registered on the watchdog notifier chain may take corresponding
|
||||
* actions.
|
||||
*
|
||||
* These are detected and handled by the "upper half" watchdog timer driver.
|
||||
*
|
||||
* WATCHDOG_KEEPALIVE_BY_ONESHOT - The watchdog timer is keepalive by
|
||||
* oneshot timer.
|
||||
* WATCHDOG_KEEPALIVE_BY_TIMER - The watchdog timer is keepalive by
|
||||
* timer.
|
||||
* WATCHDOG_KEEPALIVE_BY_WDOG - The watchdog timer is keepalive by
|
||||
* wdog.
|
||||
* WATCHDOG_KEEPALIVE_BY_WORKER - The watchdog timer is keepalive by
|
||||
* worker queue.
|
||||
* WATCHDOG_KEEPALIVE_BY_CAPTURE - The watchdog timer is keepalive by
|
||||
* capture.
|
||||
* WATCHDOG_KEEPALIVE_BY_IDLE - The watchdog timer is keepalive by
|
||||
* idle task.
|
||||
*/
|
||||
|
||||
#define WATCHDOG_KEEPALIVE_BY_ONESHOT 0
|
||||
#define WATCHDOG_KEEPALIVE_BY_TIMER 1
|
||||
#define WATCHDOG_KEEPALIVE_BY_WDOG 2
|
||||
#define WATCHDOG_KEEPALIVE_BY_WORKER 3
|
||||
#define WATCHDOG_KEEPALIVE_BY_CAPTURE 4
|
||||
#define WATCHDOG_KEEPALIVE_BY_IDLE 5
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
@ -197,6 +227,47 @@ extern "C"
|
|||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER
|
||||
/****************************************************************************
|
||||
* Name: watchdog_notifier_chain_register
|
||||
*
|
||||
* Description:
|
||||
* Add notifier to the watchdog notifier chain
|
||||
*
|
||||
* Input Parameters:
|
||||
* nb - New entry in notifier chain
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void watchdog_notifier_chain_register(FAR struct notifier_block *nb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: watchdog_notifier_chain_unregister
|
||||
*
|
||||
* Description:
|
||||
* Remove notifier from the watchdog notifier chain
|
||||
*
|
||||
* Input Parameters:
|
||||
* nb - Entry to remove from notifier chain
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void watchdog_notifier_chain_unregister(FAR struct notifier_block *nb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: watchdog_automonitor_timeout
|
||||
*
|
||||
* Description:
|
||||
* This function can be called in the watchdog timeout interrupt handler.
|
||||
* If so, callbacks on the watchdog timer notify chain are called when the
|
||||
* watchdog timer times out.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void watchdog_automonitor_timeout(void);
|
||||
|
||||
#endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: watchdog_register
|
||||
*
|
||||
|
|
1
libs/libc/.gitignore
vendored
1
libs/libc/.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
/exec_symtab.c
|
||||
/modlib_symtab.c
|
||||
modlib/gnu-elf.ld
|
||||
|
|
|
@ -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
40
libs/libc/modlib/Makefile
Normal 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)
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 **********************************/
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue