feat: 新增niobeu4 hdf驱动代码

Signed-off-by: fangye <fangye@talkweb.com.cn>
Change-Id: Ieace8bebb985b72763093dc754d39393c812a340
This commit is contained in:
fangye
2022-12-06 15:38:04 +08:00
parent b930587772
commit f896cd1858
15 changed files with 2357 additions and 0 deletions
+1
View File
@@ -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 "/>
+1
View File
@@ -19,6 +19,7 @@ if (ohos_kernel_type == "liteos_m") {
"arch",
"hals",
"hdf_config",
"hdf_drivers",
"target",
"third_party_adapter",
]
+27
View File
@@ -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",
]
}
+36
View File
@@ -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);
+41
View File
@@ -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);
}
}
+40
View File
@@ -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;
}
+39
View File
@@ -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;
}