mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-02-06 17:12:01 +08:00
[dm][hwspinlock] support hwspinlock
Hardware spinlock modules provide hardware assistance for synchronization and mutual exclusion between heterogeneous processors and those not operating under a single, shared operating system. Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
@@ -24,6 +24,7 @@ rsource "wlan/Kconfig"
|
||||
rsource "led/Kconfig"
|
||||
rsource "input/Kconfig"
|
||||
rsource "mailbox/Kconfig"
|
||||
rsource "hwspinlock/Kconfig"
|
||||
rsource "phye/Kconfig"
|
||||
rsource "ata/Kconfig"
|
||||
rsource "nvme/Kconfig"
|
||||
|
||||
15
components/drivers/hwspinlock/Kconfig
Normal file
15
components/drivers/hwspinlock/Kconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
menuconfig RT_USING_HWSPINLOCK
|
||||
bool "Using Hardware Spinlock device drivers"
|
||||
depends on RT_USING_DM
|
||||
depends on RT_USING_OFW
|
||||
select RT_USING_ADT
|
||||
select RT_USING_ADT_REF
|
||||
default n
|
||||
help
|
||||
Hardware spinlock modules provide hardware assistance for
|
||||
synchronization and mutual exclusion between heterogeneous processors
|
||||
and those not operating under a single, shared operating system.
|
||||
|
||||
if RT_USING_HWSPINLOCK
|
||||
osource "$(SOC_DM_HWSPINLOCK_DIR)/Kconfig"
|
||||
endif
|
||||
15
components/drivers/hwspinlock/SConscript
Normal file
15
components/drivers/hwspinlock/SConscript
Normal file
@@ -0,0 +1,15 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_USING_HWSPINLOCK']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../include']
|
||||
|
||||
src = ['hwspinlock.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
319
components/drivers/hwspinlock/hwspinlock.c
Normal file
319
components/drivers/hwspinlock/hwspinlock.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-09-23 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <cpuport.h>
|
||||
|
||||
#define DBG_TAG "rtdm.hwspinlock"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include "hwspinlock_dm.h"
|
||||
|
||||
static RT_DEFINE_SPINLOCK(hwspinlock_ops_lock);
|
||||
static rt_list_t hwspinlock_bank_nodes = RT_LIST_OBJECT_INIT(hwspinlock_bank_nodes);
|
||||
|
||||
rt_err_t rt_hwspinlock_bank_register(struct rt_hwspinlock_bank *bank)
|
||||
{
|
||||
struct rt_hwspinlock *hwlock;
|
||||
|
||||
if (!bank || !bank->ops || bank->locks_nr <= 0 || !bank->dev)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
rt_list_init(&bank->list);
|
||||
rt_ref_init(&bank->ref);
|
||||
|
||||
hwlock = &bank->locks[0];
|
||||
|
||||
for (int i = 0; i < bank->locks_nr; ++i, ++hwlock)
|
||||
{
|
||||
hwlock->bank = bank;
|
||||
hwlock->used = RT_FALSE;
|
||||
rt_spin_lock_init(&hwlock->lock);
|
||||
}
|
||||
|
||||
rt_spin_lock(&hwspinlock_ops_lock);
|
||||
rt_list_insert_after(&hwspinlock_bank_nodes, &bank->list);
|
||||
rt_spin_unlock(&hwspinlock_ops_lock);
|
||||
|
||||
rt_dm_dev_bind_fwdata(bank->dev, RT_NULL, bank);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_hwspinlock_bank_unregister(struct rt_hwspinlock_bank *bank)
|
||||
{
|
||||
rt_err_t err;
|
||||
|
||||
if (!bank)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
rt_spin_lock(&hwspinlock_ops_lock);
|
||||
|
||||
if (rt_ref_read(&bank->ref) == 1)
|
||||
{
|
||||
rt_list_remove(&bank->list);
|
||||
rt_dm_dev_unbind_fwdata(bank->dev, RT_NULL);
|
||||
|
||||
err = RT_EOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = -RT_EBUSY;
|
||||
}
|
||||
|
||||
rt_spin_unlock(&hwspinlock_ops_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
rt_err_t rt_hwspin_trylock_raw(struct rt_hwspinlock *hwlock,
|
||||
rt_ubase_t *out_irq_level)
|
||||
{
|
||||
rt_err_t err;
|
||||
|
||||
if (!hwlock)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
if (out_irq_level)
|
||||
{
|
||||
*out_irq_level = rt_spin_lock_irqsave(&hwlock->lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_spin_lock(&hwlock->lock);
|
||||
}
|
||||
|
||||
err = hwlock->bank->ops->trylock(hwlock);
|
||||
|
||||
if (err)
|
||||
{
|
||||
if (out_irq_level)
|
||||
{
|
||||
rt_spin_unlock_irqrestore(&hwlock->lock, *out_irq_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_spin_unlock(&hwlock->lock);
|
||||
}
|
||||
}
|
||||
|
||||
rt_hw_dmb();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
rt_err_t rt_hwspin_lock_timeout_raw(struct rt_hwspinlock *hwlock,
|
||||
rt_uint32_t timeout_ms, rt_ubase_t *out_irq_level)
|
||||
{
|
||||
rt_err_t err;
|
||||
rt_tick_t timeout = rt_tick_get() + rt_tick_from_millisecond(timeout_ms);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
err = rt_hwspin_trylock_raw(hwlock, out_irq_level);
|
||||
|
||||
if (err != -RT_EBUSY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout < rt_tick_get())
|
||||
{
|
||||
return -RT_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (hwlock->bank->ops->relax)
|
||||
{
|
||||
hwlock->bank->ops->relax(hwlock);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void rt_hwspin_unlock_raw(struct rt_hwspinlock *hwlock,
|
||||
rt_ubase_t *out_irq_level)
|
||||
{
|
||||
if (!hwlock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_hw_dmb();
|
||||
|
||||
hwlock->bank->ops->unlock(hwlock);
|
||||
|
||||
if (out_irq_level)
|
||||
{
|
||||
rt_spin_unlock_irqrestore(&hwlock->lock, *out_irq_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_spin_unlock(&hwlock->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static struct rt_hwspinlock *hwspinlock_get(struct rt_hwspinlock_bank *bank, int id)
|
||||
{
|
||||
struct rt_hwspinlock *hwlock = RT_NULL;
|
||||
|
||||
if (bank)
|
||||
{
|
||||
int offset = id - bank->base_id;
|
||||
|
||||
if (!bank->locks[offset].used)
|
||||
{
|
||||
hwlock = &bank->locks[offset];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_list_for_each_entry(bank, &hwspinlock_bank_nodes, list)
|
||||
{
|
||||
hwlock = rt_err_ptr(-RT_EBUSY);
|
||||
|
||||
for (int i = 0; i < bank->locks_nr; ++i)
|
||||
{
|
||||
if (!bank->locks[i].used)
|
||||
{
|
||||
hwlock = &bank->locks[i];
|
||||
goto _found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_found:
|
||||
if (!rt_is_err_or_null(hwlock))
|
||||
{
|
||||
hwlock->used = RT_TRUE;
|
||||
rt_ref_get(&hwlock->bank->ref);
|
||||
}
|
||||
|
||||
return hwlock;
|
||||
}
|
||||
|
||||
struct rt_hwspinlock *rt_hwspinlock_get(void)
|
||||
{
|
||||
struct rt_hwspinlock *lock;
|
||||
|
||||
rt_spin_lock(&hwspinlock_ops_lock);
|
||||
|
||||
lock = hwspinlock_get(RT_NULL, -1);
|
||||
|
||||
rt_spin_unlock(&hwspinlock_ops_lock);
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
struct rt_hwspinlock *rt_hwspinlock_get_by_index(struct rt_device *dev, int index)
|
||||
{
|
||||
return rt_ofw_get_hwspinlock_by_index(dev->ofw_node, index);
|
||||
}
|
||||
|
||||
struct rt_hwspinlock *rt_hwspinlock_get_by_name(struct rt_device *dev, const char *name)
|
||||
{
|
||||
return rt_ofw_get_hwspinlock_by_name(dev->ofw_node, name);
|
||||
}
|
||||
|
||||
static void hwspinlock_release(struct rt_ref *r)
|
||||
{
|
||||
struct rt_hwspinlock_bank *bank = rt_container_of(r, struct rt_hwspinlock_bank, ref);
|
||||
|
||||
LOG_E("%s is release", rt_dm_dev_get_name(bank->dev));
|
||||
(void)bank;
|
||||
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
void rt_hwspinlock_put(struct rt_hwspinlock *hwlock)
|
||||
{
|
||||
if (hwlock)
|
||||
{
|
||||
rt_spin_lock(&hwspinlock_ops_lock);
|
||||
hwlock->used = RT_FALSE;
|
||||
rt_spin_unlock(&hwspinlock_ops_lock);
|
||||
|
||||
rt_ref_put(&hwlock->bank->ref, &hwspinlock_release);
|
||||
}
|
||||
}
|
||||
|
||||
struct rt_hwspinlock *rt_ofw_get_hwspinlock_by_index(struct rt_ofw_node *np, int index)
|
||||
{
|
||||
rt_err_t err;
|
||||
struct rt_ofw_node *bank_np;
|
||||
struct rt_ofw_cell_args args;
|
||||
struct rt_hwspinlock *lock;
|
||||
struct rt_hwspinlock_bank *bank;
|
||||
|
||||
if (!np || index < 0)
|
||||
{
|
||||
return rt_err_ptr(-RT_EINVAL);
|
||||
}
|
||||
|
||||
err = rt_ofw_parse_phandle_cells(np, "hwlocks", "#hwlock-cells", index, &args);
|
||||
|
||||
if (err)
|
||||
{
|
||||
return rt_err_ptr(err);
|
||||
}
|
||||
|
||||
bank_np = args.data;
|
||||
|
||||
if (!rt_ofw_data(bank_np))
|
||||
{
|
||||
rt_platform_ofw_request(bank_np);
|
||||
}
|
||||
|
||||
rt_spin_lock(&hwspinlock_ops_lock);
|
||||
|
||||
bank = rt_ofw_data(bank_np);
|
||||
rt_ofw_node_put(bank_np);
|
||||
|
||||
if (!bank || args.args_count != 1)
|
||||
{
|
||||
lock = rt_err_ptr(-RT_ENOSYS);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock = hwspinlock_get(bank, bank->base_id + args.args[0]);
|
||||
}
|
||||
|
||||
rt_spin_unlock(&hwspinlock_ops_lock);
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
struct rt_hwspinlock *rt_ofw_get_hwspinlock_by_name(struct rt_ofw_node *np, const char *name)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (!np || !name)
|
||||
{
|
||||
return rt_err_ptr(-RT_EINVAL);
|
||||
}
|
||||
|
||||
index = rt_ofw_prop_index_of_string(np, "hwlock-names", name);
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
return rt_err_ptr(index);
|
||||
}
|
||||
|
||||
return rt_ofw_get_hwspinlock_by_index(np, index);
|
||||
}
|
||||
125
components/drivers/hwspinlock/hwspinlock_dm.h
Normal file
125
components/drivers/hwspinlock/hwspinlock_dm.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-09-23 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#ifndef __HWSPINLOCK_DM_H__
|
||||
#define __HWSPINLOCK_DM_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <drivers/misc.h>
|
||||
#include <ref.h>
|
||||
|
||||
/**
|
||||
* @brief Hardware spinlock instance
|
||||
*
|
||||
* Represents a single hardware spinlock managed by a bank. Each lock
|
||||
* maintains a local software spinlock to protect internal state and a
|
||||
* usage flag to indicate whether it has been allocated to clients.
|
||||
*/
|
||||
struct rt_hwspinlock
|
||||
{
|
||||
struct rt_hwspinlock_bank *bank;
|
||||
struct rt_spinlock lock; /**< Local software spinlock to guard structure access */
|
||||
|
||||
rt_bool_t used; /**< Indicates whether this lock is currently in use */
|
||||
void *priv; /**< Driver-specific private data */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hardware spinlock operations
|
||||
*
|
||||
* A hardware spinlock driver must provide these low-level operations.
|
||||
* trylock() performs a non-blocking acquire. relax() is called inside
|
||||
* busy-wait loops to reduce power usage or yield the bus.
|
||||
*/
|
||||
struct rt_hwspinlock_ops
|
||||
{
|
||||
/**
|
||||
* @brief Attempt to acquire the hardware spinlock (non-blocking)
|
||||
*
|
||||
* Should immediately return RT_EOK on success or -RT_EBUSY if the lock
|
||||
* is already taken by another CPU or hardware requester.
|
||||
*/
|
||||
rt_err_t (*trylock)(struct rt_hwspinlock *hwlock);
|
||||
|
||||
/**
|
||||
* @brief Release the hardware spinlock
|
||||
*/
|
||||
void (*unlock)(struct rt_hwspinlock *hwlock);
|
||||
|
||||
/**
|
||||
* @brief Relax operation called during spinning
|
||||
*
|
||||
* Typically implemented using power-saving instructions (e.g., WFE),
|
||||
* yielding the CPU, or other hardware-supported wait mechanisms.
|
||||
*/
|
||||
void (*relax)(struct rt_hwspinlock *hwlock);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hardware spinlock bank
|
||||
*
|
||||
* Represents a group of hardware spinlocks exported by the same device
|
||||
* or hardware module. A bank is registered globally so that locks can be
|
||||
* retrieved by index, name, or device tree bindings.
|
||||
*/
|
||||
struct rt_hwspinlock_bank
|
||||
{
|
||||
rt_list_t list;
|
||||
struct rt_ref ref;
|
||||
|
||||
struct rt_device *dev;
|
||||
const struct rt_hwspinlock_ops *ops;
|
||||
|
||||
int base_id; /**< Global base ID used to calculate lock identifiers */
|
||||
rt_size_t locks_nr; /**< Number of hardware spinlocks in this bank */
|
||||
|
||||
/**
|
||||
* @brief Array of hardware spinlock instances
|
||||
*
|
||||
* Implemented as a flexible array member. Memory is allocated using
|
||||
* hwspinlock_bank_alloc(), ensuring space for all lock structures.
|
||||
*/
|
||||
struct rt_hwspinlock locks[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocate a hardware spinlock bank with a given number of locks
|
||||
*
|
||||
* The allocation includes both the bank structure and the flexible array
|
||||
* of hardware spinlock objects.
|
||||
*
|
||||
* @param obj The object pointer used to store the bank
|
||||
* @param locks_nr Number of hardware spinlocks to allocate
|
||||
*
|
||||
* @return Pointer to the allocated memory or NULL on failure
|
||||
*/
|
||||
#define hwspinlock_bank_alloc(obj, locks_nr) \
|
||||
rt_calloc(1, sizeof(typeof(*obj)) + sizeof(struct rt_hwspinlock) * (locks_nr))
|
||||
|
||||
/**
|
||||
* @brief Compute the global hardware spinlock ID
|
||||
*
|
||||
* The global ID is calculated as:
|
||||
* bank->base_id + index
|
||||
* where the index is derived from the hardware spinlock's position inside
|
||||
* the bank->locks array.
|
||||
*
|
||||
* @param hwlock Pointer to a hardware spinlock
|
||||
*
|
||||
* @return The global lock identifier
|
||||
*/
|
||||
rt_inline int hwspinlock_find_id(struct rt_hwspinlock *hwlock)
|
||||
{
|
||||
return hwlock->bank->base_id + (hwlock - &hwlock->bank->locks[0]);
|
||||
}
|
||||
|
||||
#endif /* __HWSPINLOCK_DM_H__ */
|
||||
180
components/drivers/include/drivers/hwspinlock.h
Normal file
180
components/drivers/include/drivers/hwspinlock.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-09-23 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#ifndef __HWSPINLOCK_H__
|
||||
#define __HWSPINLOCK_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
struct rt_hwspinlock;
|
||||
struct rt_hwspinlock_ops;
|
||||
struct rt_hwspinlock_bank;
|
||||
|
||||
/**
|
||||
* @brief Register a hardware spinlock bank
|
||||
*
|
||||
* A bank represents a contiguous set of hardware spinlocks provided by
|
||||
* a hardware module. This API installs the bank into the system-wide list
|
||||
* so that each individual lock can be retrieved and used by clients.
|
||||
*
|
||||
* @param bank Pointer to the hardware spinlock bank
|
||||
* @return RT_EOK on success, otherwise an error code
|
||||
*/
|
||||
rt_err_t rt_hwspinlock_bank_register(struct rt_hwspinlock_bank *bank);
|
||||
|
||||
/**
|
||||
* @brief Unregister a hardware spinlock bank
|
||||
*
|
||||
* Removes the bank from the global registry. All locks under the bank
|
||||
* become unavailable. Caller must ensure no active users remain.
|
||||
*
|
||||
* @param bank Pointer to the hardware spinlock bank
|
||||
* @return RT_EOK on success, otherwise an error code
|
||||
*/
|
||||
rt_err_t rt_hwspinlock_bank_unregister(struct rt_hwspinlock_bank *bank);
|
||||
|
||||
/**
|
||||
* @brief Try to acquire a hardware spinlock (raw interface)
|
||||
*
|
||||
* The raw interface allows hardware drivers to retrieve the IRQ level
|
||||
* before acquiring the lock, enabling IRQ-safe usage scenarios.
|
||||
*
|
||||
* @param hwlock Pointer to the hardware spinlock
|
||||
* @param out_irq_level If non-NULL, returns saved IRQ level
|
||||
*
|
||||
* @return RT_EOK if lock is acquired, -RT_EBUSY if lock is held by others
|
||||
*/
|
||||
rt_err_t rt_hwspin_trylock_raw(struct rt_hwspinlock *hwlock,
|
||||
rt_ubase_t *out_irq_level);
|
||||
|
||||
/**
|
||||
* @brief Acquire a hardware spinlock with timeout (raw interface)
|
||||
*
|
||||
* Spins or relaxes according to the hardware implementation until the
|
||||
* lock becomes available or timeout expires. IRQ level handling is optional.
|
||||
*
|
||||
* @param hwlock Pointer to the hardware spinlock
|
||||
* @param timeout_ms Timeout in milliseconds
|
||||
* @param out_irq_level If non-NULL, returns saved IRQ level
|
||||
*
|
||||
* @return RT_EOK on success, -RT_ETIMEOUT if timed out
|
||||
*/
|
||||
rt_err_t rt_hwspin_lock_timeout_raw(struct rt_hwspinlock *hwlock,
|
||||
rt_uint32_t timeout_ms, rt_ubase_t *out_irq_level);
|
||||
|
||||
/**
|
||||
* @brief Release a hardware spinlock (raw interface)
|
||||
*
|
||||
* Restores IRQ state if @p out_irq_level is provided.
|
||||
*
|
||||
* @param hwlock Pointer to the hardware spinlock
|
||||
* @param out_irq_level IRQ level saved during lock operation
|
||||
*/
|
||||
void rt_hwspin_unlock_raw(struct rt_hwspinlock *hwlock,
|
||||
rt_ubase_t *out_irq_level);
|
||||
|
||||
/**
|
||||
* @brief Try to acquire a hardware spinlock (no IRQ management)
|
||||
*/
|
||||
rt_inline rt_err_t rt_hwspin_trylock(struct rt_hwspinlock *hwlock)
|
||||
{
|
||||
return rt_hwspin_trylock_raw(hwlock, RT_NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to acquire a hardware spinlock with IRQ saving
|
||||
*/
|
||||
rt_inline rt_err_t rt_hwspin_trylock_irqsave(struct rt_hwspinlock *hwlock,
|
||||
rt_ubase_t *out_irq_level)
|
||||
{
|
||||
return rt_hwspin_trylock_raw(hwlock, out_irq_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a hardware spinlock with timeout (no IRQ management)
|
||||
*/
|
||||
rt_inline rt_err_t rt_hwspin_lock_timeout(struct rt_hwspinlock *hwlock,
|
||||
rt_uint32_t timeout_ms)
|
||||
{
|
||||
return rt_hwspin_lock_timeout_raw(hwlock, timeout_ms, RT_NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a hardware spinlock with timeout and IRQ saving
|
||||
*/
|
||||
rt_inline rt_err_t rt_hwspin_lock_timeout_irqsave(struct rt_hwspinlock *hwlock,
|
||||
rt_uint32_t timeout_ms, rt_ubase_t *out_level)
|
||||
{
|
||||
return rt_hwspin_lock_timeout_raw(hwlock, timeout_ms, out_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a hardware spinlock (no IRQ management)
|
||||
*/
|
||||
rt_inline void rt_hwspin_unlock(struct rt_hwspinlock *hwlock)
|
||||
{
|
||||
rt_hwspin_unlock_raw(hwlock, RT_NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a hardware spinlock and restore IRQ level
|
||||
*/
|
||||
rt_inline void rt_hwspin_unlock_irqsave(struct rt_hwspinlock *hwlock,
|
||||
rt_ubase_t *out_level)
|
||||
{
|
||||
rt_hwspin_unlock_raw(hwlock, out_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a free hardware spinlock from any registered bank
|
||||
*
|
||||
* The returned lock must later be released via rt_hwspinlock_put().
|
||||
*
|
||||
* @return Pointer to a hardware spinlock, or NULL if none available
|
||||
*/
|
||||
struct rt_hwspinlock *rt_hwspinlock_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get hardware spinlock by index from a specific device
|
||||
*
|
||||
* @param dev Device providing hardware spinlocks
|
||||
* @param index Hardware spinlock index within device/bank
|
||||
*
|
||||
* @return Pointer to the hardware spinlock, or NULL if invalid index
|
||||
*/
|
||||
struct rt_hwspinlock *rt_hwspinlock_get_by_index(struct rt_device *dev, int index);
|
||||
|
||||
/**
|
||||
* @brief Get hardware spinlock by name from a specific device
|
||||
*
|
||||
* Names are assigned by device drivers and mapped to lock indices.
|
||||
*
|
||||
* @return Pointer to the hardware spinlock, or NULL if name not found
|
||||
*/
|
||||
struct rt_hwspinlock *rt_hwspinlock_get_by_name(struct rt_device *dev, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Release hardware spinlock reference obtained from get()
|
||||
*
|
||||
* Does not unlock the spinlock; only decreases usage count.
|
||||
*/
|
||||
void rt_hwspinlock_put(struct rt_hwspinlock *hwlock);
|
||||
|
||||
/**
|
||||
* @brief Get hardware spinlock by index from device tree node
|
||||
*/
|
||||
struct rt_hwspinlock *rt_ofw_get_hwspinlock_by_index(struct rt_ofw_node *np, int index);
|
||||
|
||||
/**
|
||||
* @brief Get hardware spinlock by name from device tree node
|
||||
*/
|
||||
struct rt_hwspinlock *rt_ofw_get_hwspinlock_by_name(struct rt_ofw_node *np, const char *name);
|
||||
|
||||
#endif /* __HWSPINLOCK_H__ */
|
||||
@@ -66,6 +66,10 @@ extern "C" {
|
||||
#include "drivers/mailbox.h"
|
||||
#endif /* RT_USING_MBOX */
|
||||
|
||||
#ifdef RT_USING_HWSPINLOCK
|
||||
#include "drivers/hwspinlock.h"
|
||||
#endif /* RT_USING_HWSPINLOCK */
|
||||
|
||||
#ifdef RT_USING_BLK
|
||||
#include "drivers/blk.h"
|
||||
#endif /* RT_USING_BLK */
|
||||
|
||||
Reference in New Issue
Block a user