mirror of
https://github.com/openharmony/device_board_openvalley.git
synced 2026-07-01 00:47:54 -04:00
@@ -59,6 +59,7 @@
|
||||
<filefilterlist>
|
||||
<filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies">
|
||||
<filteritem type="filepath" name="EULA" desc=""/>
|
||||
<filteritem type="filepath" name="niobeu4/liteos_m/hdf_drivers" desc="hdf drivers"/>
|
||||
</filefilter>
|
||||
<filefilter name="binaryFileTypePolicyFilter" desc="Filters for binaryFile" >
|
||||
<filteritem type="filename" name="*.png" desc="all so file have check "/>
|
||||
|
||||
@@ -19,6 +19,7 @@ if (ohos_kernel_type == "liteos_m") {
|
||||
"arch",
|
||||
"hals",
|
||||
"hdf_config",
|
||||
"hdf_drivers",
|
||||
"target",
|
||||
"third_party_adapter",
|
||||
]
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
}
|
||||
Executable
+36
@@ -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}" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <stdlib.h>
|
||||
#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);
|
||||
@@ -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}" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <stdlib.h>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
@@ -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}" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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}" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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}" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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}" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user