Files
6CAR/drivers/include/camera/sdrv-cam-os-def.h
2026-04-18 09:16:58 +08:00

354 lines
10 KiB
C

/**
* @file sdrv-cam-os-def.h
*
* @brief Semidrive platform camera driver and hal adaptive to operation system header file.
*
* @copyright Copyright (C) 2021, Semidrive Communications Inc.
*
* This file is licensed under a dual GPLv2 or X11 license.
*
*/
#ifndef __SDRV_CAM_OS_DEF_H__
#define __SDRV_CAM_OS_DEF_H__
#include <assert.h>
#include <bits.h>
#include <board.h>
#include <debug.h>
#include <errno.h>
#include <lib/list.h>
#include <reg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include "FreeRTOS.h"
#include "armv7-r/atomic.h"
#include "armv7-r/cache.h"
#include "armv7-r/irq.h"
#include "config.h"
#include "event_groups.h"
#include "i2c_cfg.h"
#include "irq.h"
#include "irq_num.h"
#include "queue.h"
#include "regs_base.h"
#include "sdrv_gpio.h"
#include "sdrv_i2c.h"
#include "task.h"
// define from cmsis_os2.h
#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default).
#define osFlagsWaitAll 0x00000001U ///< Wait for all flags.
#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for.
#define MAX_BITS_EVENT_GROUPS 24U
#define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
#define csi_err(x...) ssdk_printf(SSDK_ERR, x)
#define csi_warn(x...) ssdk_printf(SSDK_WARNING, x)
#define csi_info(x...) ssdk_printf(SSDK_NOTICE, x)
#define csi_debug(x...) ssdk_printf(SSDK_DEBUG, x)
#define cam_err(x...) ssdk_printf(SSDK_ERR, x)
#define cam_info(x...) ssdk_printf(SSDK_NOTICE, x)
#define cam_debug(x...) ssdk_printf(SSDK_DEBUG, x)
#define sensor_err(x...) ssdk_printf(SSDK_ERR, x)
#define sensor_info(x...) ssdk_printf(SSDK_NOTICE, x)
#define sensor_debug(x...) ssdk_printf(SSDK_DEBUG, x)
#define deser_crit(x...) ssdk_printf(SSDK_CRIT, x)
#define deser_err(x...) ssdk_printf(SSDK_ERR, x)
#define deser_info(x...) ssdk_printf(SSDK_NOTICE, x)
#define deser_debug(x...) ssdk_printf(SSDK_DEBUG, x)
#define HAL_LOGE(x...) ssdk_printf(SSDK_ERR, x)
#define HAL_LOGI(x...) ssdk_printf(SSDK_NOTICE, x)
#define HAL_LOGD(x...) ssdk_printf(SSDK_DEBUG, x)
typedef enum {
osOK = 0, ///< Operation completed successfully.
osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits.
osErrorTimeout = -2, ///< Operation not completed within the timeout period.
osErrorResource = -3, ///< Resource not available.
osErrorParameter = -4, ///< Parameter error.
osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osStatus_t;
#ifndef reg_addr_t
typedef paddr_t reg_addr_t;
#endif
#ifndef dma_addr_t
typedef paddr_t dma_addr_t;
#endif
#define CSI_COMPLETE_EVENT_FLAG 1u
typedef void *osEventFlagsId_t;
typedef struct {
osEventFlagsId_t event;
} completion_t;
static inline uint32_t reg_read(reg_addr_t base, uint32_t addr)
{
return readl(base + addr);
}
static inline void reg_write(reg_addr_t base, uint32_t addr, uint32_t val)
{
writel(val, base + addr);
}
//#define usleep_range(min, max) vTaskDelay(min >> 1)
static inline void usleep_range(uint32_t min, uint32_t max)
{
max = max / 2 + min / 2;
if (max < 1000)
max = 1000;
max /= 1000;
vTaskDelay(max);
}
#define mdelay(ms) vTaskDelay(ms)
#define udelay(us) vTaskDelay((us + 999) / 1000)
static inline uint32_t IRQ_Context(void)
{
uint32_t irq;
BaseType_t state;
irq = 0U;
if (arch_in_irq_mode()) {
/* Called from interrupt context */
irq = 1U;
} else {
/* Get FreeRTOS scheduler state */
state = xTaskGetSchedulerState();
if (state != taskSCHEDULER_NOT_STARTED) {
/* Scheduler was started */
if (arch_irq_is_masked()) {
/* Interrupts are masked */
irq = 1U;
}
}
}
/* Return context, 0: thread context, 1: IRQ context */
return (irq);
}
inline static void completion_init(completion_t *com)
{
// com->event = osEventFlagsNew(NULL);
EventGroupHandle_t hEventGroup;
hEventGroup = NULL;
if (IRQ_Context() == 0U) { // thread context
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
hEventGroup = xEventGroupCreate();
#endif
}
/* Return event flags ID */
com->event = ((osEventFlagsId_t)hEventGroup);
}
inline static void completion_destroy(completion_t *com)
{
// osEventFlagsDelete(com->event);
#ifndef USE_FreeRTOS_HEAP_1
if (IRQ_Context() == 0U && com->event != NULL) {
vEventGroupDelete(com->event);
}
return;
#else
return;
#endif
}
inline static int wait_completion_timeout(completion_t *com, uint32_t timeout)
{
// ret = osEventFlagsWait(com->event, CSI_COMPLETE_EVENT_FLAG,
// osFlagsWaitAny, timeout);
uint32_t flags = CSI_COMPLETE_EVENT_FLAG;
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)com->event;
BaseType_t wait_all;
BaseType_t exit_clr;
uint32_t rflags;
if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
rflags = (uint32_t)osErrorParameter;
} else if (IRQ_Context() != 0U) {
rflags = (uint32_t)osErrorISR;
} else {
wait_all = pdFAIL;
exit_clr = pdTRUE;
rflags = xEventGroupWaitBits(hEventGroup, (EventBits_t)flags, exit_clr,
wait_all, (TickType_t)timeout);
if ((flags & rflags) == 0U) {
if (timeout > 0U) {
rflags = (uint32_t)osErrorTimeout;
} else {
rflags = (uint32_t)osErrorResource;
}
}
}
return (int)rflags;
}
inline static void completion_done(completion_t *com)
{
// osEventFlagsSet(com->event, CSI_COMPLETE_EVENT_FLAG);
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)com->event;
BaseType_t yield;
if ((hEventGroup == NULL) ||
((CSI_COMPLETE_EVENT_FLAG & EVENT_FLAGS_INVALID_BITS) != 0U)) {
; // rflags = (uint32_t)osErrorParameter;
} else if (IRQ_Context() != 0U) {
#if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
(void)yield;
/* Enable timers and xTimerPendFunctionCall function to support
* osEventFlagsSet from ISR */
// rflags = (uint32_t)osErrorResource;
#else
yield = pdFALSE;
if (xEventGroupSetBitsFromISR(hEventGroup,
(EventBits_t)CSI_COMPLETE_EVENT_FLAG,
&yield) == pdFAIL) {
; // rflags = (uint32_t)osErrorResource;
} else {
// rflags = CSI_COMPLETE_EVENT_FLAG;
portYIELD_FROM_ISR(yield);
}
#endif
} else {
xEventGroupSetBits(hEventGroup, (EventBits_t)CSI_COMPLETE_EVENT_FLAG);
}
/* Return event flags after setting */
// return (rflags);
}
// single R5, no need spin lock
typedef void *spinlock_t;
#define spin_lock_init(a) (*a = NULL)
#define spin_lock_irqsave(spinlock, flags) \
do { \
irq_state_t state = arch_irq_save(); \
flags = state; \
} while (0)
#define spin_unlock_irqrestore(spinlock, flags) \
do { \
irq_state_t state = (irq_state_t)flags; \
arch_irq_restore(state); \
} while (0)
// gpio_set: set output, and set level to gpio
static inline void gpio_set(void *dev, unsigned int pin, bool level)
{
(void)dev;
sdrv_gpio_set_pin_direction(pin, GPIO_DIR_OUT);
sdrv_gpio_set_pin_output_level(pin, level);
}
// I2C interface:
static inline void wait_idle_and_set_busy(void *ctrl)
{
sdrv_i2cdrv_bus_stat_t bus_stat;
int i = 10;
bus_stat = sdrv_i2c_get_bus_stat(ctrl);
while (bus_stat == SDRV_I2CDRV_BUS_BUSY && i-- > 0) {
vTaskDelay(2);
bus_stat = sdrv_i2c_get_bus_stat(ctrl);
}
sdrv_i2c_set_bus_stat(ctrl, SDRV_I2CDRV_BUS_BUSY);
}
inline static int i2c_write(void *adap, uint8_t addr, uint8_t *buf, int count)
{
int ret;
wait_idle_and_set_busy(adap);
sdrv_i2c_write(adap, addr, buf, count, 1000, true);
ret = sdrv_i2c_get_trans_stat(adap);
sdrv_i2c_set_bus_stat(adap, SDRV_I2CDRV_BUS_IDLE);
return (ret == SDRV_I2CDRV_TRANS_OK) ? 0 : -1;
}
inline static int i2c_read(void *adap, uint8_t addr, uint8_t *buf, int count)
{
int ret;
wait_idle_and_set_busy(adap);
sdrv_i2c_read(adap, addr, buf, count, 1000, true);
ret = sdrv_i2c_get_trans_stat(adap);
sdrv_i2c_set_bus_stat(adap, SDRV_I2CDRV_BUS_IDLE);
return (ret == SDRV_I2CDRV_TRANS_OK) ? 0 : -1;
}
inline static int i2c_write_read(void *adap, uint8_t addr, uint8_t *reg,
int regc, uint8_t *buf, int bufc)
{
int ret;
wait_idle_and_set_busy(adap);
sdrv_i2c_write(adap, addr, reg, regc, 1000, true);
ret = sdrv_i2c_get_trans_stat(adap);
if (ret == SDRV_I2CDRV_TRANS_OK) {
sdrv_i2c_read(adap, addr, buf, bufc, 1000, true);
ret = sdrv_i2c_get_trans_stat(adap);
}
sdrv_i2c_set_bus_stat(adap, SDRV_I2CDRV_BUS_IDLE);
return (ret == SDRV_I2CDRV_TRANS_OK) ? 0 : -1;
}
// mutext
typedef QueueHandle_t osMutexId_t;
static inline osMutexId_t osMutexNew(void *p)
{
(void)p;
return xQueueCreateMutex(queueQUEUE_TYPE_MUTEX);
}
static inline void osMutexDelete(void *p)
{
if (p)
vQueueDelete(p);
}
static inline void osMutexAcquire(void *p, int t)
{
(void)p;
(void)t;
xQueueTakeMutexRecursive(p, t);
}
static inline void osMutexRelease(void *p)
{
(void)p;
xQueueGiveMutexRecursive(p);
}
#endif /* __SDRV_CAM_OS_DEF_H__ */