mirror of
https://github.com/openharmony/drivers_framework.git
synced 2026-08-27 02:42:28 -04:00
!605 feat: Relocate driver sample code
Merge pull request !605 from 郭东奇/OpenHarmony-3.0-LTS
This commit is contained in:
Executable
+18
@@ -0,0 +1,18 @@
|
||||
root {
|
||||
device_info {
|
||||
platform :: host {
|
||||
hostName = "platform_host";
|
||||
priority = 50;
|
||||
device_uart :: device {
|
||||
device5 :: deviceNode {
|
||||
policy = 2;
|
||||
priority = 10;
|
||||
permission = 0660;
|
||||
moduleName = "UART_SAMPLE";
|
||||
serviceName = "HDF_PLATFORM_UART_5";
|
||||
deviceMatchAttr = "sample_uart_5";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
root {
|
||||
platform {
|
||||
uart_sample {
|
||||
num = 5;
|
||||
base = 0x120a0000; // UART base register address
|
||||
irqNum = 38;
|
||||
baudrate = 115200;
|
||||
uartClk = 24000000; // 24 M
|
||||
wlen = 0x60; // 8 bit width
|
||||
parity = 0;
|
||||
stopBit = 0;
|
||||
match_attr = "sample_uart_5";
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2021 Huawei Device 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.
|
||||
|
||||
import("//build/lite/config/component/lite_component.gni")
|
||||
|
||||
lite_component("hello_uart_sample") {
|
||||
features = [
|
||||
"dev:hello_uart",
|
||||
"dispatch:hello_uart_dispatch",
|
||||
]
|
||||
}
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2021 Huawei Device 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.
|
||||
|
||||
config DRIVERS_HDF_PLATFORM_UART_SAMPLE
|
||||
bool "Enable HDF platform uart sample driver"
|
||||
default n
|
||||
depends on DRIVERS_HDF_PLATFORM
|
||||
help
|
||||
Answer Y to enable HDF platform uart sample driver.
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) 2021 Huawei Device 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.
|
||||
|
||||
HDF_FRAMEWORKS = "//drivers/framework"
|
||||
|
||||
executable("hello_uart") {
|
||||
sources = [ "hello_uart_dev.c" ]
|
||||
|
||||
include_dirs = [
|
||||
"$HDF_FRAMEWORKS/ability/sbuf/include",
|
||||
"$HDF_FRAMEWORKS/core/shared/include",
|
||||
"$HDF_FRAMEWORKS/core/host/include",
|
||||
"$HDF_FRAMEWORKS/core/master/include",
|
||||
"$HDF_FRAMEWORKS/include/core",
|
||||
"$HDF_FRAMEWORKS/include/utils",
|
||||
"$HDF_FRAMEWORKS/utils/include",
|
||||
"$HDF_FRAMEWORKS/include/osal",
|
||||
"//drivers/adapter/uhdf/posix/include",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
|
||||
"//drivers/adapter/uhdf/manager:hdf_core",
|
||||
"//drivers/adapter/uhdf/posix:hdf_posix_osal",
|
||||
]
|
||||
|
||||
public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
|
||||
defines = [ "__USER__" ]
|
||||
|
||||
cflags = [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wno-format",
|
||||
"-Wno-format-extra-args",
|
||||
]
|
||||
}
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "hdf_log.h"
|
||||
|
||||
#define HDF_LOG_TAG hello_uart
|
||||
#define INFO_SIZE 16
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ret;
|
||||
int fd;
|
||||
const char info[INFO_SIZE] = {" HELLO UART! "};
|
||||
|
||||
fd = open("/dev/uartdev-5", O_RDWR);
|
||||
if (fd < 0) {
|
||||
HDF_LOGE("uartdev-5 open failed %d", fd);
|
||||
return -1;
|
||||
}
|
||||
ret = write(fd, info, INFO_SIZE);
|
||||
if (ret != 0) {
|
||||
HDF_LOGE("write uartdev-5 ret is %d", ret);
|
||||
}
|
||||
ret = close(fd);
|
||||
if (ret != 0) {
|
||||
HDF_LOGE("uartdev-5 close failed %d", fd);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2021 Huawei Device 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.
|
||||
|
||||
HDF_FRAMEWORKS = "//drivers/framework"
|
||||
|
||||
executable("hello_uart_dispatch") {
|
||||
sources = [
|
||||
"hello_uart_dispatch.c",
|
||||
"uart_if.c",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"$HDF_FRAMEWORKS/ability/sbuf/include",
|
||||
"$HDF_FRAMEWORKS/core/shared/include",
|
||||
"$HDF_FRAMEWORKS/core/host/include",
|
||||
"$HDF_FRAMEWORKS/core/master/include",
|
||||
"$HDF_FRAMEWORKS/include/core",
|
||||
"$HDF_FRAMEWORKS/include/utils",
|
||||
"$HDF_FRAMEWORKS/utils/include",
|
||||
"$HDF_FRAMEWORKS/include/osal",
|
||||
"//drivers/adapter/uhdf/posix/include",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
|
||||
"//drivers/adapter/uhdf/manager:hdf_core",
|
||||
"//drivers/adapter/uhdf/posix:hdf_posix_osal",
|
||||
]
|
||||
|
||||
public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
|
||||
defines = [ "__USER__" ]
|
||||
|
||||
cflags = [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wno-format",
|
||||
"-Wno-format-extra-args",
|
||||
]
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 <string.h>
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "uart_if.h"
|
||||
|
||||
#define HDF_LOG_TAG hello_uart_dispatch
|
||||
#define UART_PORT 5
|
||||
|
||||
int main()
|
||||
{
|
||||
const char *info = " HELLO UART! ";
|
||||
|
||||
struct DevHandle *handle = UartOpen(UART_PORT);
|
||||
if (handle == NULL) {
|
||||
HDF_LOGE("Failed to open uart %d", UART_PORT);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
int ret = UartWrite(handle, (uint8_t *)info, strlen(info));
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("Failed to send data to uart");
|
||||
}
|
||||
|
||||
UartClose(handle);
|
||||
return ret;
|
||||
}
|
||||
Executable
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 "uart_if.h"
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "hdf_io_service_if.h"
|
||||
|
||||
#define HDF_LOG_TAG uart_if
|
||||
|
||||
struct DevHandle *UartOpen(uint32_t port)
|
||||
{
|
||||
int32_t ret;
|
||||
struct DevHandle *handle = NULL;
|
||||
char *serviceName = NULL;
|
||||
|
||||
handle = (struct DevHandle *)OsalMemCalloc(sizeof(struct DevHandle));
|
||||
if (handle == NULL) {
|
||||
HDF_LOGE("Failed to OsalMemCalloc handle");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
serviceName = (char *)OsalMemCalloc(sizeof(char) * (MAX_DEV_NAME_SIZE + 1));
|
||||
if (serviceName == NULL) {
|
||||
HDF_LOGE("Failed to OsalMemCalloc serviceName");
|
||||
OsalMemFree(handle);
|
||||
return NULL;
|
||||
}
|
||||
ret = snprintf_s(serviceName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, UART_DEV_SERVICE_NAME_PREFIX, port);
|
||||
if (ret < 0) {
|
||||
HDF_LOGE("Failed to snprintf_s");
|
||||
OsalMemFree(handle);
|
||||
OsalMemFree(serviceName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct HdfIoService *service = HdfIoServiceBind(serviceName);
|
||||
if (service == NULL) {
|
||||
HDF_LOGE("Failed to get service %s", serviceName);
|
||||
OsalMemFree(handle);
|
||||
OsalMemFree(serviceName);
|
||||
return NULL;
|
||||
}
|
||||
OsalMemFree(serviceName);
|
||||
handle->object = service;
|
||||
return handle;
|
||||
}
|
||||
|
||||
int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size)
|
||||
{
|
||||
int ret;
|
||||
struct HdfIoService *service = NULL;
|
||||
|
||||
if (handle == NULL || handle->object == NULL) {
|
||||
HDF_LOGE("handle or handle->object is NULL");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
struct HdfSBuf *sBuf = HdfSBufObtainDefaultSize();
|
||||
if (sBuf == NULL) {
|
||||
HDF_LOGE("Failed to obtain sBuf");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (!HdfSbufWriteBuffer(sBuf, data, size)) {
|
||||
HDF_LOGE("Failed to write sbuf");
|
||||
HdfSBufRecycle(sBuf);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
service = (struct HdfIoService *)handle->object;
|
||||
ret = service->dispatcher->Dispatch(&service->object, UART_WRITE, sBuf, NULL);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("Failed to send service call");
|
||||
}
|
||||
HdfSBufRecycle(sBuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UartClose(struct DevHandle *handle)
|
||||
{
|
||||
struct HdfIoService *service = NULL;
|
||||
|
||||
if (handle == NULL || handle->object == NULL) {
|
||||
HDF_LOGE("handle or handle->object is NULL");
|
||||
return;
|
||||
}
|
||||
service = (struct HdfIoService *)handle->object;
|
||||
HdfIoServiceRecycle(service);
|
||||
OsalMemFree(handle);
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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.
|
||||
*/
|
||||
|
||||
#ifndef UART_IF_H
|
||||
#define UART_IF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define UART_DEV_SERVICE_NAME_PREFIX "HDF_PLATFORM_UART_%d"
|
||||
#define MAX_DEV_NAME_SIZE 32
|
||||
|
||||
enum {
|
||||
UART_WRITE = 1
|
||||
};
|
||||
|
||||
struct DevHandle {
|
||||
void *object;
|
||||
};
|
||||
|
||||
struct DevHandle *UartOpen(uint32_t port);
|
||||
int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size);
|
||||
void UartClose(struct DevHandle *handle);
|
||||
|
||||
#endif // UART_IF_H
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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.
|
||||
*/
|
||||
|
||||
#ifndef BUF_FIFO_H
|
||||
#define BUF_FIFO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct BufferFifo {
|
||||
volatile uint32_t readPosition;
|
||||
volatile uint32_t writePosition;
|
||||
uint16_t bufSizeMask;
|
||||
uint8_t *buffer;
|
||||
};
|
||||
|
||||
static inline uint16_t BufferFifoGetDataSize(struct BufferFifo *fifo)
|
||||
{
|
||||
return (fifo->writePosition - fifo->readPosition);
|
||||
}
|
||||
|
||||
static inline bool IsPowerOfTwo(int num)
|
||||
{
|
||||
return (num > 0) && (num & (num - 1)) == 0;
|
||||
}
|
||||
|
||||
bool BufferFifoInit(struct BufferFifo *fifo, uint8_t *buf, uint16_t bufSize);
|
||||
|
||||
#endif // BUF_FIFO_H
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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.
|
||||
*/
|
||||
|
||||
#ifndef UART_DEV_SAMPLE_H
|
||||
#define UART_DEV_SAMPLE_H
|
||||
|
||||
#include "sys/ioctl.h"
|
||||
#include "uart_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define UART_IOC_MAGIC 'u'
|
||||
|
||||
/* baudrate config */
|
||||
#define UART_CFG_BAUDRATE _IO(UART_IOC_MAGIC, 1)
|
||||
|
||||
void AddUartDevice(struct UartHost *host);
|
||||
void RemoveUartDevice(struct UartHost *host);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* UART_DEV_SAMPLE_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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.
|
||||
*/
|
||||
|
||||
#ifndef UART_DISPATCH_SAMPLE_H
|
||||
#define UART_DISPATCH_SAMPLE_H
|
||||
|
||||
#include "uart_pl011_sample.h"
|
||||
|
||||
enum {
|
||||
UART_WRITE = 1
|
||||
};
|
||||
|
||||
int32_t SampleDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply);
|
||||
|
||||
#endif // UART_DISPATCH_SAMPLE_H
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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.
|
||||
*/
|
||||
|
||||
#ifndef UART_PL011_SAMPLE_H
|
||||
#define UART_PL011_SAMPLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hdf_device_desc.h"
|
||||
#include "buf_fifo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct UartRegisterMap {
|
||||
volatile uint32_t dr; /* Offset: 0x000 TYPE: (RW) Data register */
|
||||
union {
|
||||
volatile uint32_t rsr; /* Offset: 0x004 TYPE: (RO) Receive status register */
|
||||
volatile uint32_t ecr; /* Offset: 0x004 TYPE: (WO) Error clear register */
|
||||
};
|
||||
volatile uint32_t reserved0[4]; /* Offset: 0x008-0x014 Reserved */
|
||||
volatile uint32_t fr; /* Offset: 0x018 TYPE: (RO) Flag register */
|
||||
volatile uint32_t reserved1; /* Offset: 0x01C Reserved */
|
||||
volatile uint32_t ilpr; /* Offset: 0x020 TYPE: (RW) IrDA low-power counter register */
|
||||
volatile uint32_t ibrd; /* Offset: 0x024 TYPE: (RW) Integer baud rate register */
|
||||
volatile uint32_t fbrd; /* Offset: 0x028 TYPE: (RW) Fractional baud rate register */
|
||||
volatile uint32_t lcr; /* Offset: 0x02C TYPE: (RW) Line control register */
|
||||
volatile uint32_t cr; /* Offset: 0x030 TYPE: (RW) Control register */
|
||||
volatile uint32_t ifls; /* Offset: 0x034 TYPE: (RW) Interrupt FIFO level select register */
|
||||
volatile uint32_t imsc; /* Offset: 0x038 TYPE: (RW) Interrupt mask set/clear register */
|
||||
volatile uint32_t ris; /* Offset: 0x03C TYPE: (RO) Raw interrupt status register */
|
||||
volatile uint32_t mis; /* Offset: 0x040 TYPE: (RO) Masked interrupt status register */
|
||||
volatile uint32_t icr; /* Offset: 0x044 TYPE: (WO) Interrupt clear register */
|
||||
volatile uint32_t dmacr; /* Offset: 0x048 TYPE: (RW) DMA control register */
|
||||
};
|
||||
|
||||
struct UartResource {
|
||||
uint32_t num; /* UART port num */
|
||||
uint32_t base; /* UART PL011 base address */
|
||||
uint32_t irqNum; /* UART PL011 IRQ num */
|
||||
uint32_t baudrate; /* Default baudrate */
|
||||
uint32_t wlen; /* Default word length */
|
||||
uint32_t parity; /* Default parity */
|
||||
uint32_t stopBit; /* Default stop bits */
|
||||
uint32_t uartClk; /* UART clock */
|
||||
unsigned long physBase;
|
||||
};
|
||||
|
||||
enum UartDeviceState {
|
||||
UART_DEVICE_UNINITIALIZED = 0x0u,
|
||||
UART_DEVICE_INITIALIZED = 0x1u,
|
||||
};
|
||||
|
||||
struct UartDevice {
|
||||
struct IDeviceIoService ioService;
|
||||
struct UartResource resource;
|
||||
enum UartDeviceState state; /* UART State */
|
||||
uint32_t uartClk; /* UART clock */
|
||||
uint32_t baudrate; /* Baudrate */
|
||||
struct BufferFifo rxFifo;
|
||||
};
|
||||
|
||||
/* Receive Status Register/Error Clear Register data */
|
||||
#define UART_PL011_RSR_FRAMING_ERROR_MASK (1 << 0x0u) /* Framing error bit mask */
|
||||
#define UART_PL011_RSR_PARITY_ERROR_MASK (1 << 0x1u) /* Parity error bit mask */
|
||||
#define UART_PL011_RSR_BREAK_ERROR_MASK (1 << 0x2u) /* Break error bit mask */
|
||||
#define UART_PL011_RSR_OVERRUN_ERROR_MASK (1 << 0x3u) /* Overrun error bit mask */
|
||||
|
||||
/* Receive Status Register Error Mask */
|
||||
#define UART_PL011_RSR_RX_ERROR_MASK ( \
|
||||
UART_PL011_RSR_FRAMING_ERROR_MASK \
|
||||
| UART_PL011_RSR_PARITY_ERROR_MASK \
|
||||
| UART_PL011_RSR_BREAK_ERROR_MASK \
|
||||
| UART_PL011_RSR_OVERRUN_ERROR_MASK)
|
||||
|
||||
#define UART_PL011_FR_CTS_MASK (1 << 0x0u) /* Clear to send bit mask */
|
||||
#define UART_PL011_FR_DSR_MASK (1 << 0x1u) /* Data set ready bit mask */
|
||||
#define UART_PL011_FR_DCD_MASK (1 << 0x2u) /* Data carrier detect bit mask */
|
||||
#define UART_PL011_FR_BUSY_MASK (1 << 0x3u) /* UART busy bit mask */
|
||||
#define UART_PL011_FR_RX_FIFO_EMPTY_MASK (1 << 0x4u) /* Receive FIFO empty bit mask */
|
||||
#define UART_PL011_FR_TX_FIFO_FULL_MASK (1 << 0x5u) /* Transmit FIFO full bit mask */
|
||||
#define UART_PL011_FR_RX_FIFO_FULL_MASK (1 << 0x6u) /* Receive FIFO full bit mask */
|
||||
#define UART_PL011_FR_TX_FIFO_EMPTY_MASK (1 << 0x7u) /* Transmit FIFO empty. bit mask */
|
||||
#define UART_PL011_FR_RI_MASK (1 << 0x8u) /* Ring indicator bit mask */
|
||||
|
||||
/* PL011 Line Control Register Data bits */
|
||||
#define UART_PL011_LCR_H_BRK_MASK (1 << 0x0u) /* Send Break bit mask */
|
||||
#define UART_PL011_LCR_H_PEN_MASK (1 << 0x1u) /* Parity enable bit mask */
|
||||
#define UART_PL011_LCR_H_EPS_MASK (1 << 0x2u) /* Even parity select bit mask . */
|
||||
#define UART_PL011_LCR_H_FEN_MASK (1 << 0x4u) /* Enable FIFOs bit mask */
|
||||
#define UART_PL011_LCR_H_SPS_MASK (1 << 0x7u) /* Stick parity select bit mask */
|
||||
|
||||
#define UART_PL011_LCR_H_WLEN_BIT_OFFSET 0x5u /* Word length bit offset */
|
||||
#define UART_PL011_LCR_H_WLEN_MASK ( \
|
||||
0x3u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
|
||||
|
||||
#define UART_PL011_WLEN_5BITS (0x0u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
|
||||
#define UART_PL011_WLEN_6BITS (0x1u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
|
||||
#define UART_PL011_WLEN_7BITS (0x2u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
|
||||
#define UART_PL011_WLEN_8BITS (0x3u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
|
||||
|
||||
#define UART_PL011_NONE_PARITY_CHECKED 0
|
||||
|
||||
#define UART_PL011_LCR_H_STP2_BIT_OFFSET 0x3u /* Two stop bits select */
|
||||
|
||||
#define UART_PL011_STOPBIT_1 (0x0u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
|
||||
#define UART_PL011_STOPBIT_2 (0x1u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
|
||||
|
||||
#define UART_PL011_LCR_H_PARITY_MASK ( \
|
||||
UART_PL011_LCR_H_PEN_MASK \
|
||||
| UART_PL011_LCR_H_EPS_MASK \
|
||||
| UART_PL011_LCR_H_SPS_MASK)
|
||||
|
||||
#define UART_PL011_LCR_H_STOPBIT_MASK (0x1u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
|
||||
|
||||
#define UART_PL011_DATA_FORMAT_MASK ( \
|
||||
UART_PL011_LCR_H_PARITY_MASK \
|
||||
| UART_PL011_LCR_H_STOPBIT_MASK \
|
||||
| UART_PL011_LCR_H_WLEN_MASK)
|
||||
|
||||
/* Control Register */
|
||||
#define UART_PL011_CR_UARTEN_MASK (0x1u << 0x0u) /* Uart enable bit mask */
|
||||
#define UART_PL011_CR_SIREN_MASK (0x1u << 0x1u) /* Sir enable bit mask */
|
||||
#define UART_PL011_CR_SIRLP_MASK (0x1u << 0x2u) /* SIR low-power IrDA mode bit mask */
|
||||
#define UART_PL011_CR_LBE_MASK (0x1u << 0x7u) /* Loopback enable bit mask */
|
||||
#define UART_PL011_CR_TXE_MASK (0x1u << 0x8u) /* Transmit enable bit mask */
|
||||
#define UART_PL011_CR_RXE_MASK (0x1u << 0x9u) /* Receive enable bit mask */
|
||||
#define UART_PL011_CR_DTR_MASK (0x1u << 0xAu) /* Data transmit ready.bit mask */
|
||||
#define UART_PL011_CR_RTS_MASK (0x1u << 0xBu) /* Request to send bit mask */
|
||||
#define UART_PL011_CR_OUT1_MASK (0x1u << 0xCu) /* Out1 bit field mask */
|
||||
#define UART_PL011_CR_OUT2_MASK (0x1u << 0xDu) /* Out2 bit field mask */
|
||||
#define UART_PL011_CR_RTSE_MASK (0x1u << 0xEu) /* RTS hardware flow control enable bit mask */
|
||||
#define UART_PL011_CR_CTSE_MASK (0x1u << 0xFu) /* CTS hardware flow control enable bit mask */
|
||||
|
||||
|
||||
/* Interrupt FIFO Level Select Register Transmit bit offset */
|
||||
#define UART_PL011_IFLS_TX_BIT_OFFSET 0x0u
|
||||
/* Interrupt FIFO Level Select Register Receive bit offset */
|
||||
#define UART_PL011_IFLS_RX_BIT_OFFSET 0x3u
|
||||
|
||||
#define UART_PL011_RX_FIFO_LVL_1_8 (0x0u << UART_PL011_IFLS_RX_BIT_OFFSET)
|
||||
#define UART_PL011_RX_FIFO_LVL_1_4 (0x1u << UART_PL011_IFLS_RX_BIT_OFFSET)
|
||||
#define UART_PL011_RX_FIFO_LVL_1_2 (0x2u << UART_PL011_IFLS_RX_BIT_OFFSET)
|
||||
#define UART_PL011_RX_FIFO_LVL_3_4 (0x3u << UART_PL011_IFLS_RX_BIT_OFFSET)
|
||||
#define UART_PL011_RX_FIFO_LVL_7_8 (0x4u << UART_PL011_IFLS_RX_BIT_OFFSET)
|
||||
|
||||
#define UART_PL011_TX_FIFO_LVL_1_8 (0x0u << UART_PL011_IFLS_TX_BIT_OFFSET)
|
||||
#define UART_PL011_TX_FIFO_LVL_1_4 (0x1u << UART_PL011_IFLS_TX_BIT_OFFSET)
|
||||
#define UART_PL011_TX_FIFO_LVL_1_2 (0x2u << UART_PL011_IFLS_TX_BIT_OFFSET)
|
||||
#define UART_PL011_TX_FIFO_LVL_3_4 (0x3u << UART_PL011_IFLS_TX_BIT_OFFSET)
|
||||
#define UART_PL011_TX_FIFO_LVL_7_8 (0x4u << UART_PL011_IFLS_TX_BIT_OFFSET)
|
||||
|
||||
/* Default register values of UART PL011 */
|
||||
#define UART_PL011_DEFAULT_DATA_REG_VALUE (0x0u)
|
||||
#define UART_PL011_DEFAULT_ECR_VALUE (0xFFu)
|
||||
#define UART_PL011_DEFAULT_ILPR_VALUE (0x0u)
|
||||
#define UART_PL011_DEFAULT_IBRD_REG_VALUE (0x0u)
|
||||
#define UART_PL011_DEFAULT_FBRD_REG_VALUE (0x0u)
|
||||
/* Clear UARTLCR */
|
||||
#define UART_PL011_DEFAULT_LCR_H_VALUE (0x0u)
|
||||
#define UART_PL011_DEFAULT_CTRL_REG_VALUE (0x0300u)
|
||||
|
||||
#define UART_PL011_DEFAULT_IFLS_REG_VALUE ( \
|
||||
UART_PL011_RX_FIFO_LVL_1_2 \
|
||||
| UART_PL011_TX_FIFO_LVL_7_8)
|
||||
|
||||
/* Clear interrupt mask */
|
||||
#define UART_PL011_DEFAULT_IMSC_REG_VALUE (0x0u)
|
||||
/* Clear interrupt */
|
||||
#define UART_PL011_DEFAULT_ICR_VALUE (0x7FFu)
|
||||
#define UART_PL011_DEFAULT_DMACR_VALUE (0x0u)
|
||||
|
||||
#define FREQ_IRLPBAUD16_MIN (1420000u) /* 1.42 MHz */
|
||||
#define FREQ_IRLPBAUD16_MAX (2120000u) /* 2.12 MHz */
|
||||
#define SAMPLING_FACTOR (16u)
|
||||
#define UART_PL011_FBRD_WIDTH (6u)
|
||||
|
||||
/**
|
||||
* \brief ARM UART PL011 error enumeration types
|
||||
*/
|
||||
typedef enum UartPl011Error {
|
||||
UART_PL011_ERR_NONE = (0x0u),
|
||||
UART_PL011_ERR_RX_FRAME = UART_PL011_RSR_FRAMING_ERROR_MASK,
|
||||
UART_PL011_ERR_RX_PARITY = UART_PL011_RSR_PARITY_ERROR_MASK,
|
||||
UART_PL011_ERR_RX_BREAK = UART_PL011_RSR_BREAK_ERROR_MASK,
|
||||
UART_PL011_ERR_RX_OVERFLOW = UART_PL011_RSR_OVERRUN_ERROR_MASK,
|
||||
UART_PL011_ERR_INVALID_ARG = (UART_PL011_RSR_RX_ERROR_MASK + 1),
|
||||
UART_PL011_ERR_NOT_READY,
|
||||
UART_PL011_ERR_INVALID_BAUD,
|
||||
UART_PL011_ERR_NOT_INIT,
|
||||
} UartPl011Error;
|
||||
|
||||
static inline void UartPl011Enable(struct UartRegisterMap *regMap)
|
||||
{
|
||||
regMap->cr |= UART_PL011_CR_UARTEN_MASK;
|
||||
}
|
||||
|
||||
static inline void UartPl011Disable(struct UartRegisterMap *regMap)
|
||||
{
|
||||
regMap->cr &= ~UART_PL011_CR_UARTEN_MASK;
|
||||
}
|
||||
|
||||
static inline bool UartPl011IsEnabled(struct UartRegisterMap *regMap)
|
||||
{
|
||||
return (bool)(regMap->cr & UART_PL011_CR_UARTEN_MASK);
|
||||
}
|
||||
|
||||
static inline bool UartPl011IsBusy(struct UartRegisterMap *regMap)
|
||||
{
|
||||
return (bool)(regMap->fr & UART_PL011_FR_BUSY_MASK);
|
||||
}
|
||||
|
||||
void UartPl011SetLcrBits(struct UartRegisterMap *regMap, uint32_t bits);
|
||||
|
||||
static inline void UartPl011Write(struct UartRegisterMap *regMap, uint8_t byte)
|
||||
{
|
||||
while (UartPl011IsBusy(regMap));
|
||||
regMap->dr = byte;
|
||||
}
|
||||
|
||||
UartPl011Error UartPl011SetBaudrate(struct UartRegisterMap *regMap, uint32_t clk, uint32_t baudrate);
|
||||
|
||||
void UartPl011SetDataFormat(struct UartRegisterMap *regMap, uint32_t wordLen, uint32_t parity, uint32_t stopBits);
|
||||
|
||||
void UartPl011ResetRegisters(struct UartRegisterMap *regMap);
|
||||
|
||||
static inline void UartPl011EnableFifo(struct UartRegisterMap *regMap)
|
||||
{
|
||||
UartPl011SetLcrBits(regMap, UART_PL011_LCR_H_FEN_MASK);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* UART_PL011_SAMPLE_H */
|
||||
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2021 Huawei Device 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.
|
||||
|
||||
import("//drivers/adapter/khdf/liteos/hdf.gni")
|
||||
|
||||
module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART_SAMPLE)
|
||||
module_name = "hdf_uart_sample"
|
||||
hdf_driver(module_name) {
|
||||
FRAMEWORK_UART_ROOT = "//drivers/framework/sample/platform/uart/src"
|
||||
sources = [
|
||||
"$FRAMEWORK_UART_ROOT/buf_fifo.c",
|
||||
"$FRAMEWORK_UART_ROOT/uart_dev_sample.c",
|
||||
"$FRAMEWORK_UART_ROOT/uart_dispatch_sample.c",
|
||||
"$FRAMEWORK_UART_ROOT/uart_pl011_sample.c",
|
||||
"$FRAMEWORK_UART_ROOT/uart_sample.c",
|
||||
]
|
||||
|
||||
include_dirs = [ "//drivers/framework/sample/platform/uart/include/" ]
|
||||
}
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 "buf_fifo.h"
|
||||
|
||||
bool BufferFifoInit(struct BufferFifo *fifo, uint8_t *fifoBuffer, uint16_t fifoSize)
|
||||
{
|
||||
if (fifoBuffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (!IsPowerOfTwo(fifoSize)) {
|
||||
return false;
|
||||
}
|
||||
fifo->buffer = fifoBuffer;
|
||||
fifo->bufSizeMask = fifoSize - 1;
|
||||
fifo->readPosition = 0;
|
||||
fifo->writePosition = 0;
|
||||
return true;
|
||||
}
|
||||
Executable
+192
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 "uart_dev_sample.h"
|
||||
#include "fs/fs.h"
|
||||
#include "securec.h"
|
||||
#include "user_copy.h"
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "uart_pl011_sample.h"
|
||||
|
||||
#define HDF_LOG_TAG uart_dev_sample
|
||||
#define HDF_UART_FS_MODE 0660
|
||||
|
||||
static int32_t UartSampleDevOpen(struct file *filep)
|
||||
{
|
||||
struct UartHost *host = NULL;
|
||||
|
||||
if (filep == NULL || filep->f_vnode == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
|
||||
host = (struct UartHost *)drv->priv;
|
||||
if (host == NULL) {
|
||||
HDF_LOGE("%s: host is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
HDF_LOGI("%s: open uart%d success", __func__, host->num);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
static int32_t UartSampleRelease(struct file *filep)
|
||||
{
|
||||
struct UartHost *host = NULL;
|
||||
|
||||
if (filep == NULL || filep->f_vnode == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
|
||||
host = (struct UartHost *)drv->priv;
|
||||
if (host == NULL) {
|
||||
HDF_LOGE("%s: host is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
HDF_LOGI("%s: close uart%d success", __func__, host->num);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static ssize_t UartSampleRead(struct file *filep, char *buf, size_t count)
|
||||
{
|
||||
int32_t ret;
|
||||
uint8_t *tmpBuf = NULL;
|
||||
struct UartHost *host = NULL;
|
||||
|
||||
if (filep == NULL || filep->f_vnode == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
|
||||
host = (struct UartHost *)drv->priv;
|
||||
|
||||
if (LOS_IsUserAddressRange((vaddr_t)(uintptr_t)buf, count)) {
|
||||
tmpBuf = (uint8_t *)OsalMemCalloc(count);
|
||||
if (tmpBuf == NULL) {
|
||||
HDF_LOGE("%s: OsalMemCalloc error", __func__);
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
ret = UartHostRead(host, tmpBuf, count);
|
||||
if (ret == HDF_SUCCESS) {
|
||||
ret = LOS_ArchCopyToUser(buf, tmpBuf, count);
|
||||
}
|
||||
OsalMemFree(tmpBuf);
|
||||
return ret;
|
||||
} else {
|
||||
return UartHostRead(host, (uint8_t *)buf, count);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t UartSampleWrite(struct file *filep, const char *buf, size_t count)
|
||||
{
|
||||
int32_t ret;
|
||||
uint8_t *tmpBuf = NULL;
|
||||
struct UartHost *host = NULL;
|
||||
|
||||
if (filep == NULL || filep->f_vnode == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
|
||||
host = (struct UartHost *)drv->priv;
|
||||
|
||||
if (LOS_IsUserAddressRange((vaddr_t)(uintptr_t)buf, count)) {
|
||||
tmpBuf = (uint8_t *)OsalMemCalloc(count);
|
||||
if (tmpBuf == NULL) {
|
||||
HDF_LOGE("%s: OsalMemCalloc error", __func__);
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
ret = LOS_ArchCopyFromUser(tmpBuf, buf, count);
|
||||
if (ret != LOS_OK) {
|
||||
OsalMemFree(tmpBuf);
|
||||
return ret;
|
||||
}
|
||||
ret = UartHostWrite(host, tmpBuf, count);
|
||||
OsalMemFree(tmpBuf);
|
||||
return ret;
|
||||
} else {
|
||||
return UartHostWrite(host, (uint8_t *)buf, count);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t UartSampleDevIoctl(struct file *filep, int32_t cmd, unsigned long arg)
|
||||
{
|
||||
int32_t ret;
|
||||
struct UartHost *host = NULL;
|
||||
if (filep == NULL || filep->f_vnode == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
|
||||
host = (struct UartHost *)drv->priv;
|
||||
if (host->priv == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ret = HDF_FAILURE;
|
||||
switch (cmd) {
|
||||
case UART_CFG_BAUDRATE:
|
||||
ret = UartHostSetBaud(host, arg);
|
||||
break;
|
||||
default:
|
||||
HDF_LOGE("%s cmd %d not support", __func__, cmd);
|
||||
ret = HDF_ERR_NOT_SUPPORT;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct file_operations_vfs g_uartSampleDevFops = {
|
||||
.open = UartSampleDevOpen,
|
||||
.close = UartSampleRelease,
|
||||
.read = UartSampleRead,
|
||||
.write = UartSampleWrite,
|
||||
.ioctl = UartSampleDevIoctl,
|
||||
};
|
||||
|
||||
#define MAX_DEV_NAME_SIZE 32
|
||||
static void AddRemoveUartDev(struct UartHost *host, bool add)
|
||||
{
|
||||
int32_t ret;
|
||||
char *devName = NULL;
|
||||
|
||||
if (host == NULL || host->priv == NULL) {
|
||||
HDF_LOGW("%s: invalid parameter", __func__);
|
||||
return;
|
||||
}
|
||||
devName = (char *)OsalMemCalloc(sizeof(char) * (MAX_DEV_NAME_SIZE + 1));
|
||||
if (devName == NULL) {
|
||||
HDF_LOGE("%s: OsalMemCalloc error", __func__);
|
||||
return;
|
||||
}
|
||||
ret = snprintf_s(devName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, "/dev/uartdev-%d", host->num);
|
||||
if (ret < 0) {
|
||||
HDF_LOGE("%s: snprintf_s failed", __func__);
|
||||
OsalMemFree(devName);
|
||||
return;
|
||||
}
|
||||
if (add) {
|
||||
if (register_driver(devName, &g_uartSampleDevFops, HDF_UART_FS_MODE, host)) {
|
||||
HDF_LOGE("%s: gen /dev/uartdev-%d fail!", __func__, host->num);
|
||||
OsalMemFree(devName);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (unregister_driver(devName)) {
|
||||
HDF_LOGE("%s: remove /dev/uartdev-%d fail!", __func__, host->num);
|
||||
OsalMemFree(devName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
OsalMemFree(devName);
|
||||
}
|
||||
|
||||
void AddUartDevice(struct UartHost *host)
|
||||
{
|
||||
AddRemoveUartDev(host, true);
|
||||
}
|
||||
|
||||
void RemoveUartDevice(struct UartHost *host)
|
||||
{
|
||||
AddRemoveUartDev(host, false);
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 "uart_core.h"
|
||||
#include "uart_dispatch_sample.h"
|
||||
#include "hdf_log.h"
|
||||
#include "hdf_sbuf.h"
|
||||
#include "uart_pl011_sample.h"
|
||||
|
||||
#define HDF_LOG_TAG uart_dispatch_sample
|
||||
|
||||
static int32_t SampleDispatchWrite(struct UartDevice *device, struct HdfSBuf *txBuf)
|
||||
{
|
||||
uint32_t idx;
|
||||
uint32_t dataSize = 0;
|
||||
const uint8_t *data = NULL;
|
||||
struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;
|
||||
|
||||
if (regMap == NULL) {
|
||||
HDF_LOGE("%s: regMap is NULL", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (!HdfSbufReadBuffer(txBuf, (const void **)&data, &dataSize)) {
|
||||
HDF_LOGE("%s: Failed to read sbuf", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
regMap = (struct UartRegisterMap *)device->resource.physBase;
|
||||
for (idx = 0; idx < dataSize; idx++) {
|
||||
UartPl011Write(regMap, data[idx]);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t SampleDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
int32_t result = HDF_FAILURE;
|
||||
if (client == NULL || client->device == NULL) {
|
||||
HDF_LOGE("%s: client or client->device is NULL", __func__);
|
||||
return result;
|
||||
}
|
||||
struct UartHost *uartHost = (struct UartHost *)client->device->service;
|
||||
if (uartHost == NULL) {
|
||||
HDF_LOGE("%s: uartHost is NULL", __func__);
|
||||
return result;
|
||||
}
|
||||
struct UartDevice *uartDevice = (struct UartDevice *)uartHost->priv;
|
||||
if (uartDevice == NULL) {
|
||||
HDF_LOGE("%s: uartDevice is NULL", __func__);
|
||||
return result;
|
||||
}
|
||||
switch (cmdId) {
|
||||
case UART_WRITE: {
|
||||
result = SampleDispatchWrite(uartDevice, data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 "uart_pl011_sample.h"
|
||||
|
||||
void UartPl011SetLcrBits(struct UartRegisterMap *regMap, uint32_t bits)
|
||||
{
|
||||
bool uartEnabled = UartPl011IsEnabled(regMap);
|
||||
/* UART must be disabled before UARTLCR_H are reprogrammed */
|
||||
UartPl011Disable(regMap);
|
||||
regMap->lcr |= (bits);
|
||||
/* Restore uart enable state */
|
||||
if (uartEnabled) {
|
||||
UartPl011Enable(regMap);
|
||||
}
|
||||
}
|
||||
|
||||
void UartPl011UpdateLcr(struct UartRegisterMap *regMap)
|
||||
{
|
||||
bool uartEnabled = UartPl011IsEnabled(regMap);
|
||||
/* UART must be disabled before UARTLCR_H are reprogrammed */
|
||||
UartPl011Disable(regMap);
|
||||
regMap->lcr = regMap->lcr;
|
||||
/* restore uart enable state */
|
||||
if (uartEnabled) {
|
||||
UartPl011Enable(regMap);
|
||||
}
|
||||
}
|
||||
|
||||
UartPl011Error UartPl011SetBaudrate(struct UartRegisterMap *regMap, uint32_t clk, uint32_t baudrate)
|
||||
{
|
||||
if (baudrate == 0) {
|
||||
return UART_PL011_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint32_t value = SAMPLING_FACTOR * baudrate;
|
||||
uint32_t divider = clk / value;
|
||||
uint32_t remainder = clk % value;
|
||||
uint32_t fraction;
|
||||
value = (SAMPLING_FACTOR * remainder) / baudrate;
|
||||
fraction = (value >> 1) + (value & 1);
|
||||
|
||||
regMap->ibrd = divider;
|
||||
regMap->fbrd = fraction;
|
||||
/* to internally update the contents of UARTIBRD or
|
||||
* UARTFBRD, a UARTLCR_H write must always be performed at the end.
|
||||
*/
|
||||
UartPl011UpdateLcr(regMap);
|
||||
return UART_PL011_ERR_NONE;
|
||||
}
|
||||
|
||||
void UartPl011SetDataFormat(
|
||||
struct UartRegisterMap *regMap, uint32_t wordLen, uint32_t parity, uint32_t stopBits)
|
||||
{
|
||||
bool uartEnabled = UartPl011IsEnabled(regMap);
|
||||
uint32_t lcr = regMap->lcr & (~UART_PL011_DATA_FORMAT_MASK);
|
||||
lcr |= wordLen & UART_PL011_LCR_H_WLEN_MASK;
|
||||
lcr |= parity & UART_PL011_LCR_H_PARITY_MASK;
|
||||
lcr |= stopBits & UART_PL011_LCR_H_STOPBIT_MASK;
|
||||
/* UART must be disabled before UARTLCR_H are reprogrammed */
|
||||
UartPl011Disable(regMap);
|
||||
regMap->lcr = lcr;
|
||||
if (uartEnabled) {
|
||||
UartPl011Enable(regMap);
|
||||
}
|
||||
}
|
||||
|
||||
void UartPl011ResetRegisters(struct UartRegisterMap *regMap)
|
||||
{
|
||||
regMap->cr = UART_PL011_DEFAULT_CTRL_REG_VALUE;
|
||||
regMap->dr = UART_PL011_DEFAULT_DATA_REG_VALUE;
|
||||
/* Clear all the errors */
|
||||
regMap->ecr = UART_PL011_DEFAULT_ECR_VALUE;
|
||||
regMap->ilpr = UART_PL011_DEFAULT_ILPR_VALUE;
|
||||
regMap->ibrd = UART_PL011_DEFAULT_IBRD_REG_VALUE;
|
||||
regMap->fbrd = UART_PL011_DEFAULT_FBRD_REG_VALUE;
|
||||
regMap->lcr = UART_PL011_DEFAULT_LCR_H_VALUE;
|
||||
regMap->ifls = UART_PL011_DEFAULT_IFLS_REG_VALUE;
|
||||
/* Clear all interrupt mask */
|
||||
regMap->imsc = UART_PL011_DEFAULT_IMSC_REG_VALUE;
|
||||
/* Clear all interrupts */
|
||||
regMap->icr = UART_PL011_DEFAULT_ICR_VALUE;
|
||||
regMap->dmacr = UART_PL011_DEFAULT_DMACR_VALUE;
|
||||
}
|
||||
|
||||
Executable
+344
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 "device_resource_if.h"
|
||||
#include "buf_fifo.h"
|
||||
#include "hdf_device_desc.h"
|
||||
#include "hdf_log.h"
|
||||
#include "hisoc/uart.h"
|
||||
#include "osal_io.h"
|
||||
#include "osal_mem.h"
|
||||
#include "uart_core.h"
|
||||
#include "uart_dev_sample.h"
|
||||
#include "uart_dispatch_sample.h"
|
||||
#include "uart_pl011_sample.h"
|
||||
|
||||
#define HDF_LOG_TAG uart_sample
|
||||
#define UART_RX_FIFO_SIZE 128
|
||||
|
||||
static uint8_t g_fifoBuffer[UART_RX_FIFO_SIZE] = {0};
|
||||
|
||||
/* HdfDriverEntry method definitions */
|
||||
static int32_t SampleUartDriverBind(struct HdfDeviceObject *device);
|
||||
static int32_t SampleUartDriverInit(struct HdfDeviceObject *device);
|
||||
static void SampleUartDriverRelease(struct HdfDeviceObject *device);
|
||||
|
||||
/* HdfDriverEntry definitions */
|
||||
struct HdfDriverEntry g_sampleUartDriverEntry = {
|
||||
.moduleVersion = 1,
|
||||
.moduleName = "UART_SAMPLE",
|
||||
.Bind = SampleUartDriverBind,
|
||||
.Init = SampleUartDriverInit,
|
||||
.Release = SampleUartDriverRelease,
|
||||
};
|
||||
|
||||
// Initialize HdfDriverEntry
|
||||
HDF_INIT(g_sampleUartDriverEntry);
|
||||
|
||||
/* UartHostMethod method definitions */
|
||||
static int32_t SampleUartHostInit(struct UartHost *host);
|
||||
static int32_t SampleUartHostDeinit(struct UartHost *host);
|
||||
static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size);
|
||||
static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate);
|
||||
static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate);
|
||||
|
||||
/* UartHostMethod definitions */
|
||||
struct UartHostMethod g_sampleUartHostMethod = {
|
||||
.Init = SampleUartHostInit,
|
||||
.Deinit = SampleUartHostDeinit,
|
||||
.Read = NULL,
|
||||
.Write = SampleUartHostWrite,
|
||||
.SetBaud = SampleUartHostSetBaud,
|
||||
.GetBaud = SampleUartHostGetBaud,
|
||||
.SetAttribute = NULL,
|
||||
.GetAttribute = NULL,
|
||||
.SetTransMode = NULL,
|
||||
};
|
||||
|
||||
/* UartHostMethod implementations */
|
||||
static int32_t SampleUartHostInit(struct UartHost *host)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
if (host == NULL) {
|
||||
HDF_LOGW("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleUartHostDeinit(struct UartHost *host)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
if (host == NULL) {
|
||||
HDF_LOGW("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size)
|
||||
{
|
||||
uint32_t idx;
|
||||
struct UartRegisterMap *regMap = NULL;
|
||||
struct UartDevice *device = NULL;
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
if (host == NULL || data == NULL || size == 0) {
|
||||
HDF_LOGW("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
device = (struct UartDevice *)host->priv;
|
||||
if (device == NULL) {
|
||||
HDF_LOGW("%s: device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
regMap = (struct UartRegisterMap *)device->resource.physBase;
|
||||
for (idx = 0; idx < size; idx++) {
|
||||
UartPl011Write(regMap, data[idx]);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate)
|
||||
{
|
||||
struct UartDevice *device = NULL;
|
||||
struct UartRegisterMap *regMap = NULL;
|
||||
UartPl011Error err;
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
if (host == NULL) {
|
||||
HDF_LOGW("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
device = (struct UartDevice *)host->priv;
|
||||
if (device == NULL) {
|
||||
HDF_LOGW("%s: device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
regMap = (struct UartRegisterMap *)device->resource.physBase;
|
||||
if (device->state != UART_DEVICE_INITIALIZED) {
|
||||
return UART_PL011_ERR_NOT_INIT;
|
||||
}
|
||||
if (baudRate == 0) {
|
||||
return UART_PL011_ERR_INVALID_BAUD;
|
||||
}
|
||||
err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate);
|
||||
if (err == UART_PL011_ERR_NONE) {
|
||||
device->baudrate = baudRate;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate)
|
||||
{
|
||||
struct UartDevice *device = NULL;
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
if (host == NULL) {
|
||||
HDF_LOGW("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
device = (struct UartDevice *)host->priv;
|
||||
if (device == NULL) {
|
||||
HDF_LOGW("%s: device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
*baudRate = device->baudrate;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int InitUartDevice(struct UartDevice *device)
|
||||
{
|
||||
UartPl011Error err;
|
||||
struct UartResource *resource = &device->resource;
|
||||
struct UartRegisterMap *regMap = (struct UartRegisterMap *)resource->physBase;
|
||||
if ((resource->uartClk == 0) || (resource->baudrate == 0)) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
/* Updating the system clock */
|
||||
device->uartClk = resource->uartClk;
|
||||
uart_clk_cfg(0, true);
|
||||
/* clear and reset registers. */
|
||||
UartPl011ResetRegisters(regMap);
|
||||
/* set baud rate as device config */
|
||||
err = UartPl011SetBaudrate(regMap, resource->uartClk, resource->baudrate);
|
||||
if (err != UART_PL011_ERR_NONE) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
/* set the data format as device config */
|
||||
UartPl011SetDataFormat(regMap, resource->wlen, resource->parity, resource->stopBit);
|
||||
/* Enabling the FIFOs */
|
||||
UartPl011EnableFifo(regMap);
|
||||
UartPl011Enable(regMap);
|
||||
BufferFifoInit(&device->rxFifo, g_fifoBuffer, UART_RX_FIFO_SIZE);
|
||||
device->state = UART_DEVICE_INITIALIZED;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static uint32_t GetUartDeviceResource(
|
||||
struct UartDevice *device, const struct DeviceResourceNode *resourceNode)
|
||||
{
|
||||
struct UartResource *resource = &device->resource;
|
||||
struct DeviceResourceIface *dri = NULL;
|
||||
dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
|
||||
if (dri == NULL || dri->GetUint32 == NULL) {
|
||||
HDF_LOGE("DeviceResourceIface is invalid");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read num fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read base fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48);
|
||||
if (resource->physBase == 0) {
|
||||
HDF_LOGE("uart config fail to remap physBase");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read irqNum fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read baudrate fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read wlen fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read parity fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read stopBit fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("uart config read uartClk fail");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
struct UartDevice *uartDevice = NULL;
|
||||
if (device->property == NULL) {
|
||||
HDF_LOGW("%s: property is NULL", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice));
|
||||
if (uartDevice == NULL) {
|
||||
HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__);
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
ret = GetUartDeviceResource(uartDevice, device->property);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
(void)OsalMemFree(uartDevice);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
host->num = uartDevice->resource.num;
|
||||
host->priv = uartDevice;
|
||||
AddUartDevice(host);
|
||||
return InitUartDevice(uartDevice);
|
||||
}
|
||||
|
||||
static void DeinitUartDevice(struct UartDevice *device)
|
||||
{
|
||||
struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;
|
||||
/* wait for uart enter idle. */
|
||||
while (UartPl011IsBusy(regMap)) { }
|
||||
UartPl011ResetRegisters(regMap);
|
||||
uart_clk_cfg(0, false);
|
||||
OsalIoUnmap((void *)device->resource.physBase);
|
||||
device->state = UART_DEVICE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
static void DetachUartDevice(struct UartHost *host)
|
||||
{
|
||||
struct UartDevice *uartDevice = NULL;
|
||||
|
||||
if (host->priv == NULL) {
|
||||
HDF_LOGW("%s: invalid parameter", __func__);
|
||||
return;
|
||||
}
|
||||
uartDevice = host->priv;
|
||||
DeinitUartDevice(uartDevice);
|
||||
(void)OsalMemFree(uartDevice);
|
||||
host->priv = NULL;
|
||||
}
|
||||
|
||||
/* HdfDriverEntry implementations */
|
||||
static int32_t SampleUartDriverBind(struct HdfDeviceObject *device)
|
||||
{
|
||||
struct UartHost *uartHost = NULL;
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
if (device == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
uartHost = UartHostCreate(device);
|
||||
if (uartHost == NULL) {
|
||||
HDF_LOGE("%s: UartHostCreate failed", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
uartHost->service.Dispatch = SampleDispatch;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleUartDriverInit(struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
struct UartHost *host = NULL;
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
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_FAILURE;
|
||||
}
|
||||
ret = AttachUartDevice(host, device);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: attach error", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
host->method = &g_sampleUartHostMethod;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SampleUartDriverRelease(struct HdfDeviceObject *device)
|
||||
{
|
||||
struct UartHost *host = NULL;
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
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) {
|
||||
DetachUartDevice(host);
|
||||
}
|
||||
UartHostDestroy(host);
|
||||
}
|
||||
Reference in New Issue
Block a user