/** * @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 #include #include #include #include #include #include #include #include #include #include #include #include #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 { sys_OK = 0, sys_Error = -1, sys_ErrorTimeout = -2, sys_ErrorResource = -3, sys_ErrorParameter = -4, sys_ErrorNoMemory = -5, sys_ErrorISR = -6, sys_StatusReserved = 0x7FFFFFFF } 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)sys_ErrorParameter; } else if (IRQ_Context() != 0U) { rflags = (uint32_t)sys_ErrorISR; } 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)sys_ErrorTimeout; } else { rflags = (uint32_t)sys_ErrorResource; } } } 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)sys_ErrorParameter; } 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)sys_ErrorResource; #else yield = pdFALSE; if (xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)CSI_COMPLETE_EVENT_FLAG, &yield) == pdFAIL) { ; // rflags = (uint32_t)sys_ErrorResource; } 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__ */