mirror of
https://github.com/openharmony/drivers_adapter.git
synced 2026-07-20 21:59:19 -04:00
!538 add niobe407 board hdf drivers under adapter and add the niobe407 visibility in hdf_hcs.gni
Merge pull request !538 from 龙幸开/niobehdf
This commit is contained in:
@@ -83,4 +83,8 @@ hdf_driver("hdf_core") {
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/fnlink/shields" ]
|
||||
}
|
||||
if (defined(LOSCFG_NIOBE407_USE_HDF) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/talkweb/niobe407/liteos_m/hdf_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
Executable → Regular
+1
@@ -98,5 +98,6 @@ set_defaults("hdf_driver") {
|
||||
configs = [ "$HDFTOPDIR:hdf_config" ]
|
||||
visibility = [ "$HDFTOPDIR:*" ]
|
||||
visibility += [ "//device/soc/bestechnic/bes2600/liteos_m/*" ]
|
||||
visibility += [ "//device/board/talkweb/niobe407/liteos_m/*" ]
|
||||
visibility += [ "//drivers/adapter/*" ]
|
||||
}
|
||||
|
||||
@@ -25,10 +25,17 @@ hdf_driver(module_name) {
|
||||
if (defined(LOSCFG_SOC_COMPANY_WINNERMICRO)) {
|
||||
sources += [ "gpio_wm.c" ]
|
||||
}
|
||||
if (defined(LOSCFG_SOC_SERIES_STM32F4xx)) {
|
||||
sources += [ "gpio_stm32f4xx.c" ]
|
||||
}
|
||||
|
||||
include_dirs = [ "." ]
|
||||
if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/fnlink/shields" ]
|
||||
}
|
||||
if (defined(LOSCFG_NIOBE407_USE_HDF) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/talkweb/niobe407/liteos_m/hdf_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Talkweb Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "hal_gpio.h"
|
||||
#include "hal_exti.h"
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
#include "hcs_macro.h"
|
||||
#include "hdf_config_macro.h"
|
||||
#else
|
||||
#include "device_resource_if.h"
|
||||
#endif
|
||||
#include "gpio_core.h"
|
||||
#include "hdf_log.h"
|
||||
#include "osal_irq.h"
|
||||
|
||||
#define HDF_LOG_TAG gpio_stm_c
|
||||
|
||||
static const uint16_t g_stmRealPinMaps[STM32_GPIO_PIN_MAX] = {
|
||||
LL_GPIO_PIN_0,
|
||||
LL_GPIO_PIN_1,
|
||||
LL_GPIO_PIN_2,
|
||||
LL_GPIO_PIN_3,
|
||||
LL_GPIO_PIN_4,
|
||||
LL_GPIO_PIN_5,
|
||||
LL_GPIO_PIN_6,
|
||||
LL_GPIO_PIN_7,
|
||||
LL_GPIO_PIN_8,
|
||||
LL_GPIO_PIN_9,
|
||||
LL_GPIO_PIN_10,
|
||||
LL_GPIO_PIN_11,
|
||||
LL_GPIO_PIN_12,
|
||||
LL_GPIO_PIN_13,
|
||||
LL_GPIO_PIN_14,
|
||||
LL_GPIO_PIN_15,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t group;
|
||||
uint32_t realPin;
|
||||
uint32_t pin;
|
||||
} GpioInflectInfo;
|
||||
|
||||
GpioInflectInfo g_gpioPinsMap[STM32_GPIO_PIN_MAX * STM32_GPIO_GROUP_MAX] = {0};
|
||||
|
||||
static const GPIO_TypeDef* g_gpioxMaps[STM32_GPIO_GROUP_MAX] = {
|
||||
GPIOA,
|
||||
GPIOB,
|
||||
GPIOC,
|
||||
GPIOD,
|
||||
GPIOE,
|
||||
GPIOF,
|
||||
GPIOG,
|
||||
GPIOH,
|
||||
GPIOI,
|
||||
};
|
||||
|
||||
static const uint32_t g_gpioExitLineMap[STM32_GPIO_PIN_MAX] = {
|
||||
LL_EXTI_LINE_0,
|
||||
LL_EXTI_LINE_1,
|
||||
LL_EXTI_LINE_2,
|
||||
LL_EXTI_LINE_3,
|
||||
LL_EXTI_LINE_4,
|
||||
LL_EXTI_LINE_5,
|
||||
LL_EXTI_LINE_6,
|
||||
LL_EXTI_LINE_7,
|
||||
LL_EXTI_LINE_8,
|
||||
LL_EXTI_LINE_9,
|
||||
LL_EXTI_LINE_10,
|
||||
LL_EXTI_LINE_11,
|
||||
LL_EXTI_LINE_12,
|
||||
LL_EXTI_LINE_13,
|
||||
LL_EXTI_LINE_14,
|
||||
LL_EXTI_LINE_15,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t pin;
|
||||
uint32_t realPin;
|
||||
uint32_t mode;
|
||||
uint32_t group;
|
||||
uint32_t pull;
|
||||
uint32_t speed;
|
||||
uint32_t outputType;
|
||||
uint32_t alternate;
|
||||
} GpioResource;
|
||||
|
||||
enum GpioDeviceState {
|
||||
GPIO_DEVICE_UNINITIALIZED = 0x0u,
|
||||
GPIO_DEVICE_INITIALIZED = 0x1u,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t pinNums;
|
||||
GpioResource resource;
|
||||
STM32_GPIO_GROUP group; /* gpio config */
|
||||
} GpioDevice;
|
||||
|
||||
static struct GpioCntlr g_stmGpioCntlr;
|
||||
|
||||
static HAL_GPIO_EXIT_CFG_T g_gpioExitCfg[STM32_GPIO_PIN_MAX * STM32_GPIO_GROUP_MAX] = {0};
|
||||
|
||||
static void OemGpioIrqHdl(uint32_t pin)
|
||||
{
|
||||
GpioCntlrIrqCallback(&g_stmGpioCntlr, pin);
|
||||
return;
|
||||
}
|
||||
|
||||
/* HdfDriverEntry method definitions */
|
||||
static int32_t GpioDriverInit(struct HdfDeviceObject *device);
|
||||
static void GpioDriverRelease(struct HdfDeviceObject *device);
|
||||
|
||||
/* HdfDriverEntry definitions */
|
||||
struct HdfDriverEntry g_GpioDriverEntry = {
|
||||
.moduleVersion = 1,
|
||||
.moduleName = "ST_GPIO_MODULE_HDF",
|
||||
.Init = GpioDriverInit,
|
||||
.Release = GpioDriverRelease,
|
||||
};
|
||||
HDF_INIT(g_GpioDriverEntry);
|
||||
|
||||
/* GpioMethod method definitions */
|
||||
static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val);
|
||||
static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val);
|
||||
static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir);
|
||||
static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir);
|
||||
static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode);
|
||||
static int32_t GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio);
|
||||
static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio);
|
||||
static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio);
|
||||
|
||||
/* GpioMethod definitions */
|
||||
struct GpioMethod g_GpioCntlrMethod = {
|
||||
.request = NULL,
|
||||
.release = NULL,
|
||||
.write = GpioDevWrite,
|
||||
.read = GpioDevRead,
|
||||
.setDir = GpioDevSetDir,
|
||||
.getDir = GpioDevGetDir,
|
||||
.toIrq = NULL,
|
||||
.setIrq = GpioDevSetIrq,
|
||||
.unsetIrq = GpioDevUnSetIrq,
|
||||
.enableIrq = GpioDevEnableIrq,
|
||||
.disableIrq = GpioDevDisableIrq,
|
||||
};
|
||||
|
||||
static void InitGpioClock(STM32_GPIO_GROUP group)
|
||||
{
|
||||
switch (group) {
|
||||
case STM32_GPIO_GROUP_A:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_B:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_C:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_D:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_E:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOE);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_F:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOF);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_G:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOG);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_H:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOH);
|
||||
break;
|
||||
case STM32_GPIO_GROUP_I:
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOI);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t InitGpioDevice(GpioDevice* device)
|
||||
{
|
||||
LL_GPIO_InitTypeDef gpioInitStruct = {0};
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
uint32_t halGpio = g_stmRealPinMaps[device->resource.realPin];
|
||||
if (halGpio > LL_GPIO_PIN_15 || halGpio < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, halGpio);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
/* init clock */
|
||||
InitGpioClock(device->resource.group);
|
||||
|
||||
GPIO_TypeDef* goiox = g_gpioxMaps[device->resource.group];
|
||||
if (device->resource.mode & LL_GPIO_MODE_OUTPUT) {
|
||||
LL_GPIO_ResetOutputPin(goiox, halGpio);
|
||||
}
|
||||
|
||||
gpioInitStruct.Pin = halGpio;
|
||||
gpioInitStruct.Mode = device->resource.mode;
|
||||
gpioInitStruct.Pull = device->resource.pull;
|
||||
gpioInitStruct.Speed = device->resource.speed;
|
||||
gpioInitStruct.OutputType = device->resource.outputType;
|
||||
gpioInitStruct.Alternate = device->resource.alternate;
|
||||
LL_GPIO_Init(goiox, &gpioInitStruct);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
static int32_t GpioParseHcs(const struct DeviceResourceIface *dri,
|
||||
GpioDevice *device, const struct DeviceResourceNode *resourceNode)
|
||||
{
|
||||
GpioResource *resource = NULL;
|
||||
resource = &device->resource;
|
||||
if (resource == NULL) {
|
||||
HDF_LOGE("%s: resource is NULL", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (dri->GetUint32(resourceNode, "pinNum", &device->pinNums, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("gpio config read pinNum fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < device->pinNums; i++) {
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "pin", i, &resource->pin, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "realPin", i, &resource->realPin, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "mode", i, &resource->mode, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "speed", i, &resource->speed, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "pull", i, &resource->pull, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "output", i, &resource->outputType, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "group", i, &resource->group, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32ArrayElem(resourceNode, "alternate", i, &resource->alternate, 0) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
g_gpioPinsMap[resource->pin].group = resource->group;
|
||||
g_gpioPinsMap[resource->pin].realPin = resource->realPin;
|
||||
g_gpioPinsMap[resource->pin].pin = resource->pin;
|
||||
|
||||
if (InitGpioDevice(device) != HDF_SUCCESS) {
|
||||
HDF_LOGE("InitGpioDevice FAIL\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
#define PLATFORM_GPIO_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), gpio_config)
|
||||
static uint32_t GetGpioDeviceResource(GpioDevice *device)
|
||||
{
|
||||
uint32_t relPin;
|
||||
int32_t ret;
|
||||
GpioResource *resource = NULL;
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
resource = &device->resource;
|
||||
if (resource == NULL) {
|
||||
HDF_LOGE("%s: resource is NULL", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
device->pinNums = HCS_PROP(PLATFORM_GPIO_CONFIG, pinNum);
|
||||
uint32_t pins[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, pin));
|
||||
uint32_t realPins[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, realPin));
|
||||
uint32_t groups[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, group));
|
||||
uint32_t modes[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, mode));
|
||||
uint32_t speeds[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, speed));
|
||||
uint32_t pulls[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, pull));
|
||||
uint32_t outputs[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, output));
|
||||
uint32_t alternates[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, alternate));
|
||||
for (size_t i = 0; i < device->pinNums; i++) {
|
||||
resource->pin = pins[i];
|
||||
resource->realPin = realPins[i];
|
||||
resource->group = groups[i];
|
||||
resource->mode = modes[i];
|
||||
resource->speed = speeds[i];
|
||||
resource->pull = pulls[i];
|
||||
resource->outputType = outputs[i];
|
||||
resource->alternate = alternates[i];
|
||||
g_gpioPinsMap[resource->pin].group = resource->group;
|
||||
g_gpioPinsMap[resource->pin].realPin = resource->realPin;
|
||||
g_gpioPinsMap[resource->pin].pin = resource->pin;
|
||||
|
||||
if (InitGpioDevice(device) != HDF_SUCCESS) {
|
||||
HDF_LOGE("InitGpioDevice FAIL\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#else
|
||||
static int32_t GetGpioDeviceResource(GpioDevice *device, const struct DeviceResourceNode *resourceNode)
|
||||
{
|
||||
int32_t ret;
|
||||
struct DeviceResourceIface *dri = NULL;
|
||||
if (device == NULL || resourceNode == NULL) {
|
||||
HDF_LOGE("%s: device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
|
||||
if (dri == NULL || dri->GetUint32 == NULL) {
|
||||
HDF_LOGE("DeviceResourceIface is invalid");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (GpioParseHcs(dri, device, resourceNode) != HDF_SUCCESS) {
|
||||
HDF_LOGE("gpio config parse hcs fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t AttachGpioDevice(struct GpioCntlr *gpioCntlr, struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
GpioDevice *gpioDevice = NULL;
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
if (device == NULL) {
|
||||
#else
|
||||
if (device == NULL || device->property == NULL) {
|
||||
#endif
|
||||
HDF_LOGE("%s: property is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
gpioDevice = (GpioDevice *)OsalMemAlloc(sizeof(GpioDevice));
|
||||
if (gpioDevice == NULL) {
|
||||
HDF_LOGE("%s: OsalMemAlloc gpioDevice error", __func__);
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
ret = GetGpioDeviceResource(gpioDevice);
|
||||
#else
|
||||
ret = GetGpioDeviceResource(gpioDevice, device->property);
|
||||
#endif
|
||||
if (ret != HDF_SUCCESS) {
|
||||
(void)OsalMemFree(gpioDevice);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
gpioCntlr->priv = gpioDevice;
|
||||
gpioCntlr->count = gpioDevice->pinNums;
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDriverInit(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_stmGpioCntlr.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;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDriverBind(struct HdfDeviceObject *device)
|
||||
{
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("device object is NULL\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void GpioDriverRelease(struct HdfDeviceObject *device)
|
||||
{
|
||||
struct GpioCntlr *gpioCntlr = NULL;
|
||||
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
gpioCntlr = GpioCntlrFromHdfDev(device);
|
||||
if (gpioCntlr == NULL) {
|
||||
HDF_LOGE("%s: host is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
gpioCntlr->count = 0;
|
||||
}
|
||||
|
||||
/* dev api */
|
||||
static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)
|
||||
{
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
HDF_LOGE("%s %d ,write pin num %d", __func__, __LINE__, realPin);
|
||||
GPIO_TypeDef* gpiox = g_gpioxMaps[g_gpioPinsMap[gpio].group];
|
||||
if (val) {
|
||||
LL_GPIO_SetOutputPin(gpiox, pinReg);
|
||||
} else {
|
||||
LL_GPIO_ResetOutputPin(gpiox, pinReg);
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
|
||||
{
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
uint16_t value = 0;
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
GPIO_TypeDef* gpiox = g_gpioxMaps[g_gpioPinsMap[gpio].group];
|
||||
value = LL_GPIO_ReadInputPin(gpiox, pinReg);
|
||||
*val = value;
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
|
||||
{
|
||||
(void)cntlr;
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
uint16_t value = 0;
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
GPIO_TypeDef* gpiox = g_gpioxMaps[g_gpioPinsMap[gpio].group];
|
||||
LL_GPIO_SetPinMode(gpiox, pinReg, dir);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
|
||||
{
|
||||
(void)cntlr;
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
uint16_t value = 0;
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
GPIO_TypeDef* gpiox = g_gpioxMaps[g_gpioPinsMap[gpio].group];
|
||||
value = LL_GPIO_GetPinMode(gpiox, pinReg);
|
||||
*dir = value;
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode)
|
||||
{
|
||||
(void)cntlr;
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
if (mode == OSAL_IRQF_TRIGGER_RISING) {
|
||||
g_gpioExitCfg[gpio].trigger = LL_EXTI_TRIGGER_RISING;
|
||||
} else if (mode == OSAL_IRQF_TRIGGER_FALLING) {
|
||||
g_gpioExitCfg[gpio].trigger = LL_EXTI_TRIGGER_FALLING;
|
||||
} else {
|
||||
HDF_LOGE("%s %d, error mode:%d", __func__, __LINE__, mode);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio)
|
||||
{
|
||||
(void)cntlr;
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
|
||||
{
|
||||
(void)cntlr;
|
||||
LL_EXTI_InitConfig exitInitConfig = {0};
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
exitInitConfig.Exithandler = OemGpioIrqHdl;
|
||||
exitInitConfig.Gpiox = g_gpioxMaps[g_gpioPinsMap[gpio].group];
|
||||
exitInitConfig.initType.Line_0_31 = g_gpioExitLineMap[g_gpioPinsMap[gpio].realPin];
|
||||
exitInitConfig.initType.LineCommand = ENABLE;
|
||||
exitInitConfig.initType.Mode = LL_EXTI_MODE_IT;
|
||||
exitInitConfig.PinReg = pinReg;
|
||||
exitInitConfig.initType.Trigger = g_gpioExitCfg[gpio].trigger;
|
||||
|
||||
LL_SETUP_EXTI(&exitInitConfig, g_gpioPinsMap[gpio].realPin, gpio, g_gpioPinsMap[gpio].group);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
|
||||
{
|
||||
(void)cntlr;
|
||||
LL_EXTI_InitConfig exitInitConfig = {0};
|
||||
uint16_t realPin = g_gpioPinsMap[gpio].realPin;
|
||||
uint32_t pinReg = g_stmRealPinMaps[realPin];
|
||||
if (pinReg > LL_GPIO_PIN_15 || pinReg < LL_GPIO_PIN_0) {
|
||||
HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, realPin);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
exitInitConfig.Exithandler = NULL;
|
||||
exitInitConfig.Gpiox = g_gpioxMaps[g_gpioPinsMap[gpio].group];
|
||||
exitInitConfig.initType.Line_0_31 = g_gpioExitLineMap[g_gpioPinsMap[gpio].realPin];
|
||||
exitInitConfig.initType.LineCommand = DISABLE;
|
||||
exitInitConfig.initType.Mode = LL_EXTI_MODE_IT;
|
||||
exitInitConfig.PinReg = pinReg;
|
||||
exitInitConfig.initType.Trigger = g_gpioExitCfg[gpio].trigger;
|
||||
LL_SETUP_EXTI(&exitInitConfig, g_gpioPinsMap[gpio].realPin, gpio, g_gpioPinsMap[gpio].group);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
@@ -19,10 +19,17 @@ hdf_driver(module_name) {
|
||||
if (defined(LOSCFG_SOC_COMPANY_WINNERMICRO)) {
|
||||
sources += [ "i2c_wm.c" ]
|
||||
}
|
||||
if (defined(LOSCFG_SOC_SERIES_STM32F4xx)) {
|
||||
sources += [ "i2c_stm32f4xx.c" ]
|
||||
}
|
||||
|
||||
include_dirs = [ "." ]
|
||||
if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/fnlink/shields" ]
|
||||
}
|
||||
if (defined(LOSCFG_NIOBE407_USE_HDF) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/talkweb/niobe407/liteos_m/hdf_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Talkweb Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include <stdlib.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_device_desc.h"
|
||||
#include "hdf_log.h"
|
||||
#include "i2c_core.h"
|
||||
#include "i2c_if.h"
|
||||
#include "osal_mutex.h"
|
||||
#include "hdf_base_hal.h"
|
||||
#include "stm32f4xx_ll_i2c.h"
|
||||
|
||||
#define HDF_LOG_TAG "hdf_i2c"
|
||||
|
||||
typedef enum {
|
||||
I2C_HANDLE_NULL = 0,
|
||||
I2C_HANDLE_1 = 1,
|
||||
I2C_HANDLE_2 = 2,
|
||||
I2C_HANDLE_3 = 3,
|
||||
I2C_HANDLE_MAX = I2C_HANDLE_3
|
||||
} I2C_HANDLE;
|
||||
|
||||
struct RealI2cResource {
|
||||
uint8_t port;
|
||||
uint8_t devMode;
|
||||
uint32_t devAddr;
|
||||
uint32_t speed;
|
||||
struct OsalMutex mutex;
|
||||
};
|
||||
|
||||
static bool g_I2cEnableFlg[I2C_HANDLE_MAX] = {0};
|
||||
|
||||
static void HdfI2cInit(I2C_HANDLE i2cx, unsigned int i2cRate, unsigned int addr);
|
||||
static void HdfI2cWrite(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len);
|
||||
static void HdfI2cRead(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len);
|
||||
|
||||
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 = "HDF_I2C",
|
||||
.Bind = I2cDriverBind,
|
||||
.Init = I2cDriverInit,
|
||||
.Release = I2cDriverRelease,
|
||||
};
|
||||
HDF_INIT(gI2cHdfDriverEntry);
|
||||
|
||||
struct I2cMethod gI2cHostMethod = {
|
||||
.transfer = I2cDataTransfer,
|
||||
};
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
#define I2C_FIND_CONFIG(node, name, resource) \
|
||||
do { \
|
||||
if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
|
||||
resource->port = HCS_PROP(node, port); \
|
||||
resource->devMode = HCS_PROP(node, devMode); \
|
||||
resource->devAddr = HCS_PROP(node, devAddr); \
|
||||
resource->speed = HCS_PROP(node, 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);
|
||||
} else {
|
||||
HdfI2cInit(i2cResource->port, i2cResource->speed, i2cResource->devAddr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
static int32_t GetI2cDeviceResource(struct RealI2cResource *i2cResource, const struct DeviceResourceNode *resourceNode)
|
||||
{
|
||||
if (i2cResource == NULL || resourceNode == NULL) {
|
||||
HDF_LOGE("[%s]: param is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
struct DeviceResourceIface *dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
|
||||
if (dri == NULL || dri->GetUint8 == NULL || dri->GetUint32 == NULL || dri->GetUint32Array == NULL) {
|
||||
HDF_LOGE("DeviceResourceIface is invalid\r\n");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (dri->GetUint8(resourceNode, "port", &i2cResource->port, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("i2c config port fail\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint8(resourceNode, "devMode", &i2cResource->devMode, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("i2c config devMode fail\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32(resourceNode, "devAddr", &i2cResource->devAddr, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("i2c config devAddr fail\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32(resourceNode, "speed", &i2cResource->speed, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("i2c config speed fail\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
HdfI2cInit(i2cResource->port, i2cResource->speed, i2cResource->devAddr);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
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));
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
ret = GetI2cDeviceResource(i2cResource, device->deviceMatchAttr);
|
||||
#else
|
||||
ret = GetI2cDeviceResource(i2cResource, device->property);
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
struct I2cMsg *msg = NULL;
|
||||
if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
|
||||
HDF_LOGE("[%s]: OsalMutexLock fail\r\n", __func__);
|
||||
return HDF_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
msg = &msgs[i];
|
||||
if (msg->flags == I2C_FLAG_READ) {
|
||||
HdfI2cRead(device->port, msg->addr, msg->buf, msg->len);
|
||||
} else {
|
||||
HdfI2cWrite(device->port, msg->addr, msg->buf, msg->len);
|
||||
}
|
||||
}
|
||||
OsalMutexUnlock(&device->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int32_t I2cDriverBind(struct HdfDeviceObject *device)
|
||||
{
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
OsalMutexDestroy(&i2cDevice->mutex);
|
||||
OsalMemFree(i2cDevice);
|
||||
}
|
||||
}
|
||||
|
||||
static I2C_TypeDef *GetLLI2cHandlerMatch(I2C_HANDLE i2cx)
|
||||
{
|
||||
if (i2cx > I2C_HANDLE_MAX) {
|
||||
printf("ERR: GetLLI2cClkMatch fail, param match fail\r\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (i2cx) {
|
||||
case I2C_HANDLE_1:
|
||||
return (I2C_TypeDef *)I2C1;
|
||||
case I2C_HANDLE_2:
|
||||
return (I2C_TypeDef *)I2C2;
|
||||
case I2C_HANDLE_3:
|
||||
return (I2C_TypeDef *)I2C3;
|
||||
default:
|
||||
printf("ERR: GetLLI2cClkMatch fail, handler match fail\r\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool EnableLLI2cClock(I2C_TypeDef *i2cx)
|
||||
{
|
||||
if (i2cx == I2C1) {
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
return true;
|
||||
} else if (i2cx == I2C2) {
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C2);
|
||||
return true;
|
||||
} else if (i2cx == I2C3) {
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
return true;
|
||||
} else {
|
||||
printf("EnableI2cClock fail, i2cx match fail\r\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void HdfI2cInit(I2C_HANDLE i2cx, unsigned int i2cRate, unsigned int addr)
|
||||
{
|
||||
LL_I2C_InitTypeDef I2C_InitStruct = {0};
|
||||
I2C_TypeDef *myI2c = GetLLI2cHandlerMatch(i2cx);
|
||||
if (myI2c == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnableLLI2cClock(myI2c);
|
||||
LL_I2C_DisableOwnAddress2(myI2c);
|
||||
LL_I2C_DisableGeneralCall(myI2c);
|
||||
LL_I2C_EnableClockStretching(myI2c);
|
||||
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
|
||||
I2C_InitStruct.ClockSpeed = i2cRate;
|
||||
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
|
||||
I2C_InitStruct.OwnAddress1 = addr;
|
||||
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
|
||||
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
|
||||
LL_I2C_Init(myI2c, &I2C_InitStruct);
|
||||
LL_I2C_SetOwnAddress2(myI2c, 0);
|
||||
|
||||
g_I2cEnableFlg[i2cx] = true;
|
||||
}
|
||||
|
||||
static void HdfI2cWrite(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len)
|
||||
{
|
||||
if (g_I2cEnableFlg[i2cx] != true) {
|
||||
printf("I2C_WriteByte err, Please initialize first!");
|
||||
return;
|
||||
}
|
||||
|
||||
I2C_TypeDef *myI2c = GetLLI2cHandlerMatch(i2cx);
|
||||
if (myI2c == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (LL_I2C_IsActiveFlag_BUSY(myI2c));
|
||||
|
||||
LL_I2C_GenerateStartCondition(myI2c);
|
||||
while (LL_I2C_IsActiveFlag_SB(myI2c) == RESET);
|
||||
|
||||
LL_I2C_TransmitData8(myI2c, (devAddr << 1));
|
||||
while (LL_I2C_IsActiveFlag_TXE(myI2c) == RESET);
|
||||
|
||||
LL_I2C_ClearFlag_ADDR(myI2c);
|
||||
while (LL_I2C_IsActiveFlag_TXE(myI2c) == RESET);
|
||||
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
LL_I2C_TransmitData8(myI2c, buf[i]);
|
||||
while (LL_I2C_IsActiveFlag_TXE(myI2c) == RESET);
|
||||
}
|
||||
|
||||
LL_I2C_GenerateStopCondition(myI2c);
|
||||
}
|
||||
|
||||
static void HdfI2cRead(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len)
|
||||
{
|
||||
if (g_I2cEnableFlg[i2cx] != true) {
|
||||
printf("I2C_ReadByte err, Please initialize first!");
|
||||
return;
|
||||
}
|
||||
|
||||
I2C_TypeDef *myI2c = GetLLI2cHandlerMatch(i2cx);
|
||||
if (myI2c == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (LL_I2C_IsActiveFlag_BUSY(myI2c));
|
||||
|
||||
LL_I2C_GenerateStartCondition(myI2c);
|
||||
while (LL_I2C_IsActiveFlag_SB(myI2c) == RESET);
|
||||
|
||||
LL_I2C_TransmitData8(myI2c, ((devAddr << 1) | 1));
|
||||
while ((LL_I2C_IsActiveFlag_ADDR(myI2c) == RESET) || (LL_I2C_IsActiveFlag_MSL(myI2c) == RESET) ||
|
||||
(LL_I2C_IsActiveFlag_BUSY(myI2c) == RESET));
|
||||
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
if (i < len - 1) {
|
||||
LL_I2C_AcknowledgeNextData(myI2c, LL_I2C_ACK);
|
||||
} else {
|
||||
LL_I2C_AcknowledgeNextData(myI2c, LL_I2C_NACK);
|
||||
}
|
||||
while (LL_I2C_IsActiveFlag_RXNE(myI2c) == RESET);
|
||||
buf[i] = LL_I2C_ReceiveData8(myI2c);
|
||||
}
|
||||
LL_I2C_GenerateStopCondition(myI2c);
|
||||
}
|
||||
@@ -19,10 +19,17 @@ hdf_driver(module_name) {
|
||||
if (defined(LOSCFG_SOC_COMPANY_WINNERMICRO)) {
|
||||
sources += [ "pwm_wm.c" ]
|
||||
}
|
||||
if (defined(LOSCFG_SOC_SERIES_STM32F4xx)) {
|
||||
sources += [ "pwm_stm32f4xx.c" ]
|
||||
}
|
||||
|
||||
include_dirs = [ "." ]
|
||||
if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/fnlink/shields" ]
|
||||
}
|
||||
if (defined(LOSCFG_NIOBE407_USE_HDF) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/talkweb/niobe407/liteos_m/hdf_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Talkweb Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.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_device_desc.h"
|
||||
#include "pwm_core.h"
|
||||
#include "hdf_log.h"
|
||||
#include "hdf_base_hal.h"
|
||||
#include "stm32f4xx_ll_tim.h"
|
||||
|
||||
#define GPIO_STR_MAX_LENGTH 32
|
||||
|
||||
typedef enum {
|
||||
PWM_CH1 = 0,
|
||||
PWM_CH2,
|
||||
PWM_CH3,
|
||||
PWM_CH4,
|
||||
PWM_CH_MAX
|
||||
} PWM_CH;
|
||||
|
||||
typedef enum {
|
||||
PWM_TIM1 = 0,
|
||||
PWM_TIM2,
|
||||
PWM_TIM3,
|
||||
PWM_TIM4,
|
||||
PWM_TIM5,
|
||||
PWM_TIM6,
|
||||
PWM_TIM7,
|
||||
PWM_TIM8,
|
||||
PWM_TIM9,
|
||||
PWM_TIM10,
|
||||
PWM_TIM11,
|
||||
PWM_TIM12,
|
||||
PWM_TIM13,
|
||||
PWM_TIM14,
|
||||
PWM_TIM_MAX
|
||||
} PWM_TIM;
|
||||
|
||||
typedef struct {
|
||||
PWM_CH pwmCh;
|
||||
PWM_TIM pwmTim;
|
||||
uint32_t prescaler;
|
||||
uint32_t timPeroid;
|
||||
uint32_t realHz;
|
||||
} PwmResource;
|
||||
|
||||
typedef struct {
|
||||
LL_TIM_InitTypeDef timInitStruct;
|
||||
LL_TIM_OC_InitTypeDef timOcInitStruct;
|
||||
} PwmConfig;
|
||||
|
||||
typedef struct {
|
||||
struct IDeviceIoService ioService;
|
||||
PwmConfig stPwmCfg;
|
||||
struct PwmConfig *cfg;
|
||||
PwmResource resource;
|
||||
} PwmDevice;
|
||||
|
||||
typedef struct {
|
||||
uint32_t period;
|
||||
uint32_t duty;
|
||||
PWM_TIM pwmCh;
|
||||
PWM_TIM pwmTim;
|
||||
} PwmFreqArg;
|
||||
|
||||
static TIM_TypeDef* g_stTimMap[PWM_TIM_MAX] = {
|
||||
TIM1,
|
||||
TIM2,
|
||||
TIM3,
|
||||
TIM4,
|
||||
TIM5,
|
||||
TIM6,
|
||||
TIM7,
|
||||
TIM8,
|
||||
TIM9,
|
||||
TIM10,
|
||||
TIM11,
|
||||
TIM12,
|
||||
TIM13,
|
||||
TIM14,
|
||||
};
|
||||
|
||||
static uint32_t g_stChannelMap[PWM_CH_MAX] = {
|
||||
LL_TIM_CHANNEL_CH1,
|
||||
LL_TIM_CHANNEL_CH2,
|
||||
LL_TIM_CHANNEL_CH3,
|
||||
LL_TIM_CHANNEL_CH4,
|
||||
};
|
||||
|
||||
static uint32_t g_stTimIrqMap[PWM_TIM_MAX] = {
|
||||
TIM1_CC_IRQn,
|
||||
TIM2_IRQn,
|
||||
TIM3_IRQn,
|
||||
TIM4_IRQn,
|
||||
TIM5_IRQn,
|
||||
TIM6_DAC_IRQn,
|
||||
TIM7_IRQn,
|
||||
TIM8_CC_IRQn,
|
||||
TIM1_BRK_TIM9_IRQn,
|
||||
TIM1_UP_TIM10_IRQn,
|
||||
TIM1_TRG_COM_TIM11_IRQn,
|
||||
TIM8_BRK_TIM12_IRQn,
|
||||
TIM8_UP_TIM13_IRQn,
|
||||
TIM8_TRG_COM_TIM14_IRQn,
|
||||
};
|
||||
|
||||
static uint32_t g_stTimFreq[PWM_TIM_MAX] = { // tim2-tim7, tim12-tim14 is 84M,TIM1、TIM8~TIM11 is 168M
|
||||
168000000,
|
||||
84000000,
|
||||
84000000,
|
||||
84000000,
|
||||
84000000,
|
||||
84000000,
|
||||
84000000,
|
||||
168000000,
|
||||
168000000,
|
||||
168000000,
|
||||
168000000,
|
||||
84000000,
|
||||
84000000,
|
||||
};
|
||||
|
||||
#define PER_SEC_NSEC 1000000000
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
static void InitPwmClock(PWM_TIM tim)
|
||||
{
|
||||
switch (tim) {
|
||||
case PWM_TIM1:
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
|
||||
break;
|
||||
case PWM_TIM2:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
break;
|
||||
case PWM_TIM3:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
|
||||
break;
|
||||
case PWM_TIM4:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);
|
||||
break;
|
||||
case PWM_TIM5:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM5);
|
||||
break;
|
||||
case PWM_TIM6:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);
|
||||
break;
|
||||
case PWM_TIM7:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7);
|
||||
break;
|
||||
case PWM_TIM8:
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM8);
|
||||
break;
|
||||
case PWM_TIM9:
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM9);
|
||||
break;
|
||||
case PWM_TIM10:
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM10);
|
||||
break;
|
||||
case PWM_TIM11:
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM11);
|
||||
break;
|
||||
case PWM_TIM12:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM12);
|
||||
break;
|
||||
case PWM_TIM13:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM13);
|
||||
break;
|
||||
case PWM_TIM14:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM14);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
#define PWM_FIND_CONFIG(node, name, resource) \
|
||||
do { \
|
||||
if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
|
||||
uint8_t tim = HCS_PROP(node, pwmTim); \
|
||||
uint8_t ch = HCS_PROP(node, pwmCh); \
|
||||
uint8_t prescaler = HCS_PROP(node, prescaler); \
|
||||
resource->pwmCh = ch; \
|
||||
resource->pwmTim = tim; \
|
||||
resource->prescaler = prescaler; \
|
||||
result = HDF_SUCCESS; \
|
||||
} \
|
||||
} while (0)
|
||||
#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
|
||||
#define PLATFORM_PWM_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), pwm_config)
|
||||
static uint32_t GetPwmDeviceResource(PwmDevice *device, const char *deviceMatchAttr)
|
||||
{
|
||||
int32_t result = HDF_FAILURE;
|
||||
PwmResource *resource = NULL;
|
||||
if (device == NULL || deviceMatchAttr == NULL) {
|
||||
HDF_LOGE("%s: device or deviceMatchAttr is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
resource = &device->resource;
|
||||
#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, pwm_config)
|
||||
HCS_FOREACH_CHILD_VARGS(PLATFORM_PWM_CONFIG, PWM_FIND_CONFIG, deviceMatchAttr, resource);
|
||||
#endif
|
||||
if (result != HDF_SUCCESS) {
|
||||
HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
static int32_t GetPwmDeviceResource(PwmDevice *device, const struct DeviceResourceNode *resourceNode)
|
||||
{
|
||||
struct DeviceResourceIface *dri = NULL;
|
||||
PwmResource *resource = NULL;
|
||||
|
||||
if (device == NULL || resourceNode == NULL) {
|
||||
HDF_LOGE("resource or device is NULL\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
resource = &device->resource;
|
||||
if (resource == NULL) {
|
||||
HDF_LOGE("resource is NULL\r\n");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
|
||||
if (dri == NULL || dri->GetUint8 == NULL || dri->GetUint32 == NULL) {
|
||||
HDF_LOGE("DeviceResourceIface is invalid\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (dri->GetUint8(resourceNode, "pwmTim", &resource->pwmTim, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("read pwmPin fail\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (resource->pwmTim == PWM_TIM6 || resource->pwmTim == PWM_TIM7) {
|
||||
HDF_LOGE("unsupport tim\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (dri->GetUint8(resourceNode, "pwmCh", &resource->pwmCh, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("read pwmCh fail\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32(resourceNode, "prescaler", &resource->prescaler, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("read prescaler fail\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t AttachPwmDevice(struct PwmDev *host, struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
PwmDevice *pwmDevice = NULL;
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
if (device == NULL || host == NULL) {
|
||||
#else
|
||||
if (device == NULL || device->property == NULL || host == NULL) {
|
||||
#endif
|
||||
HDF_LOGE("%s: param is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
pwmDevice = (PwmDevice *)OsalMemAlloc(sizeof(PwmDevice));
|
||||
if (pwmDevice == NULL) {
|
||||
HDF_LOGE("%s: OsalMemAlloc pwmDevice error\r\n", __func__);
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
ret = GetPwmDeviceResource(pwmDevice, device->deviceMatchAttr);
|
||||
#else
|
||||
ret = GetPwmDeviceResource(pwmDevice, device->property);
|
||||
#endif
|
||||
if (ret != HDF_SUCCESS) {
|
||||
(void)OsalMemFree(pwmDevice);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
host->priv = pwmDevice;
|
||||
host->num = pwmDevice->resource.pwmTim;
|
||||
|
||||
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 = "ST_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 InitPwmFreqAndPeriod(const struct PwmConfig *config, PwmFreqArg* arg, const PwmResource *resource)
|
||||
{
|
||||
if (arg == NULL) {
|
||||
HDF_LOGE("null ptr\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t freq = 0;
|
||||
uint32_t period = 0;
|
||||
uint32_t duty = 0;
|
||||
uint32_t realHz = 0;
|
||||
|
||||
if (config->period != 0) {
|
||||
freq = (uint32_t)(PER_SEC_NSEC / config->period);
|
||||
} else {
|
||||
HDF_LOGE("invalid div\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
realHz = (uint32_t)(((double)g_stTimFreq[arg->pwmTim]) / ((double)(resource->prescaler + 1)));
|
||||
|
||||
if (freq != 0) {
|
||||
period = (uint32_t)(realHz / freq);
|
||||
} else {
|
||||
HDF_LOGE("invalid div\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (config->period != 0) {
|
||||
duty = (uint32_t)(((double)config->duty / (double)config->period) * period);
|
||||
} else {
|
||||
HDF_LOGE("invalid div\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
arg->period = period;
|
||||
arg->duty = duty;
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void InitTimPwm(const PwmFreqArg* arg, const struct PwmConfig *config,
|
||||
PwmConfig *pwmCfg, const PwmResource *resource)
|
||||
{
|
||||
if (arg == NULL) {
|
||||
HDF_LOGE("null ptr\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pwmCfg->timInitStruct.Autoreload = arg->period - 1; // if period is 1000 20KHz/1000=20Hz,period is 50ms
|
||||
pwmCfg->timInitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
pwmCfg->timInitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
pwmCfg->timInitStruct.Prescaler = resource->prescaler;
|
||||
LL_TIM_Init(g_stTimMap[arg->pwmTim], &pwmCfg->timInitStruct);
|
||||
LL_TIM_EnableARRPreload(g_stTimMap[arg->pwmTim]);
|
||||
LL_TIM_SetClockSource(g_stTimMap[arg->pwmTim], LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||
LL_TIM_SetTriggerOutput(g_stTimMap[arg->pwmTim], LL_TIM_TRGO_RESET);
|
||||
LL_TIM_DisableMasterSlaveMode(g_stTimMap[arg->pwmTim]);
|
||||
|
||||
pwmCfg->timOcInitStruct.OCMode = LL_TIM_OCMODE_PWM1; // PWM1 mode
|
||||
pwmCfg->timOcInitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
|
||||
pwmCfg->timOcInitStruct.CompareValue = arg->duty;
|
||||
if (config->polarity == PWM_NORMAL_POLARITY) {
|
||||
pwmCfg->timOcInitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
|
||||
} else {
|
||||
pwmCfg->timOcInitStruct.OCPolarity = LL_TIM_OCPOLARITY_LOW;
|
||||
}
|
||||
pwmCfg->timOcInitStruct.OCIdleState = LL_TIM_OCPOLARITY_LOW;
|
||||
|
||||
LL_TIM_OC_Init(g_stTimMap[arg->pwmTim], g_stChannelMap[arg->pwmCh], &pwmCfg->timOcInitStruct);
|
||||
LL_TIM_OC_DisableFast(g_stTimMap[arg->pwmTim], g_stChannelMap[arg->pwmCh]);
|
||||
|
||||
if (arg->pwmTim == PWM_TIM1 || arg->pwmTim == PWM_TIM8) {
|
||||
LL_TIM_BDTR_InitTypeDef bdtrInitStruct = {0};
|
||||
bdtrInitStruct.OSSRState = LL_TIM_OSSR_DISABLE;
|
||||
bdtrInitStruct.OSSIState = LL_TIM_OSSI_DISABLE;
|
||||
bdtrInitStruct.LockLevel = LL_TIM_LOCKLEVEL_OFF;
|
||||
bdtrInitStruct.DeadTime = 0; // dead area time 200ns 0x28
|
||||
bdtrInitStruct.BreakState = LL_TIM_BREAK_ENABLE;
|
||||
bdtrInitStruct.BreakPolarity = LL_TIM_BREAK_POLARITY_HIGH;
|
||||
bdtrInitStruct.AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_ENABLE;
|
||||
LL_TIM_BDTR_Init(g_stTimMap[arg->pwmTim], &bdtrInitStruct);
|
||||
}
|
||||
|
||||
NVIC_SetPriority(g_stTimIrqMap[arg->pwmTim], NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 1, 1));
|
||||
NVIC_EnableIRQ(g_stTimIrqMap[arg->pwmTim]);
|
||||
|
||||
if (arg->pwmTim == PWM_TIM1 || arg->pwmTim == PWM_TIM8) {
|
||||
LL_TIM_EnableAutomaticOutput(g_stTimMap[arg->pwmTim]);
|
||||
LL_TIM_GenerateEvent_UPDATE(g_stTimMap[arg->pwmTim]);
|
||||
}
|
||||
LL_TIM_EnableCounter(g_stTimMap[arg->pwmTim]);
|
||||
LL_TIM_CC_EnableChannel(g_stTimMap[arg->pwmTim], g_stChannelMap[arg->pwmCh]);
|
||||
LL_TIM_OC_EnablePreload(g_stTimMap[arg->pwmTim], g_stChannelMap[arg->pwmCh]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void DeInitTimPwm(PWM_TIM pwmId, PWM_CH pwmCh)
|
||||
{
|
||||
LL_TIM_DeInit(g_stTimMap[pwmId]);
|
||||
LL_TIM_OC_DisableClear(g_stTimMap[pwmId], g_stChannelMap[pwmCh]);
|
||||
NVIC_DisableIRQ(g_stTimIrqMap[pwmId]);
|
||||
|
||||
LL_TIM_DisableCounter(g_stTimMap[pwmId]);
|
||||
LL_TIM_CC_DisableChannel(g_stTimMap[pwmId], g_stChannelMap[pwmCh]);
|
||||
LL_TIM_OC_DisablePreload(g_stTimMap[pwmId], g_stChannelMap[pwmCh]);
|
||||
|
||||
if (pwmId== PWM_TIM1 || pwmId == PWM_TIM8) {
|
||||
LL_TIM_DisableAutomaticOutput(g_stTimMap[pwmId]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config)
|
||||
{
|
||||
PwmDevice *prvPwm = NULL;
|
||||
PwmConfig *pwmCfg = NULL;
|
||||
PWM_TIM pwmId;
|
||||
PWM_CH pwmCh;
|
||||
PwmResource *resource = NULL;
|
||||
|
||||
if (pwm == NULL || config == NULL || (config->period > PER_SEC_NSEC)) {
|
||||
HDF_LOGE("%s\r\n", __FUNCTION__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
prvPwm = (struct PwmDevice *)PwmGetPriv(pwm);
|
||||
if (prvPwm == NULL) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
resource = &prvPwm->resource;
|
||||
if (resource == NULL) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
pwmCfg = &prvPwm->stPwmCfg;
|
||||
if (pwmCfg == NULL) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
pwmId = prvPwm->resource.pwmTim;
|
||||
pwmCh = prvPwm->resource.pwmCh;
|
||||
|
||||
if (config->status == PWM_ENABLE_STATUS) {
|
||||
PwmFreqArg arg = {0};
|
||||
arg.pwmCh = pwmCh;
|
||||
arg.pwmTim = pwmId;
|
||||
if (InitPwmFreqAndPeriod(config, &arg, resource) != HDF_SUCCESS) {
|
||||
HDF_LOGE("calculate freq and period failed!\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
InitPwmClock(pwmId);
|
||||
InitTimPwm(&arg, config, pwmCfg, resource);
|
||||
} else {
|
||||
DeInitTimPwm(pwmId, pwmCh);
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t PwmDevOpen(struct PwmDev *pwm)
|
||||
{
|
||||
if (pwm == NULL) {
|
||||
HDF_LOGE("%s\r\n", __FUNCTION__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t PwmDevClose(struct PwmDev *pwm)
|
||||
{
|
||||
PwmDevice *prvPwm = NULL;
|
||||
PWM_TIM pwmId;
|
||||
PWM_CH pwmCh;
|
||||
if (pwm == NULL) {
|
||||
HDF_LOGE("%s\r\n", __FUNCTION__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
prvPwm = (PwmDevice *)PwmGetPriv(pwm);
|
||||
if (prvPwm == NULL) {
|
||||
HDF_LOGE("%s\r\n", __FUNCTION__);
|
||||
return HDF_DEV_ERR_NO_DEVICE;
|
||||
}
|
||||
|
||||
pwmId = prvPwm->resource.pwmTim;
|
||||
pwmCh = prvPwm->resource.pwmCh;
|
||||
LL_TIM_DeInit(g_stTimMap[pwmId]);
|
||||
LL_TIM_OC_DisableClear(g_stTimMap[pwmId], g_stChannelMap[pwmCh]);
|
||||
NVIC_DisableIRQ(g_stTimIrqMap[pwmId]);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
@@ -19,10 +19,17 @@ hdf_driver(module_name) {
|
||||
if (defined(LOSCFG_SOC_COMPANY_WINNERMICRO)) {
|
||||
sources += [ "spi_wm.c" ]
|
||||
}
|
||||
if (defined(LOSCFG_SOC_SERIES_STM32F4xx)) {
|
||||
sources += [ "spi_stm32f4xx.c" ]
|
||||
}
|
||||
|
||||
include_dirs = [ "." ]
|
||||
if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/fnlink/shields" ]
|
||||
}
|
||||
if (defined(LOSCFG_NIOBE407_USE_HDF) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/talkweb/niobe407/liteos_m/hdf_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,765 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Talkweb Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "hal_gpio.h"
|
||||
#include "hal_spi.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"
|
||||
#include "hdf_log.h"
|
||||
#endif
|
||||
#include "hdf_base_hal.h"
|
||||
|
||||
#define BITWORD_EIGHT 8
|
||||
#define BITWORD_SIXTEEN 16
|
||||
#define GPIO_STR_MAX 32
|
||||
#define PER_MS_IN_SEC 1000
|
||||
typedef enum {
|
||||
SPI_WORK_MODE_0, // CPOL = 0; CPHA = 0
|
||||
SPI_WORK_MODE_2, // CPOL = 1; CPHA = 0
|
||||
SPI_WORK_MODE_1, // CPOL = 0; CPHA = 1
|
||||
SPI_WORK_MODE_3, // CPOL = 1; CPHA = 1
|
||||
SPI_WORD_MODE_MAX,
|
||||
} SPI_CLK_MODE;
|
||||
|
||||
typedef enum {
|
||||
SPI_TRANSFER_DMA,
|
||||
SPI_TRANSFER_NORMAL,
|
||||
SPI_TRANSFER_MAX,
|
||||
} SPI_TRANS_MODE;
|
||||
|
||||
typedef enum {
|
||||
FULL_DUPLEX = 0,
|
||||
SIMPLE_RX,
|
||||
HALF_RX,
|
||||
HALF_TX,
|
||||
SPI_TRANS_DIR_MAX,
|
||||
} SPI_TRANS_DIR;
|
||||
|
||||
typedef enum {
|
||||
SPI_SLAVE_MODE = 0,
|
||||
SPI_MASTER_MODE,
|
||||
SPI_MASTER_SLAVE_MAX,
|
||||
} SPI_SLAVE_MASTER;
|
||||
|
||||
typedef enum {
|
||||
SPI_DATA_WIDTH_8 = 0,
|
||||
SPI_DATA_WIDTH_16,
|
||||
SPI_DATA_WIDTH_MAX,
|
||||
} SPI_DATA_WIDTH;
|
||||
|
||||
typedef enum {
|
||||
SPI_NSS_SOFT_MODE = 0,
|
||||
SPI_NSS_HARD_INPUT_MODE,
|
||||
SPI_NSS_HARD_OUTPUT_MODE,
|
||||
SPI_NSS_MODE_MAX,
|
||||
} SPI_NSS;
|
||||
|
||||
typedef enum {
|
||||
BAUD_RATE_DIV2 = 0,
|
||||
BAUD_RATE_DIV4,
|
||||
BAUD_RATE_DIV8,
|
||||
BAUD_RATE_DIV16,
|
||||
BAUD_RATE_DIV32,
|
||||
BAUD_RATE_DIV64,
|
||||
BAUD_RATE_DIV128,
|
||||
BAUD_RATE_DIV256,
|
||||
BAUD_RATE_DIV_MAX,
|
||||
} SPI_BAUD_RATE;
|
||||
|
||||
typedef enum {
|
||||
SPI_MSB_FIRST = 0,
|
||||
SPI_LSB_FIRST,
|
||||
SPI_MLSB_MAX,
|
||||
} SPI_BYTE_ORDER;
|
||||
|
||||
typedef enum {
|
||||
CRC_DISABLE = 0,
|
||||
CRC_ENABLE,
|
||||
CRC_STATE_MAX,
|
||||
} CRC_CALULATION;
|
||||
|
||||
typedef enum {
|
||||
SPI_PORT1 = 1,
|
||||
SPI_PORT2,
|
||||
SPI_PORT3,
|
||||
} SPI_GROUPS;
|
||||
|
||||
typedef enum {
|
||||
SPI_PROTO_MOTOROLA = 0,
|
||||
SPI_PROTO_TI,
|
||||
SPI_PROTO_MAX,
|
||||
} SPI_PROTO_STANDARD;
|
||||
|
||||
typedef struct {
|
||||
uint8_t busNum;
|
||||
uint8_t csNum;
|
||||
SPI_TRANS_DIR transDir;
|
||||
SPI_TRANS_MODE transMode;
|
||||
|
||||
SPI_SLAVE_MASTER smMode;
|
||||
SPI_CLK_MODE clkMode;
|
||||
SPI_DATA_WIDTH dataWidth;
|
||||
SPI_NSS nss;
|
||||
|
||||
SPI_BAUD_RATE baudRate;
|
||||
SPI_BYTE_ORDER bitOrder;
|
||||
CRC_CALULATION crcEnable;
|
||||
SPI_GROUPS spix;
|
||||
|
||||
STM32_GPIO_PIN csPin;
|
||||
STM32_GPIO_GROUP csGroup;
|
||||
SPI_PROTO_STANDARD standard;
|
||||
uint8_t dummyByte;
|
||||
|
||||
uint16_t crcPoly;
|
||||
} SpiResource;
|
||||
|
||||
#define HCS_UINT8_PARSE_NUM 16
|
||||
static const char *g_parseHcsMap[HCS_UINT8_PARSE_NUM] = {
|
||||
"busNum",
|
||||
"csNum",
|
||||
"transDir",
|
||||
"transMode",
|
||||
"smMode",
|
||||
"clkMode",
|
||||
"dataWidth",
|
||||
"nss",
|
||||
"baudRate",
|
||||
"bitOrder",
|
||||
"crcEnable",
|
||||
"spix",
|
||||
"csPin",
|
||||
"csGpiox",
|
||||
"standard",
|
||||
"dummyByte",
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct OsalSem* sem;
|
||||
struct OsalMutex* mutex;
|
||||
SPI_TypeDef* spix;
|
||||
} SPI_CONTEXT_T;
|
||||
|
||||
typedef struct {
|
||||
uint32_t spiId;
|
||||
SpiResource resource;
|
||||
} SpiDevice;
|
||||
|
||||
static uint32_t g_transDirMaps[SPI_TRANS_DIR_MAX] = {
|
||||
LL_SPI_FULL_DUPLEX,
|
||||
LL_SPI_SIMPLEX_RX,
|
||||
LL_SPI_HALF_DUPLEX_RX,
|
||||
LL_SPI_HALF_DUPLEX_TX,
|
||||
};
|
||||
|
||||
static uint32_t g_nssMaps[SPI_NSS_MODE_MAX] = {
|
||||
LL_SPI_NSS_SOFT,
|
||||
LL_SPI_NSS_HARD_INPUT,
|
||||
LL_SPI_NSS_HARD_OUTPUT,
|
||||
};
|
||||
|
||||
static uint32_t g_baudMaps[BAUD_RATE_DIV_MAX] = {
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV2,
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV4,
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV8,
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV16,
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV32,
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV64,
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV128,
|
||||
LL_SPI_BAUDRATEPRESCALER_DIV256,
|
||||
};
|
||||
|
||||
static SPI_TypeDef* g_spiGroupMaps[SPI_PORT3] = {
|
||||
SPI1,
|
||||
SPI2,
|
||||
SPI3,
|
||||
};
|
||||
|
||||
static void EnableSpiClock(uint32_t spiNum)
|
||||
{
|
||||
switch (spiNum) {
|
||||
case SPI_PORT1:
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
break;
|
||||
case SPI_PORT2:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
break;
|
||||
case SPI_PORT3:
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI3);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static SPI_CONTEXT_T spiContext[SPI_PORT3] = {
|
||||
{
|
||||
.sem = {NULL},
|
||||
.mutex = {NULL},
|
||||
.spix = {NULL},
|
||||
},
|
||||
{
|
||||
.sem = {NULL},
|
||||
.mutex = {NULL},
|
||||
.spix = {NULL},
|
||||
},
|
||||
{
|
||||
.sem = {NULL},
|
||||
.mutex = {NULL},
|
||||
.spix = {NULL},
|
||||
},
|
||||
};
|
||||
|
||||
int32_t HalSpiSend(SpiDevice *spiDevice, const uint8_t *data, uint16_t size)
|
||||
{
|
||||
uint32_t spiId;
|
||||
SpiResource *resource = NULL;
|
||||
|
||||
if (spiDevice == NULL || data == NULL || size == 0) {
|
||||
HDF_LOGE("spi input para err\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
spiId = spiDevice->spiId;
|
||||
resource = &spiDevice->resource;
|
||||
if (resource == NULL) {
|
||||
HDF_LOGE("resource is null\r\n");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (resource->transMode == SPI_TRANSFER_DMA) {
|
||||
return HDF_ERR_INVALID_PARAM; // unsupport now
|
||||
} else {
|
||||
uint8_t readData;
|
||||
while (size--) {
|
||||
readData = LL_SPI_Transmit(spiContext[spiId].spix, *data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t HalSpiRecv(SpiDevice *spiDevice, uint8_t *data, uint16_t size)
|
||||
{
|
||||
uint32_t len = size;
|
||||
uint32_t remainder = 0;
|
||||
uint8_t *cmd = NULL;
|
||||
uint32_t spiId;
|
||||
SpiResource *resource = NULL;
|
||||
if (spiDevice == NULL || data == NULL || size == 0) {
|
||||
HDF_LOGE("spi input para err\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
spiId = spiDevice->spiId;
|
||||
resource = &spiDevice->resource;
|
||||
if (resource == NULL) {
|
||||
HDF_LOGE("resource is null\r\n");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
cmd = (uint8_t *)OsalMemAlloc(len);
|
||||
if (cmd == NULL) {
|
||||
HDF_LOGE("%s OsalMemAlloc size %ld error\r\n", __FUNCTION__, len);
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
|
||||
memset_s(cmd, len, resource->dummyByte, len);
|
||||
|
||||
if (resource->transMode == SPI_TRANSFER_DMA) {
|
||||
return HDF_ERR_INVALID_PARAM; // unsupport now
|
||||
} else {
|
||||
while (len--) {
|
||||
*data = LL_SPI_Transmit(spiContext[spiId].spix, *cmd);
|
||||
data++;
|
||||
cmd++;
|
||||
}
|
||||
}
|
||||
|
||||
OsalMemFree(cmd);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t HalSpiSendRecv(SpiDevice *spiDevice, uint8_t *txData,
|
||||
uint16_t txSize, uint8_t *rxData, uint16_t rxSize)
|
||||
{
|
||||
uint32_t spiId;
|
||||
uint8_t* data = rxData;
|
||||
int16_t dropSize = 0;
|
||||
SpiResource *resource = NULL;
|
||||
if (spiDevice == NULL || txData == NULL || txSize == 0 || rxData == NULL || rxSize == 0) {
|
||||
HDF_LOGE("spi input para err\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
spiId = spiDevice->spiId;
|
||||
resource = &spiDevice->resource;
|
||||
|
||||
if (resource->transMode == SPI_TRANSFER_DMA) {
|
||||
return HDF_ERR_INVALID_PARAM; // unsupport now
|
||||
} else {
|
||||
while (rxSize--) {
|
||||
*rxData = LL_SPI_Transmit(spiContext[spiId].spix, *txData);
|
||||
rxData++;
|
||||
txData++;
|
||||
}
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void InitSpiInitStruct(LL_SPI_InitTypeDef *spiInitStruct, const SpiResource *resource)
|
||||
{
|
||||
spiInitStruct->TransferDirection = g_transDirMaps[resource->transDir];
|
||||
if (resource->smMode == SPI_SLAVE_MODE) {
|
||||
spiInitStruct->Mode = LL_SPI_MODE_SLAVE;
|
||||
} else {
|
||||
spiInitStruct->Mode = LL_SPI_MODE_MASTER;
|
||||
}
|
||||
|
||||
if (resource->dataWidth == SPI_DATA_WIDTH_8) {
|
||||
spiInitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT;
|
||||
} else {
|
||||
spiInitStruct->DataWidth = LL_SPI_DATAWIDTH_16BIT;
|
||||
}
|
||||
|
||||
switch (resource->clkMode) {
|
||||
case SPI_WORK_MODE_0:
|
||||
spiInitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
spiInitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
break;
|
||||
case SPI_WORK_MODE_1:
|
||||
spiInitStruct->ClockPolarity = LL_SPI_POLARITY_HIGH;
|
||||
spiInitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
break;
|
||||
case SPI_WORK_MODE_2:
|
||||
spiInitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
spiInitStruct->ClockPhase = LL_SPI_PHASE_2EDGE;
|
||||
break;
|
||||
case SPI_WORK_MODE_3:
|
||||
spiInitStruct->ClockPolarity = LL_SPI_POLARITY_HIGH;
|
||||
spiInitStruct->ClockPhase = LL_SPI_PHASE_2EDGE;
|
||||
break;
|
||||
default:
|
||||
spiInitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
spiInitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
}
|
||||
|
||||
spiInitStruct->NSS = g_nssMaps[resource->nss];
|
||||
spiInitStruct->BaudRate = g_baudMaps[resource->baudRate];
|
||||
|
||||
if (resource->bitOrder == SPI_MSB_FIRST) {
|
||||
spiInitStruct->BitOrder = LL_SPI_MSB_FIRST;
|
||||
} else {
|
||||
spiInitStruct->BitOrder = LL_SPI_LSB_FIRST;
|
||||
}
|
||||
|
||||
if (resource->crcEnable == CRC_DISABLE) {
|
||||
spiInitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
|
||||
} else {
|
||||
spiInitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_ENABLE;
|
||||
}
|
||||
spiInitStruct->CRCPoly = resource->crcPoly;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int32_t InitSpiDevice(SpiDevice *spiDevice)
|
||||
{
|
||||
uint32_t spiPort;
|
||||
SpiResource *resource = NULL;
|
||||
if (spiDevice == NULL) {
|
||||
HDF_LOGE("%s: invalid parameter\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
LL_SPI_InitTypeDef spiInitStruct = {0};
|
||||
resource = &spiDevice->resource;
|
||||
spiPort = spiDevice->spiId;
|
||||
EnableSpiClock(spiPort + 1);
|
||||
InitSpiInitStruct(&spiInitStruct, resource);
|
||||
SPI_TypeDef* spix = g_spiGroupMaps[resource->spix];
|
||||
|
||||
spiContext[spiPort].spix = spix;
|
||||
LL_SPI_Disable(spix);
|
||||
uint8_t ret = LL_SPI_Init(spix, &spiInitStruct);
|
||||
if (ret != 0) {
|
||||
HDF_LOGE("HAL INIT SPI FAILED\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resource->standard == SPI_PROTO_MOTOROLA) {
|
||||
LL_SPI_SetStandard(spix, LL_SPI_PROTOCOL_MOTOROLA);
|
||||
} else {
|
||||
LL_SPI_SetStandard(spix, LL_SPI_PROTOCOL_TI);
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
#define SPI_FIND_CONFIG(node, name, resource, spiDevice) \
|
||||
do { \
|
||||
if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
|
||||
resource->busNum = HCS_PROP(node, busNum); \
|
||||
spiDevice->spiId = resource->busNum; \
|
||||
resource->csNum = HCS_PROP(node, csNum); \
|
||||
resource->transDir = HCS_PROP(node, transDir); \
|
||||
resource->transMode = HCS_PROP(node, transMode); \
|
||||
resource->smMode = HCS_PROP(node, smMode); \
|
||||
resource->dataWidth = HCS_PROP(node, dataWidth); \
|
||||
resource->clkMode = HCS_PROP(node, clkMode); \
|
||||
resource->csNum = HCS_PROP(node, csNum); \
|
||||
resource->nss = HCS_PROP(node, nss); \
|
||||
resource->baudRate = HCS_PROP(node, baudRate); \
|
||||
resource->bitOrder = HCS_PROP(node, bitOrder); \
|
||||
resource->crcEnable = HCS_PROP(node, crcEnable); \
|
||||
resource->crcPoly = HCS_PROP(node, crcPoly); \
|
||||
resource->spix = HCS_PROP(node, spix); \
|
||||
resource->csPin = HCS_PROP(node, csPin); \
|
||||
resource->csGroup = HCS_PROP(node, csGpiox); \
|
||||
resource->standard = HCS_PROP(node, standard); \
|
||||
resource->dummyByte = HCS_PROP(node, dummyByte); \
|
||||
result = HDF_SUCCESS; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
|
||||
#define PLATFORM_SPI_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), spi_config)
|
||||
static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const char *deviceMatchAttr)
|
||||
{
|
||||
int32_t result = HDF_FAILURE;
|
||||
SpiResource *resource = NULL;
|
||||
if (spiDevice == NULL || deviceMatchAttr == NULL) {
|
||||
HDF_LOGE("device or deviceMatchAttr is NULL\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
resource = &spiDevice->resource;
|
||||
#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, spi_config)
|
||||
HCS_FOREACH_CHILD_VARGS(PLATFORM_SPI_CONFIG, SPI_FIND_CONFIG, deviceMatchAttr, resource, spiDevice);
|
||||
#endif
|
||||
if (result != HDF_SUCCESS) {
|
||||
HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const struct DeviceResourceNode *resourceNode)
|
||||
{
|
||||
struct DeviceResourceIface *dri = NULL;
|
||||
if (spiDevice == NULL || resourceNode == NULL) {
|
||||
HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
SpiResource *resource = NULL;
|
||||
resource = &spiDevice->resource;
|
||||
if (resource == NULL) {
|
||||
HDF_LOGE("%s: resource is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); // open HDF
|
||||
if (dri == NULL || dri->GetUint16 == NULL || dri->GetUint8 == NULL || dri->GetUint32 == NULL) {
|
||||
HDF_LOGE("DeviceResourceIface is invalid\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
uint8_t temp[HCS_UINT8_PARSE_NUM] = {0};
|
||||
for (int i = 0; i < HCS_UINT8_PARSE_NUM; i++) {
|
||||
if (dri->GetUint8(resourceNode, g_parseHcsMap[i], &temp[i], 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("get config %s failed\r\n", g_parseHcsMap[i]);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
}
|
||||
int ret = memcpy_s(resource, HCS_UINT8_PARSE_NUM, temp, HCS_UINT8_PARSE_NUM);
|
||||
if (ret != 0) {
|
||||
HDF_LOGE("memcpy failed\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint16(resourceNode, "crcPoly", &resource->crcPoly, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("get config %s failed\r\n", "crcPoly");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
spiDevice->spiId = resource->busNum;
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
SpiDevice *spiDevice = NULL;
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
if (spiCntlr == NULL || device == NULL) {
|
||||
#else
|
||||
if (spiCntlr == NULL || device == NULL || device->property == NULL) {
|
||||
#endif
|
||||
HDF_LOGE("%s: property is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
spiDevice = (SpiDevice *)OsalMemAlloc(sizeof(SpiDevice));
|
||||
if (spiDevice == NULL) {
|
||||
HDF_LOGE("%s: OsalMemAlloc spiDevice error\r\n", __func__);
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
ret = GetSpiDeviceResource(spiDevice, device->deviceMatchAttr);
|
||||
#else
|
||||
ret = GetSpiDeviceResource(spiDevice, device->property);
|
||||
#endif
|
||||
if (ret != HDF_SUCCESS) {
|
||||
(void)OsalMemFree(spiDevice);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
spiCntlr->priv = spiDevice;
|
||||
spiCntlr->busNum = spiDevice->spiId;
|
||||
InitSpiDevice(spiDevice);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
/* SPI Method */
|
||||
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);
|
||||
|
||||
struct SpiCntlrMethod g_twSpiCntlrMethod = {
|
||||
.GetCfg = SpiDevGetCfg,
|
||||
.SetCfg = SpiDevSetCfg,
|
||||
.Transfer = SpiDevTransfer,
|
||||
.Open = SpiDevOpen,
|
||||
.Close = SpiDevClose,
|
||||
};
|
||||
|
||||
/* HdfDriverEntry method definitions */
|
||||
static int32_t SpiDriverBind(struct HdfDeviceObject *device);
|
||||
static int32_t SpiDriverInit(struct HdfDeviceObject *device);
|
||||
static void SpiDriverRelease(struct HdfDeviceObject *device);
|
||||
|
||||
/* HdfDriverEntry definitions */
|
||||
struct HdfDriverEntry g_SpiDriverEntry = {
|
||||
.moduleVersion = 1,
|
||||
.moduleName = "ST_SPI_MODULE_HDF",
|
||||
.Bind = SpiDriverBind,
|
||||
.Init = SpiDriverInit,
|
||||
.Release = SpiDriverRelease,
|
||||
};
|
||||
|
||||
HDF_INIT(g_SpiDriverEntry);
|
||||
|
||||
static int32_t SpiDriverBind(struct HdfDeviceObject *device)
|
||||
{
|
||||
struct SpiCntlr *spiCntlr = NULL;
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("Sample device object is null!\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
HDF_LOGI("Enter %s:\r\n", __func__);
|
||||
spiCntlr = SpiCntlrCreate(device);
|
||||
if (spiCntlr == NULL) {
|
||||
HDF_LOGE("SpiCntlrCreate object is null!\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SpiDriverInit(struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SpiCntlr *spiCntlr = NULL;
|
||||
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
HDF_LOGI("Enter %s:", __func__);
|
||||
spiCntlr = SpiCntlrFromDevice(device);
|
||||
if (spiCntlr == NULL) {
|
||||
HDF_LOGE("%s: spiCntlr is NULL", __func__);
|
||||
return HDF_DEV_ERR_NO_DEVICE;
|
||||
}
|
||||
|
||||
ret = AttachSpiDevice(spiCntlr, device); // SpiCntlr add TWSpiDevice to priv
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: attach error\r\n", __func__);
|
||||
return HDF_DEV_ERR_ATTACHDEV_FAIL;
|
||||
}
|
||||
|
||||
spiCntlr->method = &g_twSpiCntlrMethod; // register callback
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SpiDriverRelease(struct HdfDeviceObject *device)
|
||||
{
|
||||
struct SpiCntlr *spiCntlr = NULL;
|
||||
SpiDevice *spiDevice = NULL;
|
||||
|
||||
HDF_LOGI("Enter %s\r\n", __func__);
|
||||
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is NULL\r\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
spiCntlr = SpiCntlrFromDevice(device);
|
||||
if (spiCntlr == NULL || spiCntlr->priv == NULL) {
|
||||
HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
spiDevice = (SpiDevice *)spiCntlr->priv;
|
||||
OsalMemFree(spiDevice);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr)
|
||||
{
|
||||
HDF_LOGI("Enter %s\r\n", __func__);
|
||||
uint32_t spiPort;
|
||||
SpiDevice *spiDevice = NULL;
|
||||
|
||||
spiDevice = (SpiDevice*)spiCntlr->priv;
|
||||
spiPort = spiDevice->spiId;
|
||||
SPI_TypeDef* spix = g_spiGroupMaps[spiDevice->resource.spix];
|
||||
LL_SPI_Enable(spix);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SpiDevClose(struct SpiCntlr *spiCntlr)
|
||||
{
|
||||
uint32_t spiPort;
|
||||
SpiDevice *spiDevice = NULL;
|
||||
|
||||
spiDevice = (SpiDevice*)spiCntlr->priv;
|
||||
spiPort = spiDevice->spiId;
|
||||
SPI_TypeDef* spix = g_spiGroupMaps[spiDevice->resource.spix];
|
||||
LL_SPI_Disable(spix);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
|
||||
{
|
||||
SpiDevice *spiDevice = NULL;
|
||||
if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
|
||||
HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
spiDevice = (SpiDevice *)spiCntlr->priv;
|
||||
if (spiDevice == NULL) {
|
||||
return HDF_DEV_ERR_NO_DEVICE;
|
||||
}
|
||||
spiCfg->maxSpeedHz = spiDevice->resource.baudRate;
|
||||
spiCfg->mode = spiDevice->resource.clkMode;
|
||||
spiCfg->transferMode = spiDevice->resource.transMode;
|
||||
spiCfg->bitsPerWord = spiDevice->resource.dataWidth;
|
||||
|
||||
if (spiDevice->resource.dataWidth) {
|
||||
spiCfg->bitsPerWord = BITWORD_SIXTEEN;
|
||||
} else {
|
||||
spiCfg->bitsPerWord = BITWORD_EIGHT;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
|
||||
{
|
||||
SpiDevice *spiDevice = NULL;
|
||||
if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
|
||||
HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
spiDevice = (SpiDevice *)spiCntlr->priv;
|
||||
if (spiDevice == NULL) {
|
||||
HDF_LOGE("%s: spiDevice is NULL\r\n", __func__);
|
||||
return HDF_DEV_ERR_NO_DEVICE;
|
||||
}
|
||||
|
||||
spiDevice->resource.baudRate = spiCfg->maxSpeedHz;
|
||||
spiDevice->resource.clkMode = spiCfg->mode;
|
||||
spiDevice->resource.transMode = spiCfg->transferMode;
|
||||
if (spiCfg->bitsPerWord == BITWORD_EIGHT) {
|
||||
spiDevice->resource.dataWidth = SPI_DATA_WIDTH_8;
|
||||
} else {
|
||||
spiDevice->resource.dataWidth = SPI_DATA_WIDTH_16;
|
||||
}
|
||||
|
||||
return InitSpiDevice(spiDevice);
|
||||
}
|
||||
|
||||
static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count)
|
||||
{
|
||||
uint32_t spiId;
|
||||
SpiDevice *spiDevice = NULL;
|
||||
uint32_t ticks = 0;
|
||||
uint8_t singleCsChange = 0;
|
||||
struct SpiMsg *msg = NULL;
|
||||
if (spiCntlr == NULL || spiCntlr->priv == NULL) {
|
||||
HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
spiDevice = (SpiDevice *)spiCntlr->priv;
|
||||
spiId = spiDevice->spiId;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
msg = &spiMsg[i];
|
||||
LL_GPIO_ResetOutputPin(LL_GET_GPIOX(spiDevice->resource.csGroup), LL_GET_HAL_PIN(spiDevice->resource.csPin));
|
||||
|
||||
if ((msg->rbuf == NULL) && (msg->wbuf != NULL)) {
|
||||
singleCsChange = msg->wbuf[0];
|
||||
|
||||
if (msg->len == 1) {
|
||||
goto CS_DOWN;
|
||||
}
|
||||
HalSpiSend(spiDevice, msg->wbuf + 1, msg->len - 1);
|
||||
}
|
||||
|
||||
if ((msg->rbuf != NULL) && (msg->wbuf == NULL)) {
|
||||
singleCsChange = msg->rbuf[0];
|
||||
|
||||
if (msg->len == 1) {
|
||||
goto CS_DOWN;
|
||||
}
|
||||
HalSpiRecv(spiDevice, msg->rbuf + 1, msg->len - 1);
|
||||
}
|
||||
|
||||
if ((msg->wbuf != NULL) && (msg->rbuf != NULL)) {
|
||||
HalSpiSendRecv(spiDevice, msg->wbuf, msg->len, msg->rbuf, msg->len);
|
||||
}
|
||||
|
||||
if (msg->csChange || singleCsChange) {
|
||||
LL_GPIO_SetOutputPin(LL_GET_GPIOX(spiDevice->resource.csGroup), LL_GET_HAL_PIN(spiDevice->resource.csPin));
|
||||
}
|
||||
if (msg->delayUs > 0) {
|
||||
ticks = (msg->delayUs / PER_MS_IN_SEC);
|
||||
osDelay(ticks);
|
||||
}
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
CS_DOWN:
|
||||
if (msg->csChange || singleCsChange) {
|
||||
LL_GPIO_SetOutputPin(LL_GET_GPIOX(spiDevice->resource.csGroup), LL_GET_HAL_PIN(spiDevice->resource.csPin));
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -25,10 +25,17 @@ hdf_driver(module_name) {
|
||||
if (defined(LOSCFG_SOC_COMPANY_WINNERMICRO)) {
|
||||
sources += [ "uart_wm.c" ]
|
||||
}
|
||||
if (defined(LOSCFG_SOC_SERIES_STM32F4xx)) {
|
||||
sources += [ "uart_stm32f4xx.c" ]
|
||||
}
|
||||
|
||||
include_dirs = [ "." ]
|
||||
if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/fnlink/shields" ]
|
||||
}
|
||||
if (defined(LOSCFG_NIOBE407_USE_HDF) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/talkweb/niobe407/liteos_m/hdf_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,4 +26,8 @@ hdf_driver(module_name) {
|
||||
}
|
||||
|
||||
include_dirs = [ "." ]
|
||||
if (defined(LOSCFG_NIOBE407_USE_HDF) &&
|
||||
defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) {
|
||||
deps = [ "//device/board/talkweb/niobe407/liteos_m/hdf_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
Executable → Regular
+46
-3
@@ -8,7 +8,12 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.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_device_desc.h"
|
||||
#include "hdf_log.h"
|
||||
#include "watchdog_core.h"
|
||||
@@ -54,6 +59,35 @@ static int InitWatchdogDeviceInfo(WatchdogDeviceInfo *watchdogdeviceinfo)
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
#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\r\n");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, watchdog_config)
|
||||
HCS_FOREACH_CHILD_VARGS(PLATFORM_WATCHDOG_CONFIG, WATCHDOG_FIND_CONFIG, deviceMatchAttr, device);
|
||||
#endif
|
||||
if (result != HDF_SUCCESS) {
|
||||
HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
|
||||
return result;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#else
|
||||
static uint32_t GetWatchdogDeviceInfoResource(WatchdogDeviceInfo *device, const struct DeviceResourceNode *resourceNode)
|
||||
{
|
||||
struct DeviceResourceIface *dri = NULL;
|
||||
@@ -76,19 +110,24 @@ static uint32_t GetWatchdogDeviceInfoResource(WatchdogDeviceInfo *device, const
|
||||
HDF_LOGE("read watchdogId fail\r\n");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
HDF_LOGI("watchdogId = %d\n", device->watchdogId);
|
||||
HDF_LOGI("timeout = %dms\n", device->timeout);
|
||||
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t AttachWatchdogDeviceInfo(struct WatchdogCntlr *watchdogCntlr, struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
if (device == NULL || device->deviceMatchAttr == NULL) {
|
||||
#else
|
||||
if (device == NULL || device->property == NULL) {
|
||||
#endif
|
||||
HDF_LOGE("%s: param is NULL\r\n", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
@@ -99,7 +138,11 @@ static int32_t AttachWatchdogDeviceInfo(struct WatchdogCntlr *watchdogCntlr, str
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
|
||||
ret = GetWatchdogDeviceInfoResource(watchdogdeviceinfo, device->deviceMatchAttr);
|
||||
#else
|
||||
ret = GetWatchdogDeviceInfoResource(watchdogdeviceinfo, device->property);
|
||||
#endif
|
||||
if (ret != HDF_SUCCESS) {
|
||||
(void)OsalMemFree(watchdogdeviceinfo);
|
||||
return HDF_FAILURE;
|
||||
@@ -177,7 +220,7 @@ static int32_t WatchdogDriverInit(struct HdfDeviceObject *device)
|
||||
}
|
||||
|
||||
watchdogCntlr->ops = &g_WatchdogCntlrMethod;
|
||||
|
||||
|
||||
HDF_LOGI("WatchdogDriverInit success!\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user