diff --git a/OAT.xml b/OAT.xml index ca495a5..ad1a6ac 100644 --- a/OAT.xml +++ b/OAT.xml @@ -59,6 +59,7 @@ + diff --git a/niobeu4/liteos_m/BUILD.gn b/niobeu4/liteos_m/BUILD.gn index a3ee232..afa7037 100644 --- a/niobeu4/liteos_m/BUILD.gn +++ b/niobeu4/liteos_m/BUILD.gn @@ -19,6 +19,7 @@ if (ohos_kernel_type == "liteos_m") { "arch", "hals", "hdf_config", + "hdf_drivers", "target", "third_party_adapter", ] diff --git a/niobeu4/liteos_m/hdf_drivers/BUILD.gn b/niobeu4/liteos_m/hdf_drivers/BUILD.gn new file mode 100644 index 0000000..bda5b53 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/BUILD.gn @@ -0,0 +1,27 @@ +# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") +import("//kernel/liteos_m/liteos.gni") + +module_name = get_path_info(rebase_path("."), "name") +module_group(module_name) { + modules = [ + "gpio", + "i2c", + "pwm", + "spi", + "uart", + "watchdog", + ] +} diff --git a/niobeu4/liteos_m/hdf_drivers/gpio/BUILD.gn b/niobeu4/liteos_m/hdf_drivers/gpio/BUILD.gn new file mode 100755 index 0000000..b7ccaa4 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/gpio/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_ESPRESSIF)) { + sources += [ "gpio_esp32u4.c" ] + } + + include_dirs = [ "." ] + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/niobeu4/liteos_m/hdf_drivers/gpio/gpio_esp32u4.c b/niobeu4/liteos_m/hdf_drivers/gpio/gpio_esp32u4.c new file mode 100644 index 0000000..ee9337c --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/gpio/gpio_esp32u4.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed 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 +#include "los_task.h" +#include "los_event.h" +#include "gpio_types.h" +#include "gpio_core.h" +#include "gpio_if.h" +#include "hdf_base.h" +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#include "driver/gpio.h" + +#define HDF_GPIO_DEBUG +#define HDF_LOG_TAG "ESP32U4_HDF_GPIO" + +struct GpioSourceStr { + char *pin_index; + char *pull_mode; + char *drive_capability; +}; + +struct GpioSourceValue { + int pin_index; + int pull_mode; + int drive_capability; + int direction; +}; + +int g_pin_nums = 0; // hcs文件中定义的pin个数 + +#ifdef GPIO_NUM_MAX +#undef GPIO_NUM_MAX +#endif +struct GpioSourceValue all_gpio_config[GPIO_NUM_MAX]; // 单个GPIO配置,最大支持40个GPIO配置 + +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_GPIO_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), gpio_config) +#define HDF_GPIO_FIND_SOURCE(node, name) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + struct GpioSourceStr cur_gpio_attr = HCS_ARRAYS(HCS_PROP(node, gpio_attr)); \ + all_gpio_config[g_pin_nums].pin_index = GetPinIndexFromStr(cur_gpio_attr.pin_index); \ + all_gpio_config[g_pin_nums].pull_mode = GetPullModeFromStr(cur_gpio_attr.pull_mode); \ + all_gpio_config[g_pin_nums].drive_capability = GetDriveCapabilityFromStr(cur_gpio_attr.drive_capability); \ + HDF_LOGI("----- GPIO Index [%d] Config -----", g_pin_nums); \ + HDF_LOGI("pin_index = %s[%d]", cur_gpio_attr.pin_index, all_gpio_config[g_pin_nums].pin_index); \ + HDF_LOGI("pull_mode = %s[%d]", cur_gpio_attr.pull_mode, all_gpio_config[g_pin_nums].pull_mode); \ + HDF_LOGI("drive_capability = %s[%d]", cur_gpio_attr.drive_capability, \ + all_gpio_config[g_pin_nums].drive_capability); \ + gpio_reset_pin(all_gpio_config[g_pin_nums].pin_index); \ + gpio_set_pull_mode(all_gpio_config[g_pin_nums].pin_index, all_gpio_config[g_pin_nums].pull_mode); \ + gpio_set_drive_capability(all_gpio_config[g_pin_nums].pin_index, \ + all_gpio_config[g_pin_nums].drive_capability); \ + g_pin_nums++; \ + } \ + } while (0) + +#define DIR_PARAM_OFFSET 1 +#define ESP_INTR_FLAG_DEFAULT 0 + +static unsigned int lastTickCount = 0; +static struct GpioCntlr g_EspGpioCntlr; + +static int32_t Esp32u4GpioWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val) +{ + gpio_set_level(all_gpio_config[local].pin_index, val); + return 0; +} + +static int32_t Esp32u4GpioRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val) +{ + if (val == NULL) + return -1; + *val = gpio_get_level(all_gpio_config[local].pin_index); + return *val; +} + +#define FUNC_2 2 +static int32_t Esp32u4GpioSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir) +{ + all_gpio_config[local].direction = dir; + if (dir == GPIO_DIR_OUT) { + gpio_iomux_out(all_gpio_config[local].pin_index, FUNC_2, 0); + } + gpio_set_direction(all_gpio_config[local].pin_index, dir + DIR_PARAM_OFFSET); + return 0; +} + +static int32_t Esp32u4GpioGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir) +{ + *dir = all_gpio_config[local].direction; + return 0; +} + +#define SHAKE_COUNT 10 +static void gpio_interrupt_callback_func(VOID *arg) +{ + unsigned int tickCount = osKernelGetTickCount(); + unsigned int count = tickCount - lastTickCount; + lastTickCount = tickCount; + if (count > SHAKE_COUNT) { // 消抖 + uint16_t *gpio_num = (uint16_t *)arg; + GpioCntlrIrqCallback(&g_EspGpioCntlr, *gpio_num); // 调用用户注册的回调函数 + } + return; +} + +static int32_t Esp32u4GpioSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode) +{ + int interrupt_type = GPIO_INTR_DISABLE; + uint32_t *irq_args = (uint32_t *)malloc(sizeof(uint32_t)); + switch (mode) { + case OSAL_IRQF_TRIGGER_NONE: + interrupt_type = GPIO_INTR_DISABLE; + break; + case OSAL_IRQF_TRIGGER_RISING: + interrupt_type = GPIO_INTR_POSEDGE; + break; + case OSAL_IRQF_TRIGGER_FALLING: + interrupt_type = GPIO_INTR_NEGEDGE; + break; + case OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING: + interrupt_type = GPIO_INTR_ANYEDGE; + break; + case OSAL_IRQF_TRIGGER_HIGH: + interrupt_type = GPIO_INTR_HIGH_LEVEL; + break; + case OSAL_IRQF_TRIGGER_LOW: + interrupt_type = GPIO_INTR_LOW_LEVEL; + break; + default: + HDF_LOGE("Unknow interrupt mode! (mode = %d)", mode); + break; + } +#ifdef HDF_GPIO_DEBUG + HDF_LOGE("---> Set %d interrupt mode %d!", all_gpio_config[local].pin_index, interrupt_type); +#endif + gpio_set_intr_type(all_gpio_config[local].pin_index, interrupt_type); // 设置中断类型 + if (irq_args != NULL) { + *irq_args = (uint32_t)local; + int ret = gpio_isr_handler_add(all_gpio_config[local].pin_index, + gpio_interrupt_callback_func, irq_args); // 使能中断 + if (ret == -1) { + HDF_LOGE("GpioDevEnableIrq failed!\n"); + } + } else { + HDF_LOGE("irq_args malloc failed!"); + return HDF_FAILURE; + } + return 0; +} + +static int32_t Esp32u4GpioUnsetIrq(struct GpioCntlr *cntlr, uint16_t local) +{ + gpio_set_intr_type(all_gpio_config[local].pin_index, GPIO_INTR_DISABLE); // 设置取消中断设置 + gpio_isr_handler_remove(all_gpio_config[local].pin_index); + return 0; +} + +static int32_t Esp32u4GpioEnableIrq(struct GpioCntlr *cntlr, uint16_t local) +{ + gpio_intr_enable(all_gpio_config[local].pin_index); + return HDF_SUCCESS; +} + +static int32_t Esp32u4GpioDisableIrq(struct GpioCntlr *cntlr, uint16_t local) +{ + gpio_intr_disable(all_gpio_config[local].pin_index); + return 0; +} + +struct GpioMethod g_GpioCntlrMethod = { + .request = NULL, + .release = NULL, + .write = Esp32u4GpioWrite, + .read = Esp32u4GpioRead, + .setDir = Esp32u4GpioSetDir, + .getDir = Esp32u4GpioGetDir, + .toIrq = NULL, + .setIrq = Esp32u4GpioSetIrq, + .unsetIrq = Esp32u4GpioUnsetIrq, + .enableIrq = Esp32u4GpioEnableIrq, + .disableIrq = Esp32u4GpioDisableIrq, +}; + +static int32_t Esp32u4GpioBind(struct HdfDeviceObject *device) +{ + return HDF_SUCCESS; +} +#define NUM_10 10 +static int GetPinIndexFromStr(const char *str) +{ + if (str == NULL || strlen(str) < NUM_10) { + HDF_LOGE("pin index config is illegal!"); + return GPIO_NUM_NC; + } + + char *ptr_nun = &str[9]; + int level = strlen(ptr_nun); // 获取下标位数 + int pin_index = 0; // GPIO号 + for (int i = 0; i < level; i++) { + if (i != 0) { + pin_index = NUM_10 * pin_index; + } + int num = ptr_nun[i] - '0'; + if (num >= NUM_10) { // 字符非法 + HDF_LOGE("pin index config is illegal!"); + return GPIO_NUM_NC; + } + pin_index += num; + } + return pin_index; +} + +static int GetPullModeFromStr(const char *str) +{ + if (!strcmp(str, "GPIO_PULLUP_ONLY")) { + return GPIO_PULLUP_ONLY; + } else if (!strcmp(str, "GPIO_PULLDOWN_ONLY")) { + return GPIO_PULLDOWN_ONLY; + } else if (!strcmp(str, "GPIO_PULLUP_PULLDOWN")) { + return GPIO_PULLUP_PULLDOWN; + } + return GPIO_FLOATING; +} + +static int GetDriveCapabilityFromStr(const char *str) +{ + if (!strcmp(str, "GPIO_DRIVE_CAP_0")) { + return GPIO_DRIVE_CAP_0; + } else if (!strcmp(str, "GPIO_DRIVE_CAP_1")) { + return GPIO_DRIVE_CAP_1; + } else if (!strcmp(str, "GPIO_DRIVE_CAP_2")) { + return GPIO_DRIVE_CAP_2; + } else if (!strcmp(str, "GPIO_DRIVE_CAP_3")) { + return GPIO_DRIVE_CAP_3; + } else if (!strcmp(str, "GPIO_DRIVE_CAP_MAX")) { + return GPIO_DRIVE_CAP_MAX; + } + return GPIO_DRIVE_CAP_DEFAULT; +} + +static int32_t AttachGpioDevice(struct GpioCntlr *gpioCntlr, struct HdfDeviceObject *device) +{ + int32_t ret; + if (device == NULL) { + HDF_LOGE("%s: property is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + HCS_FOREACH_CHILD_VARGS(PLATFORM_GPIO_CONFIG, HDF_GPIO_FIND_SOURCE, device->deviceMatchAttr); + + gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + + gpioCntlr->priv = NULL; + gpioCntlr->count = g_pin_nums; + + return HDF_SUCCESS; +} + +static int32_t Esp32u4GpioInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct GpioCntlr *gpioCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = PlatformDeviceBind(&g_EspGpioCntlr.device, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: bind hdf device failed:%d", __func__, ret); + return ret; + } + + gpioCntlr = GpioCntlrFromHdfDev(device); + if (gpioCntlr == NULL) { + HDF_LOGE("GpioCntlrFromHdfDev fail\r\n"); + return HDF_DEV_ERR_NO_DEVICE_SERVICE; + } + + ret = AttachGpioDevice(gpioCntlr, device); /* GpioCntlr add GpioDevice to priv */ + if (ret != HDF_SUCCESS) { + HDF_LOGE("AttachGpioDevice fail\r\n"); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + gpioCntlr->ops = &g_GpioCntlrMethod; /* register callback */ + ret = GpioCntlrAdd(gpioCntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GpioCntlrAdd fail %d\r\n", gpioCntlr->start); + return HDF_FAILURE; + } + + HDF_LOGI("Esp32u4GpioInit success!\r\n"); + return HDF_SUCCESS; +} + +static void Esp32u4GpioRelease(struct HdfDeviceObject *device) +{ + printf("========> Func: %s Line:%d\r\n", __FUNCTION__, __LINE__); +} + +static const struct HdfDriverEntry GPIO_DriverEntry = { + .moduleVersion = 1, + .moduleName = "ESP32U4_HDF_GPIO", + .Bind = Esp32u4GpioBind, + .Init = Esp32u4GpioInit, + .Release = Esp32u4GpioRelease, +}; + +HDF_INIT(GPIO_DriverEntry); \ No newline at end of file diff --git a/niobeu4/liteos_m/hdf_drivers/i2c/BUILD.gn b/niobeu4/liteos_m/hdf_drivers/i2c/BUILD.gn new file mode 100644 index 0000000..d941beb --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/i2c/BUILD.gn @@ -0,0 +1,41 @@ +# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + + if (defined(LOSCFG_SOC_COMPANY_ESPRESSIF)) { + sources += [ "i2c_esp32u4.c" ] + } + + include_dirs = [ "." ] + if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) && + defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + deps = [ "//device/board/fnlink/shields" ] + } + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/niobeu4/liteos_m/hdf_drivers/i2c/i2c_esp32u4.c b/niobeu4/liteos_m/hdf_drivers/i2c/i2c_esp32u4.c new file mode 100644 index 0000000..763b75a --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/i2c/i2c_esp32u4.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed 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 +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "i2c_core.h" +#include "i2c_if.h" +#include "osal_mutex.h" +#include "driver/i2c.h" + +#define HDF_LOG_TAG "ESP32U4_HDF_I2C" + +struct RealI2cResource { + uint8_t port; // I2C端口号 + uint8_t mode; // I2C主从模式 0:master 1:slave + uint8_t scl_pin; // SCL引脚号 + uint8_t sda_pin; // SDA引脚号 + uint32_t speed; // I2C时钟频率 +}; + +static int32_t I2cDriverBind(struct HdfDeviceObject *device); +static int32_t I2cDriverInit(struct HdfDeviceObject *device); +static void I2cDriverRelease(struct HdfDeviceObject *device); +static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count); + +struct HdfDriverEntry gI2cHdfDriverEntry = { + .moduleVersion = 1, + .moduleName = "ESP32U4_HDF_I2C", + .Bind = I2cDriverBind, + .Init = I2cDriverInit, + .Release = I2cDriverRelease, +}; +HDF_INIT(gI2cHdfDriverEntry); + +struct I2cMethod gI2cHostMethod = { + .transfer = I2cDataTransfer, +}; + +#define I2C_FIND_CONFIG(node, name, resource) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + (resource)->mode = HCS_PROP(node, mode); \ + (resource)->port = HCS_PROP(node, port); \ + (resource)->scl_pin = HCS_PROP(node, scl_pin); \ + (resource)->sda_pin = HCS_PROP(node, sda_pin); \ + (resource)->speed = HCS_PROP(node, speed); \ + HDF_LOGE("----- I2C%d Config -----", (resource)->port); \ + HDF_LOGE("mode = %d", (resource)->mode); \ + HDF_LOGE("scl_pin = %d", (resource)->scl_pin); \ + HDF_LOGE("sda_pin = %d", (resource)->sda_pin); \ + HDF_LOGE("speed = %d", (resource)->speed); \ + result = HDF_SUCCESS; \ + } \ + } while (0) +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_I2C_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), i2c_config) +static uint32_t GetI2cDeviceResource(struct RealI2cResource *i2cResource, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + struct RealI2cResource *resource = NULL; + if (i2cResource == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("device or deviceMatchAttr is NULL\r\n"); + return HDF_ERR_INVALID_PARAM; + } + resource = i2cResource; +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, i2c_config) + HCS_FOREACH_CHILD_VARGS(PLATFORM_I2C_CONFIG, I2C_FIND_CONFIG, deviceMatchAttr, resource); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr); + } + return result; +} +#define TICKS_SECOND 1000 +unsigned int DeviceI2cWrite(int id, unsigned char addr, const unsigned char *data, unsigned int dataLen, int ack) +{ + unsigned int ret; + i2c_cmd_handle_t cmd; + if (dataLen < 1) { + return 0; + } + cmd = i2c_cmd_link_create(); + if ((ret = i2c_master_start(cmd)) != 0) { + HDF_LOGE("DeviceI2cWrite i2c_master_start failed ret = %x", ret); + return ret; + } + if ((ret = i2c_master_write_byte(cmd, addr | 0x00, ack)) != 0) { + HDF_LOGE("DeviceI2cWrite i2c_master_write_addr failed ret = %x", ret); + return ret; + } + + if ((ret = i2c_master_write(cmd, data, dataLen, 1)) != 0) { + HDF_LOGE("DeviceI2cWrite i2c_master_write failed ret = %x", ret); + return ret; + } + + if ((ret = i2c_master_stop(cmd)) != 0) { + HDF_LOGE("DeviceI2cWrite i2c_master_stop failed ret = %x", ret); + return ret; + } + if ((ret = i2c_master_cmd_begin(id, cmd, TICKS_SECOND / portTICK_RATE_MS)) != 0) { + HDF_LOGE("DeviceI2cWrite i2c_master_cmd_begin failed ret = %d", ret); + return ret; + } + i2c_cmd_link_delete(cmd); + return ret; +} + +unsigned int DeviceI2cRead(int id, unsigned char addr, const unsigned char *data, unsigned int dataLen, int ack) +{ + unsigned int ret; + i2c_cmd_handle_t cmd; + if (dataLen < 1) { + return 0; + } + cmd = i2c_cmd_link_create(); + if ((ret = i2c_master_start(cmd)) != 0) { + HDF_LOGE("DeviceI2cRead i2c_master_start failed ret = %x", ret); + return ret; + } + + if ((ret = i2c_master_write_byte(cmd, addr | 0x01, ack)) != 0) { + HDF_LOGE("DeviceI2cRead i2c_master_write_addr failed ret = %x", ret); + return ret; + } + + if (dataLen > 1) { + if ((ret = i2c_master_read(cmd, data, dataLen - 1, 0)) != 0) { + HDF_LOGE("DeviceI2cRead i2c_master_read failed ret = %x", ret); + return ret; + } + } + + if ((ret = i2c_master_read_byte(cmd, data + dataLen - 1, 1)) != 0) { + HDF_LOGE("DeviceI2cRead i2c_master_read_byte failed ret = %x", ret); + return ret; + } + + if ((ret = i2c_master_stop(cmd)) != 0) { + HDF_LOGE("DeviceI2cRead i2c_master_stop failed ret = %x", ret); + return ret; + } + + if ((ret = i2c_master_cmd_begin(id, cmd, TICKS_SECOND / portTICK_RATE_MS)) != 0) { + HDF_LOGE("DeviceI2cRead i2c_master_cmd_begin failed ret = %x", ret); + return ret; + } + i2c_cmd_link_delete(cmd); + return ret; +} +#define MODE2 2 +#define MODE4 4 +static int DeviceI2cInit(int id, int scl_pin, int sda_pin, int speed, int mode) +{ + i2c_config_t conf; + (void)memset_s(&conf, sizeof(conf), 0, sizeof(conf)); + conf.mode = (mode & 1) ? I2C_MODE_SLAVE : I2C_MODE_MASTER; + conf.sda_io_num = sda_pin; + conf.scl_io_num = scl_pin; + conf.sda_pullup_en = (mode & MODE2) ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE; + conf.scl_pullup_en = (mode & MODE4) ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE; + conf.master.clk_speed = speed; + i2c_param_config(id, &conf); + return i2c_driver_install(id, conf.mode, 0, 0, 0); +} + +static int32_t AttachI2cDevice(struct I2cCntlr *host, struct HdfDeviceObject *device) +{ + int32_t ret = HDF_FAILURE; + + if (host == NULL || device == NULL) { + HDF_LOGE("[%s]: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + struct RealI2cResource *i2cResource = (struct RealI2cResource *)OsalMemAlloc(sizeof(struct RealI2cResource)); + if (i2cResource == NULL) { + HDF_LOGE("[%s]: OsalMemAlloc RealI2cResource fail\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + memset_s(i2cResource, sizeof(struct RealI2cResource), 0, sizeof(struct RealI2cResource)); + + ret = GetI2cDeviceResource(i2cResource, device->deviceMatchAttr); + + DeviceI2cInit(i2cResource->port, i2cResource->scl_pin, i2cResource->sda_pin, + i2cResource->speed, i2cResource->mode); + + if (ret != HDF_SUCCESS) { + OsalMemFree(i2cResource); + return HDF_FAILURE; + } + + host->busId = i2cResource->port; + host->priv = i2cResource; + + return HDF_SUCCESS; +} + +static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count) +{ + unsigned int ret; + if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) { + HDF_LOGE("[%s]: I2cDataTransfer param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (count <= 0) { + HDF_LOGE("[%s]: I2cDataTransfer count err\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + struct RealI2cResource *device = (struct I2cDevice *)cntlr->priv; + if (device == NULL) { + HDF_LOGE("%s: I2cDevice is NULL\r\n", __func__); + return HDF_DEV_ERR_NO_DEVICE; + } + + for (; count > 0; --count, ++msgs) { + if ((msgs->flags) == 0) { // write + if (DeviceI2cWrite(cntlr->busId, msgs->addr, msgs->buf, msgs->len, 1)) + break; + } else if ((msgs->flags) == I2C_FLAG_READ) { // read + if (DeviceI2cRead(cntlr->busId, msgs->addr, msgs->buf, msgs->len, 1)) + break; + } + } + return count; +} + +static int32_t I2cDriverBind(struct HdfDeviceObject *device) +{ + return HDF_SUCCESS; +} + +static int32_t I2cDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret = HDF_FAILURE; + struct I2cCntlr *host = NULL; + if (device == NULL) { + HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr)); + if (host == NULL) { + HDF_LOGE("[%s]: malloc host is NULL\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr)); + host->ops = &gI2cHostMethod; + device->priv = (VOID *)host; + + ret = AttachI2cDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("[%s]: AttachI2cDevice error, ret = %d\r\n", __func__, ret); + I2cDriverRelease(device); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + ret = I2cCntlrAdd(host); + if (ret != HDF_SUCCESS) { + I2cDriverRelease(device); + return HDF_FAILURE; + } + HDF_LOGI("I2cDriverInit success!!"); + return HDF_SUCCESS; +} + +static void I2cDriverRelease(struct HdfDeviceObject *device) +{ + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return; + } + + struct I2cCntlr *i2cCntrl = device->priv; + if (i2cCntrl == NULL || i2cCntrl->priv == NULL) { + HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__); + return; + } + i2cCntrl->ops = NULL; + struct RealI2cResource *i2cDevice = (struct I2cDevice *)i2cCntrl->priv; + OsalMemFree(i2cCntrl); + + if (i2cDevice != NULL) { + OsalMemFree(i2cDevice); + } +} diff --git a/niobeu4/liteos_m/hdf_drivers/pwm/BUILD.gn b/niobeu4/liteos_m/hdf_drivers/pwm/BUILD.gn new file mode 100644 index 0000000..c98ec80 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/pwm/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_ESPRESSIF)) { + sources += [ "pwm_esp32u4.c" ] + } + + include_dirs = [ "." ] + if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) && + defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + deps = [ "//device/board/fnlink/shields" ] + } + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/niobeu4/liteos_m/hdf_drivers/pwm/pwm_esp32u4.c b/niobeu4/liteos_m/hdf_drivers/pwm/pwm_esp32u4.c new file mode 100644 index 0000000..a32240a --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/pwm/pwm_esp32u4.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed 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 +#include +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#include "hdf_device_desc.h" +#include "pwm_if.h" +#include "pwm_core.h" +#include "hdf_log.h" +#include "driver/mcpwm.h" +#include "driver/ledc.h" + +#define PERIOD_NUM 1000000000 +#define PERIOD2FREQUENCY(period) (PERIOD_NUM / (period)) +#define MCPWM_GENERATOR(cmpr) ((cmpr) % 2) +#define NUM_8192 8192 +#define GET_ESP_DUTY_CYCLE_PERCENT(duty, period) (int)(NUM_8192 * (1.0 * (duty) / (period))) + +#define UNIT_MAX_OUTPUT 6 // 每个PWM单元最大输出的个数 +#define CONFIG_2_PWM_NUM(unit, signal_port) (((unit)*UNIT_MAX_OUTPUT) + (signal_port)) +#define PWM_NUM_2_CONFIG(pwm_num, unit, signal_port) \ + do { \ + (unit) = (pwm_num) / UNIT_MAX_OUTPUT; \ + (signal_port) = (pwm_num) % UNIT_MAX_OUTPUT; \ + } while (0) + +typedef struct _PwmDeviceConfig { + int channel; + int pwm_timer; + int freq_hz; + int gpio_pin; + ledc_timer_config_t ledc_timer_config; + ledc_channel_config_t ledc_channel_config; +} PwmDeviceConfig; + +static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config); +static int32_t PwmDevOpen(struct PwmDev *pwm); +static int32_t PwmDevClose(struct PwmDev *pwm); + +struct PwmMethod g_pwmmethod = { + .setConfig = PwmDevSetConfig, + .open = PwmDevOpen, + .close = PwmDevClose, +}; + +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_PWM_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), pwm_config) + +#define PWM_FIND_CONFIG(node, name, resource) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + (resource)->channel = GetChannelFromStr(HCS_PROP(node, channel)); \ + (resource)->pwm_timer = GetTimerFromStr(HCS_PROP(node, timer)); \ + (resource)->freq_hz = HCS_PROP(node, freq_hz); \ + (resource)->gpio_pin = GetPinIndexFromStr(HCS_PROP(node, gpio_pin)); \ + (resource)->ledc_timer_config.duty_resolution = LEDC_TIMER_13_BIT; \ + (resource)->ledc_timer_config.clk_cfg = LEDC_AUTO_CLK; \ + (resource)->ledc_timer_config.timer_num = (resource)->pwm_timer; \ + (resource)->ledc_timer_config.speed_mode = LEDC_LOW_SPEED_MODE; \ + (resource)->ledc_channel_config.channel = (resource)->channel; \ + (resource)->ledc_channel_config.gpio_num = (resource)->gpio_pin; \ + (resource)->ledc_channel_config.speed_mode = LEDC_LOW_SPEED_MODE; \ + (resource)->ledc_channel_config.hpoint = 0; \ + (resource)->ledc_channel_config.timer_sel = (resource)->pwm_timer; \ + HDF_LOGD("<---------- %s ------------>", name); \ + HDF_LOGD("channel = %s [%d]", HCS_PROP(node, channel), (resource)->channel); \ + HDF_LOGD("pwm_timer = %s [%d]", HCS_PROP(node, timer), (resource)->pwm_timer); \ + HDF_LOGD("freq_hz = %dHz", (resource)->freq_hz); \ + HDF_LOGD("gpio_pin = %s [%d]", HCS_PROP(node, gpio_pin), (resource)->gpio_pin); \ + result = HDF_SUCCESS; \ + } \ + } while (0) + +#define NUM_10 10 + +static int GetPinIndexFromStr(const char *str) +{ + if (str == NULL || strlen(str) < 10) { + HDF_LOGE("pin index config is illegal!"); + return GPIO_NUM_NC; + } + + char *ptr_nun = &str[9]; + int level = strlen(ptr_nun); // 获取下标位数 + int pin_index = 0; // GPIO号 + for (int i = 0; i < level; i++) { + if (i != 0) { + pin_index = NUM_10 * pin_index; + } + int num = ptr_nun[i] - '0'; + if (num >= NUM_10) { // 字符非法 + HDF_LOGE("pin index config is illegal!"); + return GPIO_NUM_NC; + } + pin_index += num; + } + return pin_index; +} + +static int GetTimerFromStr(const char *str) +{ + if (!strcmp(str, "LEDC_TIMER_0")) { + return LEDC_TIMER_0; + } else if (!strcmp(str, "LEDC_TIMER_1")) { + return LEDC_TIMER_1; + } else if (!strcmp(str, "LEDC_TIMER_2")) { + return LEDC_TIMER_2; + } else if (!strcmp(str, "LEDC_TIMER_3")) { + return LEDC_TIMER_3; + } + HDF_LOGE("pwm_timer is illegal! must be LEDC_TIMER_0-LEDC_TIMER_03."); + return LEDC_TIMER_MAX; +} + +static int GetChannelFromStr(const char *str) +{ + if (!strcmp(str, "LEDC_CHANNEL_0")) { + return LEDC_CHANNEL_0; + } else if (!strcmp(str, "LEDC_CHANNEL_1")) { + return LEDC_CHANNEL_1; + } else if (!strcmp(str, "LEDC_CHANNEL_2")) { + return LEDC_CHANNEL_2; + } else if (!strcmp(str, "LEDC_CHANNEL_3")) { + return LEDC_CHANNEL_3; + } else if (!strcmp(str, "LEDC_CHANNEL_4")) { + return LEDC_CHANNEL_4; + } else if (!strcmp(str, "LEDC_CHANNEL_5")) { + return LEDC_CHANNEL_5; + } else if (!strcmp(str, "LEDC_CHANNEL_6")) { + return LEDC_CHANNEL_6; + } else if (!strcmp(str, "LEDC_CHANNEL_7")) { + return LEDC_CHANNEL_7; + } + HDF_LOGE("channel is illegal! must be LEDC_CHANNEL 0-7."); + return LEDC_CHANNEL_MAX; +} + +static uint32_t GetPwmDeviceResource(PwmDeviceConfig *device, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + if (device == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("%s: device or deviceMatchAttr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + HCS_FOREACH_CHILD_VARGS(PLATFORM_PWM_CONFIG, PWM_FIND_CONFIG, deviceMatchAttr, device); + + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr); + } + + return result; +} + +static int32_t AttachPwmDevice(struct PwmDev *host, struct HdfDeviceObject *device) +{ + int32_t ret; + PwmDeviceConfig *pwmDevice = NULL; + if (device == NULL || host == NULL) { + HDF_LOGE("%s: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + pwmDevice = (PwmDeviceConfig *)OsalMemAlloc(sizeof(PwmDeviceConfig)); + if (pwmDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc pwmDevice error\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + ret = GetPwmDeviceResource(pwmDevice, device->deviceMatchAttr); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(pwmDevice); + return HDF_FAILURE; + } + + PwmSetPriv(host, pwmDevice); + host->num = pwmDevice->channel; + + return HDF_SUCCESS; +} + +static int32_t PwmDriverBind(struct HdfDeviceObject *device); +static int32_t PwmDriverInit(struct HdfDeviceObject *device); +static void PwmDriverRelease(struct HdfDeviceObject *device); + +struct HdfDriverEntry g_pwmDriverEntry = { + .moduleVersion = 1, + .moduleName = "ESP32U4_HDF_PLATFORM_PWM", + .Bind = PwmDriverBind, + .Init = PwmDriverInit, + .Release = PwmDriverRelease, +}; +HDF_INIT(g_pwmDriverEntry); + +static int32_t PwmDriverBind(struct HdfDeviceObject *device) +{ + struct PwmDev *devService = NULL; + if (device == NULL) { + HDF_LOGE("hdfDevice object is null!\r\n"); + return HDF_FAILURE; + } + + devService = (struct PwmDev *)OsalMemCalloc(sizeof(struct PwmDev)); + if (devService == NULL) { + HDF_LOGE("malloc pwmDev failed\n"); + } + device->service = &devService->service; + devService->device = device; + + return HDF_SUCCESS; +} + +static int32_t PwmDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct PwmDev *host = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + host = (struct PwmDev *)device->service; + if (host == NULL) { + HDF_LOGE("%s: host is NULL\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = AttachPwmDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s:attach error\r\n", __func__); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + host->method = &g_pwmmethod; + ret = PwmDeviceAdd(device, host); + if (ret != HDF_SUCCESS) { + PwmDeviceRemove(device, host); + OsalMemFree(host->device); + OsalMemFree(host); + return HDF_DEV_ERR_NO_DEVICE; + } + + return HDF_SUCCESS; +} + +static void PwmDriverRelease(struct HdfDeviceObject *device) +{ + struct PwmDev *host = NULL; + if (device == NULL || device->service == NULL) { + HDF_LOGE("device is null\r\n"); + return; + } + host = (struct PwmDev *)device->service; + if (host != NULL && host->device != NULL) { + host->method = NULL; + OsalMemFree(host->device); + OsalMemFree(host); + host->device = NULL; + host = NULL; + } + device->service = NULL; + host = NULL; + return; +} + +static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config) +{ + int ret; + if (pwm == NULL || config == NULL) { + HDF_LOGE("%s: PwmDev* pwm or struct PwmConfig *config is NULL!", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + PwmDeviceConfig *pwmDevice = (PwmDeviceConfig *)PwmGetPriv(pwm); + if (pwmDevice == NULL) { + HDF_LOGE("%s: PwmDeviceConfig* pwmDevice is NULL", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + if (config->status == PWM_ENABLE_STATUS) { // 使能PWM + if (pwmDevice->ledc_timer_config.freq_hz != PERIOD2FREQUENCY(config->period)) { // 周期有频率变化 + pwmDevice->ledc_timer_config.freq_hz = PERIOD2FREQUENCY(config->period); + ledc_timer_config(&pwmDevice->ledc_timer_config); // 重新配置周期 + printf("\r\n------->config freq_hz = %d [period = %d]\r\n", + pwmDevice->ledc_timer_config.freq_hz, config->period); + printf("speed_mode = %d\r\n", pwmDevice->ledc_timer_config.speed_mode); + printf("timer_num = %d\r\n", pwmDevice->ledc_timer_config.timer_num); + printf("clk_cfg = %d\r\n", pwmDevice->ledc_timer_config.clk_cfg); + printf("duty_resolution = %d\r\n", pwmDevice->ledc_timer_config.duty_resolution); + } + if (pwmDevice->ledc_channel_config.duty != GET_ESP_DUTY_CYCLE_PERCENT(config->duty, config->period)) { + pwmDevice->ledc_channel_config.duty = GET_ESP_DUTY_CYCLE_PERCENT(config->duty, config->period); + printf("\r\n------->config ledc_duty = %d [duty=%d <--> period=%d]\r\n", + pwmDevice->ledc_channel_config.duty, config->duty, config->period); + printf("gpio_num = %d\r\n", pwmDevice->ledc_channel_config.gpio_num); + printf("speed_mode = %d\r\n", pwmDevice->ledc_channel_config.speed_mode); + printf("channel = %d\r\n", pwmDevice->ledc_channel_config.channel); + printf("timer_sel = %d\r\n", pwmDevice->ledc_channel_config.timer_sel); + printf("hpoint = %d\r\n", pwmDevice->ledc_channel_config.hpoint); + } + } else if (config->status == PWM_DISABLE_STATUS) { // 失能PWM + ledc_stop(pwmDevice->ledc_timer_config.speed_mode, pwmDevice->channel, config->polarity); + printf("------->pwm output stop, set level = %d\r\n", config->polarity); + } + return HDF_SUCCESS; +} + +static int32_t PwmDevOpen(struct PwmDev *pwm) +{ + if (pwm == NULL) { + HDF_LOGE("%s: PwmDev* pwm is NULL", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + + PwmDeviceConfig *pwmDevice = (PwmDeviceConfig *)PwmGetPriv(pwm); + if (pwmDevice == NULL) { + HDF_LOGE("%s: PwmDeviceConfig* pwmDevice is NULL", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + return HDF_SUCCESS; +} + +static int32_t PwmDevClose(struct PwmDev *pwm) +{ + HDF_LOGI("——> Enter %s", __FUNCTION__); + return HDF_SUCCESS; +} \ No newline at end of file diff --git a/niobeu4/liteos_m/hdf_drivers/spi/BUILD.gn b/niobeu4/liteos_m/hdf_drivers/spi/BUILD.gn new file mode 100644 index 0000000..54856e3 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/spi/BUILD.gn @@ -0,0 +1,39 @@ +# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_SPI) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_ESPRESSIF)) { + sources += [ "spi_esp32u4.c" ] + } + include_dirs = [ "." ] + if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) && + defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + deps = [ "//device/board/fnlink/shields" ] + } + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/niobeu4/liteos_m/hdf_drivers/spi/spi_esp32u4.c b/niobeu4/liteos_m/hdf_drivers/spi/spi_esp32u4.c new file mode 100644 index 0000000..454a4f2 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/spi/spi_esp32u4.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed 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 +#include +#include "osal_mutex.h" +#include "osal_sem.h" +#include "spi_core.h" +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif +#include "hdf_log.h" +#include "osal_mem.h" +#include "gpio_types.h" +#include "driver/spi_common.h" +#include "driver/spi_master.h" + +#ifndef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#error "LOSCFG_DRIVERS_HDF_CONFIG_MACRO" +#endif + +typedef struct { + uint8_t spi_num; + uint8_t miso_pin; + uint8_t mosi_pin; + uint8_t sck_pin; + uint8_t cs_pin; + uint8_t mode; + uint8_t queue_size; + uint8_t dma_chn; + uint8_t transferMode; + uint8_t bitsPerWord; + uint16_t openCnt; + uint16_t max_transfer_size; + uint32_t speed; + spi_device_handle_t spi_handle; +} SpiDeviceSt; + +static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg); +static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg); +static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count); +static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr); +static int32_t SpiDevClose(struct SpiCntlr *spiCntlr); + +static int32_t SpiDriverBind(struct HdfDeviceObject *device); +static int32_t SpiDriverInit(struct HdfDeviceObject *device); +static void SpiDriverRelease(struct HdfDeviceObject *device); + +struct SpiCntlrMethod g_twSpiCntlrMethod = { + .GetCfg = SpiDevGetCfg, + .SetCfg = SpiDevSetCfg, + .Transfer = SpiDevTransfer, + .Open = SpiDevOpen, + .Close = SpiDevClose, +}; + +struct HdfDriverEntry g_SpiDriverEntry = { + .moduleVersion = 1, + .moduleName = "ESP32U4_SPI_MODULE_HDF", + .Bind = SpiDriverBind, + .Init = SpiDriverInit, + .Release = SpiDriverRelease, +}; + +HDF_INIT(g_SpiDriverEntry); + +#define SPI_FIND_CONFIG(node, name, dev) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + (dev)->spi_num = HCS_PROP(node, spi_num); \ + (dev)->miso_pin = HCS_PROP(node, miso_pin); \ + (dev)->mosi_pin = HCS_PROP(node, mosi_pin); \ + (dev)->sck_pin = HCS_PROP(node, sck_pin); \ + (dev)->cs_pin = HCS_PROP(node, cs_pin); \ + (dev)->speed = HCS_PROP(node, speed); \ + (dev)->mode = HCS_PROP(node, mode); \ + (dev)->max_transfer_size = HCS_PROP(node, max_transfer_size); \ + (dev)->queue_size = HCS_PROP(node, queue_size); \ + (dev)->dma_chn = HCS_PROP(node, dma_chn); \ + result = HDF_SUCCESS; \ + } \ + } while (0) + +#define PLATFORM_SPI_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), spi_config) +static int32_t GetSpiDeviceResource(SpiDeviceSt *spiDevice, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + if (spiDevice == NULL || deviceMatchAttr == NULL) { + return HDF_ERR_INVALID_PARAM; + } + HCS_FOREACH_CHILD_VARGS(PLATFORM_SPI_CONFIG, SPI_FIND_CONFIG, deviceMatchAttr, spiDevice); + return result; +} + +static int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, struct HdfDeviceObject *device) +{ + int32_t ret; + SpiDeviceSt *spiDevice = NULL; + + if (spiCntlr == NULL || device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + spiDevice = (SpiDeviceSt *)OsalMemCalloc(sizeof(SpiDeviceSt)); + if (spiDevice == NULL) { + return HDF_ERR_MALLOC_FAIL; + } + + ret = GetSpiDeviceResource(spiDevice, device->deviceMatchAttr); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(spiDevice); + return HDF_FAILURE; + } + + spiCntlr->priv = spiDevice; + spiCntlr->busNum = spiDevice->spi_num; + + return HDF_SUCCESS; +} + +static int32_t SpiDriverBind(struct HdfDeviceObject *device) +{ + struct SpiCntlr *spiCntlr = NULL; + if (device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + spiCntlr = SpiCntlrCreate(device); + if (spiCntlr == NULL) { + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +static int32_t SpiDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct SpiCntlr *spiCntlr = NULL; + + if (device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + spiCntlr = SpiCntlrFromDevice(device); + if (spiCntlr == NULL) { + return HDF_DEV_ERR_NO_DEVICE; + } + + ret = AttachSpiDevice(spiCntlr, device); + if (ret != HDF_SUCCESS) { + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + spiCntlr->method = &g_twSpiCntlrMethod; + + return ret; +} + +static void SpiDriverRelease(struct HdfDeviceObject *device) +{ + SpiDeviceSt *dev; + struct SpiCntlr *spiCntlr = NULL; + + if (device == NULL) { + return; + } + + spiCntlr = SpiCntlrFromDevice(device); + if (spiCntlr == NULL) { + return; + } + + dev = (SpiDeviceSt *)spiCntlr->priv; + if (dev == NULL) { + return; + } + if (dev->openCnt) { + dev->openCnt = 1; + (void)SpiDevClose(spiCntlr); + } + OsalMemFree(spiCntlr->priv); + spiCntlr->priv = NULL; + return; +} +static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr) +{ + esp_err_t err; + SpiDeviceSt *dev; + if (spiCntlr == NULL) { + return HDF_ERR_INVALID_PARAM; + } + dev = (SpiDeviceSt *)spiCntlr->priv; + if (dev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + if (dev->openCnt == 0) { + spi_bus_config_t buscfg = {0}; + buscfg.miso_io_num = dev->miso_pin; + buscfg.mosi_io_num = dev->mosi_pin; + buscfg.sclk_io_num = dev->sck_pin; + buscfg.quadwp_io_num = GPIO_NUM_NC; + buscfg.quadhd_io_num = GPIO_NUM_NC; + buscfg.max_transfer_sz = dev->max_transfer_size; + err = spi_bus_initialize(dev->spi_num, &buscfg, dev->dma_chn); + if (err != ESP_OK) { + return HDF_ERR_IO; + } + } + if (dev->openCnt == 0) { + spi_device_interface_config_t devcfg = {0}; + devcfg.clock_speed_hz = dev->speed; + devcfg.mode = dev->mode; + devcfg.spics_io_num = dev->cs_pin; + devcfg.queue_size = dev->queue_size; + err = spi_bus_add_device(dev->spi_num, &devcfg, &dev->spi_handle); + if (err != ESP_OK) { + return HDF_ERR_DEVICE_BUSY; + } + } + dev->openCnt++; + return HDF_SUCCESS; +} + +static int32_t SpiDevClose(struct SpiCntlr *spiCntlr) +{ + esp_err_t err; + SpiDeviceSt *dev; + if (spiCntlr == NULL) { + return HDF_ERR_INVALID_PARAM; + } + dev = (SpiDeviceSt *)spiCntlr->priv; + if (dev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + if (dev->openCnt > 0) { + if (--dev->openCnt > 0) { + return HDF_SUCCESS; + } + err = spi_bus_remove_device(dev->spi_handle); + if (err != ESP_OK) { + return HDF_ERR_DEVICE_BUSY; + } + dev->spi_handle = NULL; + + err = spi_bus_free(dev->spi_num); + if (err != ESP_OK) { + return HDF_ERR_IO; + } + } + return HDF_SUCCESS; +} + +static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg) +{ + SpiDeviceSt *dev; + if (spiCntlr == NULL || spiCfg == NULL) { + return HDF_ERR_INVALID_PARAM; + } + dev = (SpiDeviceSt *)spiCntlr->priv; + if (dev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + spiCfg->maxSpeedHz = dev->speed; + spiCfg->mode = dev->mode; + spiCfg->transferMode = dev->transferMode; + spiCfg->bitsPerWord = dev->bitsPerWord; + return HDF_SUCCESS; +} +static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg) +{ + SpiDeviceSt *dev; + if (spiCntlr == NULL || spiCfg == NULL) { + return HDF_ERR_INVALID_PARAM; + } + dev = (SpiDeviceSt *)spiCntlr->priv; + if (dev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + dev->speed = spiCfg->maxSpeedHz; + dev->mode = spiCfg->mode; + dev->transferMode = spiCfg->transferMode; + dev->bitsPerWord = spiCfg->bitsPerWord; + return HDF_SUCCESS; +} + +static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count) +{ + esp_err_t err; + SpiDeviceSt *dev; + if (spiCntlr == NULL) { + return HDF_ERR_INVALID_PARAM; + } + dev = (SpiDeviceSt *)spiCntlr->priv; + if (dev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + for (size_t i = 0; i < count; i++) { + struct SpiMsg *msg = &spiMsg[i]; + spi_transaction_t t = {0}; + if ((msg->wbuf == NULL) && (msg->rbuf == NULL)) { + continue; + } + t.length = msg->len << '\x3'; + t.rx_buffer = msg->rbuf; + t.tx_buffer = msg->wbuf; + err = spi_device_polling_transmit(dev->spi_handle, &t); + if (err != ESP_OK) { + return HDF_ERR_DEVICE_BUSY; + } + } + return HDF_SUCCESS; +} diff --git a/niobeu4/liteos_m/hdf_drivers/uart/BUILD.gn b/niobeu4/liteos_m/hdf_drivers/uart/BUILD.gn new file mode 100644 index 0000000..f94c38c --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/uart/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_ESPRESSIF)) { + sources += [ "uart_esp32u4.c" ] + } + + include_dirs = [ "." ] + if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) && + defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + deps = [ "//device/board/fnlink/shields" ] + } + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/niobeu4/liteos_m/hdf_drivers/uart/uart_esp32u4.c b/niobeu4/liteos_m/hdf_drivers/uart/uart_esp32u4.c new file mode 100644 index 0000000..41bd6c4 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/uart/uart_esp32u4.c @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed 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 +#include +#include "esp_err.h" +#include "uart.h" +#include "gpio_types.h" +#include "uart_types.h" +#include "uart_if.h" +#include "uart_core.h" +#include "osal_sem.h" +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#include "hdf_log.h" + +#ifdef GPIO_NUM_MAX +#undef GPIO_NUM_MAX +#endif + +#define HDF_UART_TMO 1000 +#define HDF_LOG_TAG uartDev +#define GPIO_MAX_LENGTH 32 +#define UART_FIFO_MAX_BUFFER 2048 +#define UART_DMA_RING_BUFFER_SIZE 256 // mast be 2^n +#define MAX_DEV_NAME_SIZE 32 + +#define UART_PIN_NUNS 4 // 串口引脚配置个数 +#define MAX_UART_NUMS 3 // 最大串口个数 +#define UART_RX_BUFF_SIZE 512 +#define UART_TX_BUFF_SIZE 512 +#define OH_ESP_DATABITS_EX(data_bits) (3 - (data_bits)) +#define OH2ESP_STOPBITS(oh_stop_bits) (1 + (oh_stop_bits)) +#define ESP2OH_STOPBITS(esp_stop_bits) ((esp_stop_bits)-1) + +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_UART_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), uart_config) +#define HDF_GPIO_FIND_SOURCE(node, uartHost, device) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), (device)->deviceMatchAttr) == 0) { \ + int cur_uart_gpio_pin[] = HCS_ARRAYS(HCS_PROP(node, uart_gpio_pin)); \ + struct UartAttrSourceStr cur_uart_attr = HCS_ARRAYS(HCS_PROP(node, uart_attr)); \ + UartAttr *uart_config = (UartAttr *)OsalMemAlloc(sizeof(UartAttr)); \ + if (uart_config == NULL) { \ + HDF_LOGE("%s: OsalMemCalloc uart_config error", __func__); \ + return HDF_ERR_MALLOC_FAIL; \ + } \ + uart_config->uart_port = HCS_PROP(node, uart_port); \ + uart_config->baudrate = HCS_PROP(node, baudrate); \ + uart_config->uart_pin[0] = cur_uart_gpio_pin[0]; \ + uart_config->uart_pin[1] = cur_uart_gpio_pin[1]; \ + uart_config->uart_pin[2] = cur_uart_gpio_pin[2]; \ + uart_config->uart_pin[3] = cur_uart_gpio_pin[3]; \ + uart_config->data_bits = GetWordLengthFromStr(cur_uart_attr.data_bits); \ + uart_config->parity = GetParityFromStr(cur_uart_attr.parity); \ + uart_config->stop_bits = GetStopBitsFromStr(cur_uart_attr.stop_bits); \ + uart_config->hw_flowcontrol = GetHwFlowControlFromStr(cur_uart_attr.hw_flowcontrol); \ + HDF_LOGE("----- UART%d Config -----", uart_config->uart_port); \ + HDF_LOGE("baudrate = %d", uart_config->baudrate); \ + HDF_LOGE("Uart_Pin = [%d,%d,%d,%d]", uart_config->uart_pin[0], uart_config->uart_pin[1], \ + uart_config->uart_pin[2], uart_config->uart_pin[3]); \ + HDF_LOGE("data_bits = %s[%d]", cur_uart_attr.data_bits, uart_config->data_bits); \ + HDF_LOGE("parity = %s[%d]", cur_uart_attr.parity, uart_config->parity); \ + HDF_LOGE("stop_bits = %s[%d]", cur_uart_attr.stop_bits, uart_config->stop_bits); \ + HDF_LOGE("hw_flowcontrol = %s[%d]", cur_uart_attr.hw_flowcontrol, \ + uart_config->hw_flowcontrol); \ + uart_config->block_time = 0; \ + (uartHost)->priv = uart_config; \ + (uartHost)->num = uart_config->uart_port; \ + } \ + } while (0) + +static int32_t UartDriverBind(struct HdfDeviceObject *device); +static int32_t UartDriverInit(struct HdfDeviceObject *device); +static void UartDriverRelease(struct HdfDeviceObject *device); + +struct HdfDriverEntry g_UartDriverEntry = { + .moduleVersion = 1, + .moduleName = "ESP32U4_HDF_UART", + .Bind = UartDriverBind, + .Init = UartDriverInit, + .Release = UartDriverRelease, +}; + +HDF_INIT(g_UartDriverEntry); + +static int32_t UartHostDevInit(struct UartHost *host); +static int32_t UartHostDevDeinit(struct UartHost *host); +static int32_t UartHostDevWrite(struct UartHost *host, uint8_t *data, uint32_t size); +static int32_t UartHostDevSetBaud(struct UartHost *host, uint32_t baudRate); +static int32_t UartHostDevGetBaud(struct UartHost *host, uint32_t *baudRate); +static int32_t UartHostDevRead(struct UartHost *host, uint8_t *data, uint32_t size); +static int32_t UartHostDevSetAttribute(struct UartHost *host, struct UartAttribute *attribute); +static int32_t UartHostDevGetAttribute(struct UartHost *host, struct UartAttribute *attribute); +static int32_t UartHostDevSetTransMode(struct UartHost *host, enum UartTransMode mode); + +struct UartHostMethod g_uartHostMethod = { + .Init = UartHostDevInit, + .Deinit = UartHostDevDeinit, + .Read = UartHostDevRead, + .Write = UartHostDevWrite, + .SetBaud = UartHostDevSetBaud, + .GetBaud = UartHostDevGetBaud, + .SetAttribute = UartHostDevSetAttribute, + .GetAttribute = UartHostDevGetAttribute, + .SetTransMode = UartHostDevSetTransMode, +}; + +struct UartAttrSourceStr { + char *data_bits; + char *parity; + char *stop_bits; + char *hw_flowcontrol; +}; + +typedef struct _UartAttr { + int uart_port; + int baudrate; + int uart_pin[UART_PIN_NUNS]; + int data_bits; + int parity; + int stop_bits; + int hw_flowcontrol; + unsigned int block_time; +} UartAttr; + +static int GetWordLengthFromStr(const char *str) +{ + if (!strcmp(str, "UART_DATA_5_BITS")) { + return UART_DATA_5_BITS; + } else if (!strcmp(str, "UART_DATA_6_BITS")) { + return UART_DATA_6_BITS; + } else if (!strcmp(str, "UART_DATA_7_BITS")) { + return UART_DATA_7_BITS; + } + return UART_DATA_8_BITS; +} + +static int GetParityFromStr(const char *str) +{ + if (!strcmp(str, "UART_PARITY_EVEN")) { + return UART_PARITY_EVEN; + } else if (!strcmp(str, "UART_PARITY_ODD")) { + return UART_PARITY_ODD; + } + return UART_PARITY_DISABLE; +} + +static int GetStopBitsFromStr(const char *str) +{ + if (!strcmp(str, "UART_STOP_BITS_1_5")) { + return UART_STOP_BITS_1_5; + } else if (!strcmp(str, "UART_STOP_BITS_2")) { + return UART_STOP_BITS_2; + } + return UART_STOP_BITS_1; +} + +static int GetHwFlowControlFromStr(const char *str) +{ + if (!strcmp(str, "UART_HW_FLOWCTRL_RTS")) { + return UART_HW_FLOWCTRL_RTS; + } else if (!strcmp(str, "UART_HW_FLOWCTRL_CTS")) { + return UART_HW_FLOWCTRL_CTS; + } else if (!strcmp(str, "UART_HW_FLOWCTRL_CTS_RTS")) { + return UART_HW_FLOWCTRL_CTS_RTS; + } + return UART_HW_FLOWCTRL_DISABLE; +} + +static int32_t AttachUartDevice(struct UartHost *uartHost, struct HdfDeviceObject *device) +{ + int32_t ret; + if (device == NULL || uartHost == NULL) { + HDF_LOGE("%s: uartHost or device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + HCS_FOREACH_CHILD_VARGS(PLATFORM_UART_CONFIG, HDF_GPIO_FIND_SOURCE, uartHost, device); + + return HDF_SUCCESS; +} + +static int32_t UartDriverBind(struct HdfDeviceObject *device) +{ + if (device == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + struct UartHost *devService = UartHostCreate(device); + if (devService == NULL) { + HDF_LOGE("%s: UartHostCreate fail!", __func__); + return HDF_FAILURE; + } + HDF_LOGI("%s: UartHostCreate success!", __func__); + return HDF_SUCCESS; +} + +static void UartDriverRelease(struct HdfDeviceObject *device) +{ + struct UartHost *host = NULL; + if (device == NULL) { + HDF_LOGE("%s: device is NULL!", __func__); + return; + } + + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is null", __func__); + return; + } + + if (host->priv != NULL) { + OsalMemFree(host->priv); + host->priv = NULL; + } +} + +static int32_t UartDriverInit(struct HdfDeviceObject *device) +{ + HDF_LOGI("Enter %s:", __func__); + int32_t ret; + struct UartHost *host = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = AttachUartDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: attach error", __func__); + return HDF_FAILURE; + } + host->method = &g_uartHostMethod; + return ret; +} + +#define DEFAULT_RX_FLOW_CTRL_THRESH 122 +#define INDEX_2 2 +#define INDEX_3 3 +/* UartHostMethod implementations */ +static int32_t UartHostDevInit(struct UartHost *host) +{ + int ret; + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + UartAttr *uart_config = (UartAttr *)host->priv; + if (uart_config == NULL) { + HDF_LOGE("%s: parse uart config fail", __func__); + return HDF_FAILURE; + } + uart_config_t uartConfig = {0}; + uartConfig.baud_rate = uart_config->baudrate; + uartConfig.data_bits = uart_config->data_bits; + uartConfig.parity = uart_config->parity; + uartConfig.stop_bits = uart_config->stop_bits; + uartConfig.flow_ctrl = uart_config->hw_flowcontrol; + if (0x01 & uartConfig.flow_ctrl) { + uartConfig.rx_flow_ctrl_thresh = DEFAULT_RX_FLOW_CTRL_THRESH; + } + uart_param_config(uart_config->uart_port, &uartConfig); + + // 检查pin脚是否合法 + for (int i = 0; i < UART_PIN_NUNS; i++) { + if (uart_config->uart_pin[i] >= GPIO_NUM_MAX || uart_config->uart_pin[i] < 0) { + uart_config->uart_pin[i] = -1; + } + } + + ret = uart_set_pin(uart_config->uart_port, uart_config->uart_pin[0], uart_config->uart_pin[1], + uart_config->uart_pin[INDEX_2], uart_config->uart_pin[INDEX_3]); + if (ret != 0) { + HDF_LOGE("uart_set_pin failed ret=0x%X\n", ret); + return HDF_FAILURE; + } + + ret = uart_driver_install(uart_config->uart_port, UART_RX_BUFF_SIZE, UART_TX_BUFF_SIZE, 0, NULL, 0); + if (ret != 0) { + HDF_LOGE("uart_driver_install failed ret=0x%X\n", ret); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +static int32_t UartHostDevDeinit(struct UartHost *host) +{ + int ret = HDF_FAILURE; + ret = uart_driver_delete(host->num); + if (ret != ESP_OK) { + HDF_LOGE("%s: uart%d_driver_delete failed\n", host->num, __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t UartHostDevWrite(struct UartHost *host, uint8_t *data, uint32_t size) +{ + int ret = HDF_FAILURE; + ret = uart_write_bytes(host->num, (const uint8_t *)data, size); + if (ret < 0) { + HDF_LOGE("uart_write_bytes failed!"); + return HDF_FAILURE; + } + return ret; +} + +static int32_t UartHostDevRead(struct UartHost *host, uint8_t *data, uint32_t size) +{ + int length = 0; + int rcv_bytes = 0; + if (host == NULL) { + HDF_LOGE("UartHost is NULL!"); + return HDF_ERR_INVALID_PARAM; + } + + UartAttr *uart_config = (UartAttr *)host->priv; + if (uart_config == NULL) { + HDF_LOGE("%s: parse uart config fail", __func__); + return HDF_FAILURE; + } + int ret = uart_read_bytes(host->num, (uint8_t *)data, 1, uart_config->block_time); + if (ret < 0) { + HDF_LOGE("uart_read_bytes failed!"); + return HDF_FAILURE; + } + rcv_bytes += ret; + uart_get_buffered_data_len(host->num, &length); // 获取buffer长度 + if (length > 0) { + ret = uart_read_bytes(host->num, (uint8_t *)(&data[1]), size - 1, 0); + if (ret < 0) { + HDF_LOGE("uart_read_bytes failed!"); + return HDF_FAILURE; + } + rcv_bytes += ret; + } + return rcv_bytes; +} + +static int32_t UartHostDevSetBaud(struct UartHost *host, uint32_t baudRate) +{ + if (host == NULL) { + HDF_LOGE("UartHost is NULL!"); + return HDF_ERR_INVALID_PARAM; + } + + UartAttr *uart_config = (UartAttr *)host->priv; + if (uart_config == NULL) { + HDF_LOGE("%s: parse uart config fail", __func__); + return HDF_FAILURE; + } + uart_config->baudrate = baudRate; + return HDF_SUCCESS; +} + +static int32_t UartHostDevGetBaud(struct UartHost *host, uint32_t *baudRate) +{ + if (host == NULL) { + HDF_LOGE("UartHost is NULL!"); + return HDF_ERR_INVALID_PARAM; + } + UartAttr *uart_config = (UartAttr *)host->priv; + if (uart_config == NULL) { + HDF_LOGE("%s: parse uart config fail", __func__); + return HDF_FAILURE; + } + *baudRate = uart_config->baudrate; + return HDF_SUCCESS; +} + +static int32_t UartHostDevSetAttribute(struct UartHost *host, struct UartAttribute *attribute) +{ + if (host == NULL) { + HDF_LOGE("UartHost is NULL!"); + return HDF_ERR_INVALID_PARAM; + } + UartAttr *uart_config = (UartAttr *)host->priv; + if (uart_config == NULL) { + HDF_LOGE("%s: parse uart config fail", __func__); + return HDF_FAILURE; + } + + uart_config->data_bits = OH_ESP_DATABITS_EX(attribute->dataBits); + if (attribute->parity == UART_ATTR_PARITY_NONE) { + uart_config->parity = UART_PARITY_DISABLE; + } else if (attribute->parity == UART_ATTR_PARITY_EVEN) { + uart_config->parity = UART_PARITY_EVEN; + } else if (attribute->parity == UART_ATTR_PARITY_ODD) { + uart_config->parity = UART_PARITY_ODD; + } else { + HDF_LOGE("%s: Not support set uart attribute->parity = %d", __func__, attribute->parity); + return HDF_FAILURE; + } + uart_config->stop_bits = OH2ESP_STOPBITS(attribute->stopBits); + return HDF_SUCCESS; +} + +static int32_t UartHostDevGetAttribute(struct UartHost *host, struct UartAttribute *attribute) +{ + if (host == NULL) { + HDF_LOGE("UartHost is NULL!"); + return HDF_ERR_INVALID_PARAM; + } + UartAttr *uart_config = (UartAttr *)host->priv; + if (uart_config == NULL) { + HDF_LOGE("%s: parse uart config fail", __func__); + return HDF_FAILURE; + } + + attribute->dataBits = OH_ESP_DATABITS_EX(uart_config->data_bits); + + if (uart_config->parity == UART_PARITY_EVEN) { + attribute->parity = UART_ATTR_PARITY_EVEN; + } else if (uart_config->parity == UART_PARITY_ODD) { + attribute->parity = UART_ATTR_PARITY_ODD; + } else { + attribute->parity = UART_ATTR_PARITY_NONE; + } + attribute->stopBits = ESP2OH_STOPBITS(uart_config->stop_bits); + return HDF_SUCCESS; +} + +static int32_t UartHostDevSetTransMode(struct UartHost *host, enum UartTransMode mode) +{ + UartAttr *uart_config = (UartAttr *)host->priv; + if (uart_config == NULL) { + HDF_LOGE("%s: parse uart config fail", __func__); + return HDF_FAILURE; + } + if (mode == UART_MODE_RD_BLOCK) { + uart_config->block_time = 0xFFFFFFFF; + } else if (mode == UART_MODE_RD_NONBLOCK) { + uart_config->block_time = 0; + } else { + HDF_LOGE("%s: Not support mode = %d", __func__, mode); + } + return HDF_SUCCESS; +} \ No newline at end of file diff --git a/niobeu4/liteos_m/hdf_drivers/watchdog/BUILD.gn b/niobeu4/liteos_m/hdf_drivers/watchdog/BUILD.gn new file mode 100644 index 0000000..77122b2 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/watchdog/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_WATCHDOG) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_ESPRESSIF)) { + sources += [ "watchdog_esp32u4.c" ] + } + + include_dirs = [ "." ] + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/niobeu4/liteos_m/hdf_drivers/watchdog/watchdog_esp32u4.c b/niobeu4/liteos_m/hdf_drivers/watchdog/watchdog_esp32u4.c new file mode 100644 index 0000000..e406333 --- /dev/null +++ b/niobeu4/liteos_m/hdf_drivers/watchdog/watchdog_esp32u4.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed 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 +#include +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "watchdog_core.h" +#include "watchdog_if.h" + +#define REG32_READ(reg) (*(volatile uint32_t *)(reg)) +#define REG32_WRITE(reg, value) (*(volatile uint32_t *)(reg) = value) + +#define RWDT_PROTECT_KEY 0x50d83aa1 +#define RWDT_PROTECT 0x3ff480a4 +#define RWDT_CFG0 0x3ff4808c +#define RWDT_CFG0_VALUE ((1 << 10) | (7 << 11) | (3 << 28) | (1 << 31)) +#define RWDT_CFG1 0x3ff48090 +#define RWDT_FEED 0x3ff480a0 +#define RWDT_TICK_BASE 0x3ff48070 +#define RWDT_TICK ((REG32_READ(RWDT_TICK_BASE) >> 30) & 3) +#define RWDT_WOG() REG32_WRITE(RWDT_FEED, (1 << 31)) +#define RWDT_IS_RUN() (REG32_READ(RWDT_CFG0) & (1 << 31)) + +#define SLOW_CK_TICK (150 * 1000) +#define XTAL_32K_TICK (32768) +#define CK8M_D256_OUT_TICK (8 * 1000 * 1000 / 256) + +typedef struct { + int watchdogId; + int timeout; // Maximum interval between watchdog feeding, unit: ms +} WatchdogDeviceInfo; + +static int g_watchdogStart = 0; +static int g_watchdogTimeout = 0; + +static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr); +static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr); +static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds); +static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds); +static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status); +static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr); + +struct WatchdogMethod g_WatchdogCntlrMethod = { + .getStatus = WatchdogDevGetStatus, + .setTimeout = WatchdogDevSetTimeout, + .getTimeout = WatchdogDevGetTimeout, + .start = WatchdogDevStart, + .stop = WatchdogDevStop, + .feed = WatchdogDevFeed, + .getPriv = NULL, + .releasePriv = NULL, +}; + +#define WATCHDOG_FIND_CONFIG(node, name, device) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + (device)->watchdogId = HCS_PROP(node, id); \ + (device)->timeout = HCS_PROP(node, timeout); \ + result = HDF_SUCCESS; \ + } \ + } while (0) + +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_WATCHDOG_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), watchdog_config) + +static uint32_t GetWatchdogDeviceInfoResource(WatchdogDeviceInfo *device, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + if (device == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("device or deviceMatchAttr is NULL"); + return HDF_ERR_INVALID_PARAM; + } + + HCS_FOREACH_CHILD_VARGS(PLATFORM_WATCHDOG_CONFIG, WATCHDOG_FIND_CONFIG, deviceMatchAttr, device); + + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL", deviceMatchAttr); + return result; + } + + return HDF_SUCCESS; +} + +static int32_t AttachWatchdogDeviceInfo(struct WatchdogCntlr *watchdogCntlr, struct HdfDeviceObject *device) +{ + int32_t ret; + WatchdogDeviceInfo *watchdogdeviceinfo = NULL; + + if (device == NULL || device->deviceMatchAttr == NULL) { + HDF_LOGE("%s: param is NULL", __func__); + return HDF_FAILURE; + } + + watchdogdeviceinfo = (WatchdogDeviceInfo *)OsalMemAlloc(sizeof(WatchdogDeviceInfo)); + if (watchdogdeviceinfo == NULL) { + HDF_LOGE("%s: OsalMemAlloc WatchdogDeviceInfo error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = GetWatchdogDeviceInfoResource(watchdogdeviceinfo, device->deviceMatchAttr); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(watchdogdeviceinfo); + return HDF_FAILURE; + } + + (void)OsalMutexInit(&watchdogCntlr->lock); + + watchdogCntlr->priv = watchdogdeviceinfo; + watchdogCntlr->wdtId = watchdogdeviceinfo->watchdogId; + + return HDF_SUCCESS; +} + +/* HdfDriverEntry method definitions */ +static int32_t WatchdogDriverBind(struct HdfDeviceObject *device); +static int32_t WatchdogDriverInit(struct HdfDeviceObject *device); +static void WatchdogDriverRelease(struct HdfDeviceObject *device); + +/* HdfDriverEntry definitions */ +struct HdfDriverEntry g_watchdogDriverEntry = { + .moduleVersion = 1, + .moduleName = "ESP32U4_WATCHDOG_MODULE_HDF", + .Bind = WatchdogDriverBind, + .Init = WatchdogDriverInit, + .Release = WatchdogDriverRelease, +}; + +// Initialize HdfDriverEntry +HDF_INIT(g_watchdogDriverEntry); + +static int32_t WatchdogDriverBind(struct HdfDeviceObject *device) +{ + struct WatchdogCntlr *watchdogCntlr = NULL; + if (device == NULL) { + HDF_LOGE("hdfDevice object is null!"); + return HDF_FAILURE; + } + + watchdogCntlr = (struct WatchdogCntlr *)OsalMemAlloc(sizeof(struct WatchdogCntlr)); + if (watchdogCntlr == NULL) { + HDF_LOGE("%s: OsalMemAlloc watchdogCntlr error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + device->service = &watchdogCntlr->service; + watchdogCntlr->device = device; + watchdogCntlr->priv = NULL; + return HDF_SUCCESS; +} + +static int32_t WatchdogDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct WatchdogCntlr *watchdogCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + watchdogCntlr = WatchdogCntlrFromDevice(device); + if (watchdogCntlr == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = AttachWatchdogDeviceInfo(watchdogCntlr, device); + if (ret != HDF_SUCCESS) { + OsalMemFree(watchdogCntlr); + HDF_LOGE("%s:attach error", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogCntlr->ops = &g_WatchdogCntlrMethod; + HDF_LOGI("WatchdogDriverInit success!"); + return ret; +} + +static void WatchdogDriverRelease(struct HdfDeviceObject *device) +{ + struct WatchdogCntlr *watchdogCntlr = NULL; + WatchdogDeviceInfo *watchdogdeviceinfo = NULL; + + if (device == NULL) { + HDF_LOGE("device is null"); + return; + } + + watchdogCntlr = WatchdogCntlrFromDevice(device); + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL", __func__); + return; + } + + watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv; + if (watchdogdeviceinfo != NULL) { + OsalMemFree(watchdogdeviceinfo); + } + return; +} + +#define XTAL_TICK 1 +#define CK8M_TICK 2 + +static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr) +{ + WatchdogDeviceInfo *watchdogdeviceinfo = NULL; + int32_t watchdogId = 0; + int32_t timeout = 0; + int32_t ticks = 0; + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv; + if (watchdogdeviceinfo == NULL) { + HDF_LOGE("%s: OBJECT is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + watchdogId = watchdogdeviceinfo->watchdogId; + timeout = watchdogdeviceinfo->timeout; + + switch (RWDT_TICK) { + case XTAL_TICK: + ticks = XTAL_32K_TICK; + break; + case CK8M_TICK: + ticks = CK8M_D256_OUT_TICK; + break; + default: + ticks = SLOW_CK_TICK; + break; + } + REG32_WRITE(RWDT_PROTECT, RWDT_PROTECT_KEY); + RWDT_WOG(); + REG32_WRITE(RWDT_CFG0, RWDT_CFG0_VALUE); + REG32_WRITE(RWDT_CFG1, (timeout * ticks)); + REG32_WRITE(RWDT_PROTECT, 0); + + HDF_LOGI("Watchdog Started! timeout: %d second", timeout); + g_watchdogStart = 1; + return HDF_SUCCESS; +} + +static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr) +{ + if (!watchdogCntlr) { + return HDF_FAILURE; + } + if (!RWDT_IS_RUN()) { + return HDF_SUCCESS; + } + REG32_WRITE(RWDT_PROTECT, RWDT_PROTECT_KEY); + RWDT_WOG(); + REG32_WRITE(RWDT_CFG0, 0); + REG32_WRITE(RWDT_PROTECT, 0); + return HDF_SUCCESS; +} + +static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds) +{ + WatchdogDeviceInfo *watchdogdeviceinfo = NULL; + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv; + if (watchdogdeviceinfo == NULL) { + HDF_LOGE("%s: OBJECT is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + watchdogdeviceinfo->timeout = seconds; + + return HDF_SUCCESS; +} + +static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds) +{ + WatchdogDeviceInfo *watchdogdeviceinfo = NULL; + if (watchdogCntlr == NULL || seconds == NULL) { + HDF_LOGE("%s: PARAM is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv; + if (watchdogdeviceinfo == NULL) { + HDF_LOGE("%s: OBJECT is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + *seconds = watchdogdeviceinfo->timeout; + return HDF_SUCCESS; +} + +static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status) +{ + if (watchdogCntlr == NULL || status == NULL) { + HDF_LOGE("%s: PARAM is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (g_watchdogStart == 1) { + *status = WATCHDOG_START; + } else { + *status = WATCHDOG_STOP; + } + return HDF_SUCCESS; +} + +static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr) +{ + if (!watchdogCntlr) { + return HDF_FAILURE; + } + REG32_WRITE(RWDT_PROTECT, RWDT_PROTECT_KEY); + RWDT_WOG(); + REG32_WRITE(RWDT_PROTECT, 0); + return HDF_SUCCESS; +} \ No newline at end of file