提交 35834b20 编写于 作者: C caiyan.cai 提交者: Jinliang Li

release version:rel_3.3.0-20211028_1000

Signed-off-by: Ncaiyan.cai <caiyan.cai@alibaba-inc.com>
上级 052bf7ec
# 介绍
图形驱动框架: 连接用户层和驱动层的枢纽
# 特性
面向对象的设计理念:核心设备驱动模型采用Bus-Device-Driver分离的架构,用C语言结合面向对象的设计理念进行设计和实现。
# 目录
```sh
fbdev/
├── include #fbdev包含的头文件
│   ├── fb_define.h
│   ├── fb_rotate.h
│   └── fb.h
├── src #fbdev 代码实现
│   ├── fb_rotate.c
│   └── fb.c
├── README.md
└── package.yaml #aos编译文件
```
# 依赖
- 操作系统系统基础组件
- vfs: master
- posix: master
# 使用
厂商无需关注此模块的实现细节
对外提供的接口见udisplay组件
## 编译指令
无需单独编译
# 参考
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#ifndef FB_H
#define FB_H
/**
* @addtogroup aos_fbdev fbdev
* This is the brief description of the component.
*
* This is the detailed description, and it's optional.
* @{
*/
#include <fb_define.h>
#include <ulog/ulog.h>
#include <aos/kernel.h>
#ifdef CONFIG_BACKLIGHT_MODE_ENABLE
#include "backlight.h"
#endif
#include "aos/vfs.h"
/* Here is Macro and struct definition*/
#define FB_MAX 3
#define FB_STR "FB"
#define FB_MAX_NUM 16
#define FB_NAME_LEN 16
#define fb_node_path "/dev/fb"
#define FBDEV_STEP_DEBUG printf("[%s][%d]excute to here\n", __func__, __LINE__);
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
#define PAGE_SIZE 4096
#define fb_memcpy_fromfb memcpy
#define fb_memcpy_tofb memcpy
#ifndef unlikely
#if defined(__CC_ARM)
#define unlikely(x) __builtin_expect(!!(x), 0)
#elif defined(__ICCARM__)
#define unlikely(x) (x)
#elif defined(__GNUC__)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define unlikely(x) (x)
#endif
#endif
/* FBINFO_* = fb_info.flags bit flags */
#define FBINFO_DEFAULT 0
#define FBINFO_HWACCEL_DISABLED 0x0002
#define FBINFO_HWACCEL_NONE 0x0000
#define FBINFO_HWACCEL_COPYAREA 0x0100 /* required */
#define FBINFO_HWACCEL_FILLRECT 0x0200 /* required */
#define FBINFO_HWACCEL_IMAGEBLIT 0x0400 /* required */
#define FBINFO_HWACCEL_ROTATE 0x0800 /* optional */
#define FBINFO_HWACCEL_XPAN 0x1000 /* optional */
#define FBINFO_HWACCEL_YPAN 0x2000 /* optional */
#define FBINFO_HWACCEL_YWRAP 0x4000 /* optional */
struct _fb_ops_t;
#ifdef CONFIG_BACKLIGHT_MODE_ENABLE
struct _bl_device_t;
#endif
struct _fb_info_t;
typedef struct _fb_videomode_t {
const char *name; /* optional */
uint32_t refresh; /* optional */
uint32_t xres;
uint32_t yres;
uint32_t pixclock;
uint32_t left_margin;
uint32_t right_margin;
uint32_t upper_margin;
uint32_t lower_margin;
uint32_t hsync_len;
uint32_t vsync_len;
uint32_t sync;
uint32_t vmode;
uint32_t flag;
} fb_videomode_t;
struct fb_pixmap {
uint8_t *addr; /* pointer to memory */
uint32_t size; /* size of buffer in bytes */
uint32_t offset; /* current offset to buffer */
uint32_t buf_align; /* byte alignment of each bitmap */
uint32_t scan_align; /* alignment per scanline */
uint32_t access_align; /* alignment per read/write (bits) */
uint32_t flags; /* see FB_PIXMAP_* */
uint32_t blit_x; /* supported bit block dimensions (1-32)*/
uint32_t blit_y; /* Format: blit_x = 1 << (width - 1) */
/* blit_y = 1 << (height - 1) */
/* if 0, will be set to 0xffffffff (all)*/
/* access methods */
void (*writeio)(struct _fb_info_t *info, void *dst, void *src, unsigned int size);
void (*readio) (struct _fb_info_t *info, void *dst, void *src, unsigned int size);
};
typedef struct _fb_info_t {
char path[FB_NAME_LEN];
int ref;
int node;
int flags;
aos_mutex_t lock; /* Lock for open/release/ioctl funcs */
aos_mutex_t mm_lock; /* Lock for fb_mmap and smem_* fields */
fb_var_screeninfo_t var; /* Current var */
fb_fix_screeninfo_t fix; /* Current fix */
struct fb_pixmap pixmap; /* Image hardware mapper */
struct fb_pixmap sprite; /* Cursor hardware mapper */
// struct fb_cmap cmap; /* Current cmap */
uint8_t *prefb; /* Pre-frame buffer from user space*/
void *par; /* From here on everything is device dependent */
#ifdef CONFIG_BACKLIGHT_MODE_ENABLE
struct _bl_device_t *bl_dev; /*backlight device*/
uint8_t bl_curve[FB_BACKLIGHT_LEVELS];
#endif
uint32_t state; /* Hardware state i.e suspend */
const struct _fb_ops_t *fbops;
union {
uint8_t *screen_base; /* Virtual address */
uint8_t *screen_buffer;
};
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */
} fb_info_t;
typedef struct _fb_ops_t {
/* open/release and usage marking */
int (*fb_open)(fb_info_t *info, int user);
int (*fb_release)(fb_info_t *info, int user);
/* For framebuffers with strange non linear layouts or that do not
* work with normal memory mapped access
*/
ssize_t (*fb_read)(fb_info_t *info, char *buf,
size_t count);
ssize_t (*fb_write)(fb_info_t *info, const char *buf,
size_t count);
/* blank display */
int (*fb_blank)(int blank, fb_info_t *info);
/* pan display */
int (*fb_pan_display)(fb_var_screeninfo_t *var, fb_info_t *info);
/* set the video mode according to info->var */
int (*fb_set_par)(struct fb_info *info);
/* Rotates the display */
void (*fb_rotate)(fb_info_t *info, int angle);
/* wait for blit idle, optional */
int (*fb_sync)(fb_info_t *info);
/* perform fb specific ioctl (optional) */
int (*fb_ioctl)(fb_info_t *info, unsigned int cmd,
unsigned long arg);
/* perform fb specific mmap */
void *(*fb_mmap)(fb_info_t *info, size_t size);
#ifdef CONFIG_HW_ACCELERATION
/* Draws a rectangle */
void (*fb_fillrect) (fb_info_t *info, const fb_fillrect_t *rect);
/* Copy data from area to another */
void (*fb_copyarea) (fb_info_t *info, const fb_copyarea_t *region);
/* Draws a image to the display */
void (*fb_imageblit) (fb_info_t *info, const fb_image_t *image);
#endif
/* teardown any resources to do with this framebuffer */
void (*fb_destroy)(fb_info_t *info);
} fb_ops_t;
/* Here is API and callback definition*/
static inline void lock_fb_info(fb_info_t *info)
{
if (aos_mutex_lock(&info->lock, AOS_WAIT_FOREVER) != 0) {
LOGE(FB_STR, "Failed to lock mutex (%s).", __func__);
return;
}
}
static inline void unlock_fb_info(fb_info_t *info)
{
aos_mutex_unlock(&info->lock);
}
static inline inode_t *file_inode(const file_t *file)
{
if (!file)
return NULL;
return file->node;
}
int fb_init(void);
fb_info_t *framebuffer_alloc(size_t size);
int register_framebuffer(fb_info_t *info);
void unregister_framebuffer(fb_info_t *info);
void framebuffer_release(fb_info_t *info);
/** @} */
#endif
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#ifndef COMP_FB_H
#define COMP_FB_H
#include <stdint.h>
#include <stddef.h>
#define FB_BACKLIGHT_LEVELS 128
#define FB_BACKLIGHT_MAX 0xFF
#ifdef CONFIG_64BIT
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif /* CONFIG_64BIT */
#define FB_SYNC 0x0001
#define FB_ASYNC 0x0010
// show normally
#define FB_ROTATE_UR 0
// rotate 90 degrees clockwise
#define FB_ROTATE_CW 1
// upside down
#define FB_ROTATE_UD 2
// rotate 90 degrees counterclockwise
#define FB_ROTATE_CCW 3
#define BYTES_PER_LONG (BITS_PER_LONG / 8)
#define PADDING (BYTES_PER_LONG - (sizeof(fb_info_t) % BYTES_PER_LONG))
#define FBIOGET_VSCREENINFO 0x4600
#define FBIOPUT_VSCREENINFO 0x4601
#define FBIOGET_FSCREENINFO 0x4602
#define FBIOGET_FRRAMEBUFFER 0x4603
#define FBIOGETCMAP 0x4604
#define FBIOPUTCMAP 0x4605
#define FBIOPAN_DISPLAY 0x4606
#define FBIO_WAITFORVSYNC 0x4607
#define FBIOPUT_PREFB_ADDR 0x4608
#define FBIOBLANK 0x4611
/*brightness ioctl*/
#define FBIOPUT_BRIGHTNESS 0x4612
#define FBIOGET_BRIGHTNESS 0x4613
#define FBIOENABLE_BACKLIGHT 0x4614
#define FBIODISABLE_BACKLIGHT 0x4615
typedef struct _fb_fix_screeninfo_t {
char id[16]; /* Identification string */
uint64_t smem_start; /* Start of frame buffer mem */
/* (physical address) */
uint32_t smem_len; /* Length of frame buffer mem */
uint16_t xpanstep; /* zero if no hardware panning */
uint16_t ypanstep; /* zero if no hardware panning */
uint16_t ywrapstep; /* zero if no hardware ywrap */
uint32_t line_length;
uint64_t mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
size_t mmio_len; /* Length of Memory Mapped I/O */
uint16_t reserved[15];
} fb_fix_screeninfo_t;
typedef struct _fb_bitfield_t {
uint32_t offset;
uint32_t length;
uint32_t msb_right;
} fb_bitfield_t;
typedef struct _fb_var_screeninfo_t {
uint32_t xres; /* visible resolution */
uint32_t yres;
uint32_t xres_virtual; /* virtual resolution */
uint32_t yres_virtual;
uint32_t xoffset; /* offset from virtual to visible */
uint32_t yoffset;
uint32_t bits_per_pixel;
fb_bitfield_t red; /* bitfield in fb mem if true color */
fb_bitfield_t green;
fb_bitfield_t blue;
fb_bitfield_t transp; /* transparency */
uint32_t height; /* height of picture in mm */
uint32_t width; /* width of picture in mm */
uint32_t rotate; /* angle we rotate counter clockwise */
uint16_t reserved[10];
} fb_var_screeninfo_t;
#endif /* COMP_FB_H */
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#ifndef FB_ROTATE_H
#define FB_ROTATE_H
/**
* @addtogroup rotate
* This is the brief description of the component.
*
* This is the detailed description, and it's optional.
* @{
*/
#include <stdio.h>
#include <stdint.h>
/* Here is Macro and struct definition*/
/* Here is API and callback definition*/
void rotate_cw(const uint8_t *in, uint8_t *out, uint32_t w, uint32_t h);
/** @} */
#endif
## 第一部分: 基础信息
name: fbdev # <必选项> 包名称 (符合C语言变量命名规则),长度少于等于64字节
version: master # <必选项> 组件版本号
description: 图形显示相关驱动框架 # <必选项> 建议至少20字以上
type: common # <必选项> 组件类型,为:solution, chip, board, common, sdk
tag: # <可选项> 组件分类,缺省值: ''
keywords: # <可选项> 标签,会影响到组件被搜索的效果,合理的标签很重要
- fbdev
license: Apache license v2.0 # <可选项> 源代码的许可证,要确保所有代码、文件的许可证不冲突。如:MIT,Apache license v2.0,BSD
## 第二部分:依赖信息
# 指定该组件依赖的组件及版本,版本支持条件比较,支持:>=v1.0, >v1.0, ==v1.0, <=v1.0, <v1.0, v1.0
# 未指定条件时,默认为 ==,如 v1.0 与 ==v1.0
# depends: # <可选项> 该组件依赖其他的组件,合理的依赖才能保证组件能编译、使用
# - minilibc: v7.2.0
# - aos: >=v7.2.0
depends:
- base: master
- vfs: master
- posix: master
## 第四部分:编译连接信息
# build_config: # <可选项> 编译配置项
# include: # <可选项> 编译时,影响编译器的-I 参数 ,全局有效
# - src # include 只能是该软件包下的目录,不能使用外部目录
# internal_include: # <可选项> 编译时,影响编译器的-I 参数 ,组件内有效
# - include
# cflag: '' # <可选项> C 编译器所需要要的编译参数
# cxxflag: '' # <可选项> CXX 编译器所需要要的编译参数
# asmflag: '' # <可选项> 汇编器所需要要参数
# define: # <可选项> 宏定义, 增加编译器的-D 选项,如:
# XXX: 1 # -DXXX=1
# AAA: 1 # -DAAA
# STR: "abc" # -DSTR="abc"
# libs: # 该组件中支持的二进制静态库,如:libxxx.a, libyyy.a
# - xxx # -lxxx
# - yyy # -lyyy
# libpath: # 指定静态库所在的路径(相对于该组件路径)
# - libs # -Llibs
build_config:
include:
- include
# source_file: # <可选项> 指定参与编译的源代码文件,支持通配符,采用相对路径
# - src/*.c # 例:组件 src 目录下所有的扩展名为 c 的源代码文件
source_file:
# FB
- src/fb_rotate.c
- src/fb.c
## 第五部分:配置信息
# def_config: # 组件的可配置项
# CONFIG_DEBUG: y
# CONFIG_PARAM_NOT_CHECK: y
# CONFIG_CLI: y
def_config:
## 第六部分:安装信息
# install:
# - dest: include/ # 安装的目的路径 dest是相当路径,通常是相对于YoC SDK 安装目录
# source: # 安装源列表
# - src/*.h # 支持通配符,相对路径
install:
- dest: "include/devices"
source:
## 第七部分:导出部分
# export:
# - dest: "<SOLUTION_PATH>/generated/data" # 安装的目的路径 dest是相当路径
# source: # 安装源列表
# - "bootimgs/boot"
# - "bootimgs/tee"
# - "bootimgs/mtb"
# - "configs/config.yaml"
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <aos/kernel.h>
#include <errno.h>
#include <aos/vfs.h>
#include <string.h>
#include <fb.h>
#include <devicevfs/devicevfs.h>
#include <k_api.h>
// #include <k_shmm.h>
#define FBPIXMAPSIZE (1024 * 8)
fb_info_t *registered_fb[FB_MAX];
static int num_registered_fb = 0;
static aos_mutex_t fb_mutex;
static int fb_open(inode_t *inode, file_t *file);
static int fb_close(file_t *file);
static ssize_t fb_read(file_t *file, void *buf, size_t len);
static ssize_t fb_write(file_t *file, const void *buf, size_t len);
static int fb_ioctl(file_t *file, int cmd, unsigned long arg);
#ifdef CONFIG_AOS_MMAP_ENABLE
static void *fb_mmap(file_t *file, size_t size);
#endif
file_ops_t fb_fops = {
.open = fb_open,
.close = fb_close, // release
.read = fb_read,
.write = fb_write,
.ioctl = fb_ioctl,
#ifdef CONFIG_AOS_MMAP_ENABLE
.mmap = fb_mmap,
#endif
};
static fb_info_t *get_fb_info(char *path)
{
int i = 0;
fb_info_t *fb_info;
if (path == NULL) {
printf("[%s]path is null\n", __func__);
return NULL;
}
for (i = 0; i < FB_MAX; i++) {
if (strlen(path) != strlen(registered_fb[i]->path))
continue;
if (strncmp(registered_fb[i]->path, path, strlen(path)) == 0)
break;
}
if (i >= FB_MAX)
return NULL;
if (aos_mutex_lock(&fb_mutex, AOS_WAIT_FOREVER) != 0) {
LOGE(FB_STR, "Failed to lock mutex (%s).", __func__);
return NULL;
}
fb_info = registered_fb[i];
aos_mutex_unlock(&fb_mutex);
return fb_info;
}
static int fb_open(inode_t *inode, file_t *file)
{
fb_info_t *info;
int ret = 0;
info = get_fb_info(inode->i_name);
if (!info)
return -ENODEV;
lock_fb_info(info);
if (info->fbops->fb_open)
ret = info->fbops->fb_open(info, 1);
unlock_fb_info(info);
return ret;
}
static fb_info_t *file_fb_info(file_t *file)
{
inode_t *inode = file_inode(file);
fb_info_t *info;
if (!inode)
return NULL;
info = get_fb_info(inode->i_name);
if (!info)
return NULL;
return info;
}
static ssize_t fb_read(file_t *file, void *buf, size_t len)
{
fb_info_t *info = file_fb_info(file);
unsigned long total_size;
if (!info || !info->screen_base)
return -ENODEV;
if (info->state != FBINFO_STATE_RUNNING)
return -EPERM;
if (info->fbops->fb_read)
return info->fbops->fb_read(info, buf, len);
total_size = info->screen_size;
if (total_size == 0)
total_size = info->fix.smem_len;
if (len >= total_size)
len = total_size;
memcpy(buf, info->screen_base, len);
return len;
}
static ssize_t fb_write(file_t *file, const void *buf, size_t len)
{
fb_info_t *info = file_fb_info(file);
if (!info || !info->screen_base)
return -ENODEV;
if (info->fbops->fb_write)
return info->fbops->fb_write(info, buf, len);
if (!info->screen_base)
return -1;
memcpy(info->screen_base, buf, len);
return len;
}
static int fb_set_var(fb_info_t *info, fb_var_screeninfo_t *var)
{
int32_t ret = 0;
memcpy(&info->var, var, sizeof(fb_var_screeninfo_t));
if (info->fbops->fb_set_par)
ret = info->fbops->fb_set_par(info);
return ret;
}
static int fb_pan_display(fb_info_t *info, fb_var_screeninfo_t *var)
{
fb_fix_screeninfo_t *fix = &info->fix;
uint32_t yres = info->var.yres;
int err = 0;
if (!var)
return -EINVAL;
if (var->xoffset > 0 && (!fix->xpanstep ||
(var->xoffset % fix->xpanstep)))
err = -EINVAL;
if (err || !info->fbops->fb_pan_display ||
var->yoffset > info->var.yres_virtual - yres ||
var->xoffset > info->var.xres_virtual - info->var.xres)
return -EINVAL;
err = info->fbops->fb_pan_display(var, info);
if (err != 0)
return err;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
return 0;
}
static int fb_blank(fb_info_t *info, int blank)
{
int ret = -EINVAL;
if (info->fbops->fb_blank)
ret = info->fbops->fb_blank(blank, info);
return ret;
}
static void printf_string(int cmd)
{
switch (cmd) {
case FBIOGET_VSCREENINFO:
printf("ioctl cmd : FBIOGET_VSCREENINFO\n");
break;
case FBIOPUT_VSCREENINFO:
// printf("ioctl cmd : FBIOPUT_VSCREENINFO\n");
break;
case FBIOGET_FSCREENINFO:
printf("ioctl cmd : FBIOGET_FSCREENINFO\n");
break;
case FBIOPAN_DISPLAY:
printf("ioctl cmd : FBIOPAN_DISPLAY\n");
break;
case FBIOPUT_PREFB_ADDR:
printf("ioctl cmd : FBIOPUT_PREFB_ADDR\n");
break;
// case FBIOPUT_PREFB_PARAMS:
// // printf("ioctl cmd: FBIOPUT_PREFB_PARAMS\n");
// break;
case FBIO_WAITFORVSYNC:
printf("ioctl cmd: FBIO_WAITFORVSYNC\n");
break;
case FBIOBLANK:
printf("ioctl cmd : FBIOBLANK\n");
break;
case FBIOPUT_BRIGHTNESS:
printf("ioctl cmd : FBIOPUT_BRIGHTNESS\n");
break;
case FBIOGET_BRIGHTNESS:
printf("ioctl cmd : FBIOGET_BRIGHTNESS\n");
break;
#ifdef CONFIG_BACKLIGHT_MODE_ENABLE
case FBIOENABLE_BACKLIGHT:
printf("ioctl cmd : FBIOENABLE_BACKLIGHT\n");
break;
case FBIODISABLE_BACKLIGHT:
printf("ioctl cmd : FBIODISABLE_BACKLIGHT\n");
break;
#endif
default:
// printf("ioctl cmd: unknown command\n");
break;
}
return;
}
static int fb_ioctl(file_t *file, int cmd, unsigned long arg)
{
int ret = 0;
fb_info_t *info = file_fb_info(file);
fb_var_screeninfo_t var;
printf_string(cmd);
switch (cmd) {
case FBIOGET_VSCREENINFO:
lock_fb_info(info);
memcpy((void *)arg, &info->var, sizeof(fb_var_screeninfo_t));
unlock_fb_info(info);
break;
case FBIOPUT_VSCREENINFO:
lock_fb_info(info);
ret = fb_set_var(info, (fb_var_screeninfo_t *)arg);
unlock_fb_info(info);
if (ret < 0)
ret = -EFAULT;
break;
case FBIOGET_FSCREENINFO:
lock_fb_info(info);
memcpy((void *)arg, &info->fix, sizeof(fb_fix_screeninfo_t));
unlock_fb_info(info);
break;
case FBIOGET_FRRAMEBUFFER:
info->screen_buffer = malloc((int32_t)arg);
break;
case FBIOPAN_DISPLAY:
lock_fb_info(info);
if (arg)
ret = fb_pan_display(info, (fb_var_screeninfo_t *)arg);
unlock_fb_info(info);
break;
case FBIOBLANK:
lock_fb_info(info);
ret = fb_blank(info, arg);
unlock_fb_info(info);
break;
#ifdef CONFIG_BACKLIGHT_MODE_ENABLE
case FBIOPUT_BRIGHTNESS:
if (info->bl_dev)
backlight_device_set_brightness(info->bl_dev, *(int32_t *)arg);
break;
case FBIOGET_BRIGHTNESS:
if (info->bl_dev) {
int32_t brightness;
brightness = backlight_device_get_brightness(info->bl_dev);
memcpy((void *)arg, &brightness, sizeof(brightness));
}
break;
case FBIOENABLE_BACKLIGHT:
if (info->bl_dev)
backlight_enable(info->bl_dev);
break;
case FBIODISABLE_BACKLIGHT:
if (info->bl_dev)
backlight_disable(info->bl_dev);
break;
#endif
#ifdef CONFIG_HW_ACCELERATION
case FBIO_ACCEL_FILLRECT:
lock_fb_info(info);
if (info->fbops->fb_fillrect) {
info->fbops->fb_fillrect(info, (const fb_fillrect_t *)arg);
ret = 0;
} else {
ret = -EIO;
}
unlock_fb_info(info);
break;
case FBIO_ACCEL_IMAGEBLIT:
lock_fb_info(info);
if (info->fbops->fb_imageblit) {
info->fbops->fb_imageblit(info, (const fb_image_t *)arg);
ret = 0;
} else {
ret = -EIO;
}
unlock_fb_info(info);
break;
case FBIO_ACCEL_COPYAREA:
lock_fb_info(info);
if (info->fbops->fb_copyarea) {
info->fbops->fb_copyarea(info, (const fb_copyarea_t *)arg);
ret = 0;
} else {
ret = -EIO;
}
unlock_fb_info(info);
break;
#endif
default:
lock_fb_info(info);
if (info->fbops->fb_ioctl)
ret = info->fbops->fb_ioctl(info, cmd, arg);
else
ret = -EIO;
unlock_fb_info(info);
break;
}
return ret;
}
#ifdef CONFIG_AOS_MMAP_ENABLE
static void *fb_mmap(file_t *file, size_t size)
{
fb_info_t *info = file_fb_info(file);
void *(*fb_mmap_fn)(fb_info_t *info, size_t size);
uint64_t *start;
uint32_t len;
if (!info)
return NULL;
if (aos_mutex_lock(&info->mm_lock, AOS_WAIT_FOREVER) != 0) {
LOGE(FB_STR, "Failed to lock mutex (%s).", __func__);
return NULL;
}
fb_mmap_fn = info->fbops->fb_mmap;
if (fb_mmap_fn) {
void *res;
// The framebuffer needs to be accessed decrypted, be sure
// SME protection is removed ahead of the call
res = fb_mmap_fn(info, size);
aos_mutex_unlock(&info->mm_lock);
return res;
}
start = (uint64_t *)&info->fix.smem_start; // pyshical address
len = info->fix.smem_len;
if (start == NULL || len == 0) {
info->fix.smem_start = (uint64_t)k_shmm_map_area(NULL, size);
if (info->screen_base == NULL) {
aos_mutex_unlock(&info->mm_lock);
return NULL;
}
info->screen_base = (uint8_t *)info->fix.smem_start;
info->fix.smem_len = size;
}
aos_mutex_unlock(&info->mm_lock);
return (void *)info->screen_base;
}
#endif
static void put_fb_info(fb_info_t *info)
{
if (info->fbops->fb_destroy)
info->fbops->fb_destroy(info);
}
static int fb_close(file_t *file)
{
fb_info_t *info = file_fb_info(file);
if (!info)
return -ENODEV;
lock_fb_info(info);
if (info->fbops->fb_release)
info->fbops->fb_release(info, 1);
unlock_fb_info(info);
put_fb_info(info);
return 0;
}
static int do_register_framebuffer(fb_info_t *fb_info)
{
int i = 0, ret = 0;
if (num_registered_fb == FB_MAX)
return -ENXIO;
/*set ENDIAN mode, TODO*/
num_registered_fb++;
for (i = 0; i < FB_MAX; i++)
if (!registered_fb[i])
break;
fb_info->node = i;
aos_mutex_new(&fb_info->lock);
aos_mutex_new(&fb_info->mm_lock);
/*register framebuffer device to vfs*/
ret = snprintf(fb_info->path, FB_NAME_LEN, "%s%d", fb_node_path, fb_info->node);
if (ret < 0) {
LOGE(FB_STR, "copy fb path fail (%s)\n", __func__);
return -1;
}
ret = aos_register_driver(fb_info->path, &fb_fops, NULL);
if (unlikely(ret))
return -1;
if (i < FB_MAX)
registered_fb[i] = fb_info;
else
LOGE(FB_STR, "out of bounds (%s)\n", __func__);
return ret;
}
static void do_unregister_framebuffer(fb_info_t *fb_info)
{
registered_fb[fb_info->node] = NULL;
num_registered_fb--;
/* this may free fb info */
put_fb_info(fb_info);
}
int register_framebuffer(fb_info_t *info)
{
int ret;
if (aos_mutex_lock(&fb_mutex, AOS_WAIT_FOREVER) != 0) {
LOGE(FB_STR, "Failed to lock mutex (%s).", __func__);
return -1;
}
ret = do_register_framebuffer(info);
aos_mutex_unlock(&fb_mutex);
return ret;
}
void unregister_framebuffer(fb_info_t *info)
{
if (aos_mutex_lock(&fb_mutex, AOS_WAIT_FOREVER) != 0) {
LOGE(FB_STR, "Failed to lock mutex (%s).", __func__);
return;
}
do_unregister_framebuffer(info);
aos_mutex_unlock(&fb_mutex);
}
int fb_init(void)
{
int i;
int ret = 0;
ret = aos_mutex_new((aos_mutex_t *)&fb_mutex);
if (unlikely(ret)) {
printf("create fb mutex failed\n");
return -1;
}
ret = aos_register_driver(fb_node_path, &fb_fops, NULL);
if (unlikely(ret))
return -1;
for (i = 0; i < FB_MAX; i++)
registered_fb[i] = NULL;
return ret;
}
fb_info_t *framebuffer_alloc(size_t size)
{
int fb_info_size = sizeof(fb_info_t);
fb_info_t *info;
char *p;
if (size)
fb_info_size += PADDING;
p = aos_malloc(fb_info_size + size);
if (!p)
return NULL;
info = (fb_info_t *) p;
if (size)
info->par = p + fb_info_size;
return info;
}
/**
* framebuffer_release - marks the structure available for freeing
*
* @info: frame buffer info structure
*
*/
void framebuffer_release(fb_info_t *info)
{
if (!info)
return;
aos_free(info);
}
LEVEL0_DRIVER_ENTRY(fb_init)
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
// #include <fb.h>
#include <fb_rotate.h>
/*rotate 90 degrees clockwise*/
void rotate_cw(const uint8_t *in, uint8_t *out, uint32_t w, uint32_t h)
{
int32_t i, ix, iy, res; /* Default is RGBA8888 */
if (in && out) {
for (iy = 0; iy < h; iy++) {
for (ix = 0; ix < w; ix++)
((uint32_t *)out)[h - 1 - iy + h * ix] = ((uint32_t *)in)[ix + iy * w];
}
}
return;
}
......@@ -15,49 +15,49 @@ extern "C" {
#endif
/**
* @brief Get a TTY device.
* @param[out] ref TTY ref to operate
* @param[in] id TTY device ID
* @return 0: on success; < 0: on failure
* @brief Get a TTY device.
* @param ref TTY ref to operate.
* @param id TTY device ID.
* @return 0: on success; < 0: on failure.
*/
aos_status_t aos_tty_get(aos_tty_ref_t *ref, uint32_t id);
/**
* @brief Release a TTY device.
* @param[in] ref TTY ref to operate
* @return None
* @brief Release a TTY device.
* @param ref TTY ref to operate.
* @return None.
*/
void aos_tty_put(aos_tty_ref_t *ref);
/**
* @brief Get the parameters associated with a TTY device.
* @param[in] ref TTY ref to operate
* @param[out] termios POSIX-compliant termios struct
* @return 0: on success; < 0: on failure
* @brief Get the parameters associated with a TTY device.
* @param ref TTY ref to operate.
* @param termios POSIX-compliant termios structure.
* @return 0: on success; < 0: on failure.
*/
aos_status_t aos_tty_get_attr(aos_tty_ref_t *ref, struct termios *termios);
/**
* @brief Set the parameters associated with a TTY device.
* @param[in] ref TTY ref to operate
* @param[in] optional_actions specifie when the changes take effect
* @param[in] termios POSIX-compliant termios struct
* @return 0: on success; < 0: on failure
* @brief Set the parameters associated with a TTY device.
* @param ref TTY ref to operate.
* @param optional_actions Specifie when the changes take effect.
* @param termios POSIX-compliant termios structure.
* @return 0: on success; < 0: on failure.
*/
aos_status_t aos_tty_set_attr(aos_tty_ref_t *ref, int optional_actions, const struct termios *termios);
/**
* @brief Read data from a TTY device.
* @param[in] ref TTY ref to operate
* @param[out] buf data buffer
* @param[in] count attempt to read up to count bytes
* @param[in] timeout timeout in milliseconds
* @return > 0: the number of bytes read; < 0: on failure
* @brief Read data from a TTY device.
* @param ref TTY ref to operate.
* @param buf Data buffer.
* @param count Attempt to read up to count bytes.
* @param timeout Timeout in milliseconds.
* @return > 0: the number of bytes read; < 0: on failure.
*/
ssize_t aos_tty_read(aos_tty_ref_t *ref, void *buf, size_t count, uint32_t timeout);
/**
* @brief Write data to a TTY device.
* @param[in] ref TTY ref to operate
* @param[in] buf data buffer
* @param[in] count attempt to write up to count bytes
* @param[in] timeout timeout in milliseconds
* @return > 0: the number of bytes written; < 0: on failure
* @brief Write data to a TTY device.
* @param ref TTY ref to operate.
* @param buf Data buffer.
* @param count Attempt to write up to count bytes.
* @param timeout Timeout in milliseconds.
* @return > 0: the number of bytes written; < 0: on failure.
*/
ssize_t aos_tty_write(aos_tty_ref_t *ref, const void *buf, size_t count, uint32_t timeout);
......
......@@ -54,6 +54,7 @@ extern "C" {
#endif
aos_status_t aos_tty_register(aos_tty_t *tty);
aos_status_t aos_tty_register_argumented(aos_tty_t *tty, uint32_t id, const aos_tty_ops_t *ops, uint32_t flags);
aos_status_t aos_tty_unregister(uint32_t id);
size_t aos_tty_rx_buffer_produce(aos_tty_t *tty, const void *buf, size_t count);
......
......@@ -4,7 +4,7 @@
#include <aos/tty_core.h>
#define STA_TX_EN ((uint32_t)1 << 0)
#define STA_TX_EN ((uint32_t)1 << 0) /* reserved for XON/XOFF flow control */
#define RW_BUDGET 256
#define RX_COUNT_THRESHOLD ((size_t)UINT8_MAX)
......@@ -481,7 +481,8 @@ static size_t tx_buffer_produce(aos_tty_t *tty, const void *buf, size_t count)
if (old_count == 0 && new_count > 0) {
aos_event_set(&tty->event, ~EVENT_TX_EMPTY, AOS_EVENT_AND);
tty->ops->start_tx(tty);
if (tty->status & STA_TX_EN)
tty->ops->start_tx(tty);
}
aos_spin_unlock_irqrestore(&tty->lock, flags);
......@@ -640,6 +641,10 @@ aos_status_t aos_tty_register(aos_tty_t *tty)
if (!tty)
return -EINVAL;
if (!tty->ops || !tty->ops->startup || !tty->ops->shutdown || !tty->ops->set_attr ||
!tty->ops->enable_rx || !tty->ops->disable_rx || !tty->ops->start_tx || !tty->ops->stop_tx)
return -EINVAL;
tty->dev.type = AOS_DEV_TYPE_TTY;
tty->dev.ops = &dev_tty_ops;
#ifdef AOS_COMP_VFS
......@@ -668,6 +673,18 @@ aos_status_t aos_tty_register(aos_tty_t *tty)
return 0;
}
aos_status_t aos_tty_register_argumented(aos_tty_t *tty, uint32_t id, const aos_tty_ops_t *ops, uint32_t flags)
{
if (!tty)
return -EINVAL;
tty->dev.id = id;
tty->ops = ops;
tty->flags = flags;
return aos_tty_register(tty);
}
aos_status_t aos_tty_unregister(uint32_t id)
{
return aos_dev_unregister(AOS_DEV_TYPE_TTY, id);
......
......@@ -24,6 +24,8 @@ extern "C" {
#define DT_SOCK 12
#define DT_WHT 14
#define DIRSIZ(dp) (offsetof(struct dirent, d_name) + ((strlen((dp)->d_name) + 1 + 3) & ~3))
typedef aos_dir_t DIR;
struct dirent {
......
......@@ -61,6 +61,73 @@ void seekdir(DIR *dirp, long loc)
return aos_seekdir((aos_dir_t *)dirp, loc);
}
int scandir(const char *dirname, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **))
{
int num_entry = 0;
int array_size = 16;
DIR *dirp;
struct dirent *d, *p;
struct dirent **names, **names_new;
if ((dirname == NULL) || (namelist == NULL)) {
errno = EINVAL;
return -1;
}
dirp = opendir(dirname);
if (dirp == NULL)
return -1;
names = (struct dirent **)malloc(sizeof(struct dirent *) * array_size);
if (names == NULL) {
errno = ENOMEM;
goto error;
}
while ((d = readdir(dirp)) != NULL) {
if ((filter != NULL) && ((*filter)(d) == 0))
continue;
p = (struct dirent *) malloc(DIRSIZ(d));
if (p == NULL) {
errno = ENOMEM;
goto error;
}
p->d_ino = d->d_ino;
p->d_type = d->d_type;
strncpy(p->d_name, d->d_name, strlen(d->d_name));
if (num_entry >= array_size) {
names_new = realloc(names, sizeof(struct dirent *) * array_size * 2);
if (names_new == NULL) {
free(p);
errno = ENOMEM;
goto error;
}
names = names_new;
array_size *= 2;
}
names[num_entry++] = p;
}
closedir(dirp);
if ((num_entry > 0) && (compar != NULL))
qsort(names, num_entry, sizeof(struct dirent *), (void *)compar);
*namelist = names;
return num_entry;
error:
while (num_entry > 0)
free(names[num_entry--]);
free(names);
closedir(dirp);
return -1;
}
int mkdir(const char *path, mode_t mode)
{
int ret;
......
......@@ -9,7 +9,6 @@
int prctl(int option, ...)
{
int ret = 0;
va_list ap;
unsigned long arg;
......
......@@ -79,7 +79,6 @@ static void do_pthread_cleanup(pthread_tcb_t *ptcb)
/* Exit the pthread, never return. */
void pthread_exit(void* value_ptr)
{
int ret = 0;
pthread_tcb_t *ptcb = NULL;
ptcb = __pthread_get_tcb(pthread_self());
......@@ -131,7 +130,6 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
int ret = 0;
pthread_tcb_t *ptcb = NULL; /* The ptcb of new thread. */
pthread_tcb_t *ptcb_c = NULL; /* The ptcb of current thread. */
uint32_t stack_size = 0;
int kpolicy = 0;
int kpriority = 0;
......@@ -389,7 +387,6 @@ int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param
{
int ret = 0;
pthread_tcb_t *ptcb = NULL;
uint8_t old_priority = 0;
uint8_t priority = 0;
int kpolicy = 0;
......
......@@ -224,8 +224,8 @@ int pthread_attr_getscope(const pthread_attr_t *restrict attr, int *restrict con
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
{
if ((attr == NULL) || (contentionscope != PTHREAD_SCOPE_PROCESS) &&
(contentionscope != PTHREAD_SCOPE_SYSTEM)) {
if ((attr == NULL) ||
((contentionscope != PTHREAD_SCOPE_PROCESS) && (contentionscope != PTHREAD_SCOPE_SYSTEM))) {
return EINVAL;
}
......
......@@ -20,7 +20,8 @@ static inline pthread_t _pid_to_pthread(pid_t pid)
return NULL;
}
return (pthread_t)pid;
/* todo, not surpport */
return (pthread_t)(uintptr_t)pid;
}
/* Convert pid to ptcb of the thread. */
......
......@@ -133,8 +133,6 @@ int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
/* unlock a semaphore */
int sem_post(sem_t *sem)
{
int ret = 0;
if (sem == NULL) {
errno = EINVAL;
return -1;
......@@ -148,8 +146,6 @@ int sem_post(sem_t *sem)
/* get the value of a semaphore */
int sem_getvalue(sem_t *sem, int *sval)
{
int ret = 0;
if ((sem == NULL) || (sval == NULL)) {
errno = EINVAL;
return -1;
......@@ -162,8 +158,6 @@ int sem_getvalue(sem_t *sem, int *sval)
/* close a named semaphore */
int sem_close(sem_t *sem)
{
int ret = 0;
if (sem == NULL) {
errno = EINVAL;
return -1;
......@@ -176,8 +170,6 @@ int sem_close(sem_t *sem)
/* remove a named semaphore */
int sem_unlink(const char *name)
{
int ret = 0;
if (name == NULL) {
errno = EINVAL;
return -1;
......
......@@ -210,8 +210,6 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *restrict
int ret = 0;
int64_t value_ns = 0;
int64_t interval_ns = 0;
int64_t value_ticks = 0;
int64_t interval_ticks = 0;
struct timespec value_spec = {0};
struct timespec interval_spec = {0};
timer_list_t *timer_list = NULL;
......
......@@ -79,7 +79,7 @@
# Release Note
## 2021-10-12
## 2021-08-26
- JavaScript轻应用:IoT-Device修复publish内存泄漏问题、优化物模型初始化流程;IoT-Gateway增加NTP时间获取功能、完善拓扑管理、子设备注册和登陆登出等API;新增以太网配网功能,支持静态IP配网;新增UDP功能;更新JS轻应用版本信息获取接口;修复setTimeout、SPI的write问题等
- python轻应用:micropython引擎升级到V1.17;API对齐HaaS轻应用接口标准;新增BLE支持;GPIO适配层重构;封装Python视觉AI接口
- components:新增linkkit、ble_mesh、genie_service组件用于天猫精灵IoT生态的接入;
......
......@@ -75,7 +75,23 @@ key_value["ldflag"] += " --specs=nosys.specs"
# and call cmake to build
comp_path = os.path.dirname(sys.argv[0])
build_cmd = '%s-gcc %s %s -E -D__ARM__ -D__ALIGN__=4 -P %s/_haas1000_alios.c -o %s/_haas1000_alios.lds' % (key_value["toolchain"], key_value["cflag"], key_value["macro_list"], comp_path, comp_path)
macro_path = "macro_defines.h"
f = open(macro_path, 'w')
data_list = key_value["macro_list"].split('-D')
for item in data_list:
k_list = item.split('=')
if len(k_list) < 2:
continue
head = "#ifndef " + k_list[0] + "\n"
f.write(head)
data = item.replace('=', " ")
f.write("#define "+ data + "\n")
f.write("#endif\n\n")
f.close()
build_cmd = '%s-gcc %s -imacros %s -E -D__ARM__ -D__ALIGN__=4 -P %s/_haas1000_alios.c -o %s/_haas1000_alios.lds' % (key_value["toolchain"], key_value["cflag"], macro_path, comp_path, comp_path)
print(build_cmd)
ret = os.system(build_cmd) >> 8
if ret != 0:
......
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#include <drv/pwm.h>
#include <aos/pwm_core.h>
#include "hal_pwm.h"
#include "hal_gpio.h"
#include "hal_trace.h"
#include "hal_iomux.h"
#include "hal_cmu.h"
#include "pmu.h"
#define NS_PER_SEC (1000000000UL)
#define DIV_ROUND_CLOSEST(x, divisor)( \
{ \
typeof(x) __x = x; \
typeof(divisor) __d = divisor; \
(((typeof(x))-1) > 0 || \
((typeof(divisor))-1) > 0 || \
(((__x) > 0) == ((__d) > 0))) ? \
(((__x) + ((__d) / 2)) / (__d)) : \
(((__x) - ((__d) / 2)) / (__d)); \
} \
)
typedef struct {
aos_pwm_t aos_pwm;
void *priv;
} haas1000_pwm_t;
#define _HAL_PWM_MAX_NUM 4
static struct HAL_IOMUX_PIN_FUNCTION_MAP pinmux_pwm[_HAL_PWM_MAX_NUM] = {
{ HAL_IOMUX_PIN_P2_6, HAL_IOMUX_FUNC_PWM0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
{ HAL_IOMUX_PIN_P2_7, HAL_IOMUX_FUNC_PWM1, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
{ HAL_IOMUX_PIN_P2_4, HAL_IOMUX_FUNC_PWM2, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
{ HAL_IOMUX_PIN_P2_5, HAL_IOMUX_FUNC_PWM3, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
};
static uint8_t pwm_chan[_HAL_PWM_MAX_NUM] = {0};
static void haas1000_pwm_uninit(haas1000_pwm_t *pwm)
{
return;
}
int haas1000_pwm_out_config(haas1000_pwm_t *pwm, uint32_t channel, uint32_t period_ns,
uint32_t pulse_width_ns, csi_pwm_polarity_t polarity)
{
struct HAL_PWM_CFG_T cfg;
if (channel >= _HAL_PWM_MAX_NUM)
return 0;
if (pwm_chan[channel] == 0) {
hal_iomux_init(&pinmux_pwm[channel], 1);
hal_gpio_pin_set_dir(pinmux_pwm[channel].pin, HAL_GPIO_DIR_OUT, 1);
}
pwm_chan[channel] = 1;
if (period_ns == 0) {
hal_pwm_disable(channel);
} else {
cfg.freq = DIV_ROUND_CLOSEST(NS_PER_SEC, period_ns);
cfg.ratio = DIV_ROUND_CLOSEST(((uint64_t)pulse_width_ns) * 100, period_ns);
cfg.inv = polarity;
cfg.sleep_on = false;
hal_pwm_enable(channel, &cfg);
}
return 0;
}
static int haas1000_pwm_out_start(haas1000_pwm_t *pwm_dev, uint32_t channel)
{
return 0;
}
static int haas1000_pwm_out_stop(haas1000_pwm_t *pwm_dev, uint32_t channel)
{
uint32_t pwm_chan = channel;
hal_pwm_disable(pwm_chan);
return 0;
}
static void haas1000_pwm_unregister(aos_pwm_t *pwm)
{
haas1000_pwm_t *pwm_dev = aos_container_of(pwm, haas1000_pwm_t, aos_pwm);
haas1000_pwm_uninit(pwm_dev);
}
static int haas1000_pwm_startup(aos_pwm_t *pwm)
{
return 0;
}
static void haas1000_pwm_shutdown(aos_pwm_t *pwm)
{
haas1000_pwm_t *pwm_dev = aos_container_of(pwm, haas1000_pwm_t, aos_pwm);
haas1000_pwm_out_stop(pwm_dev, pwm_dev->aos_pwm.dev.id);
}
static int haas1000_pwm_apply(aos_pwm_t *pwm, aos_pwm_attr_t const *attr)
{
uint32_t period;
uint32_t duty_cycle;
haas1000_pwm_t *pwm_dev = aos_container_of(pwm, haas1000_pwm_t, aos_pwm);
period = attr->period;
duty_cycle = attr->duty_cycle;
haas1000_pwm_out_config(pwm_dev, pwm_dev->aos_pwm.dev.id,
period, duty_cycle, attr->polarity);
if (attr->enabled)
haas1000_pwm_out_start(pwm_dev, pwm_dev->aos_pwm.dev.id);
else
haas1000_pwm_out_stop(pwm_dev, pwm_dev->aos_pwm.dev.id);
return 0;
}
static const aos_pwm_ops_t haas1000_pwm_ops = {
.unregister = haas1000_pwm_unregister,
.apply = haas1000_pwm_apply,
.shutdown = haas1000_pwm_shutdown,
.startup = haas1000_pwm_startup
};
static int haas1000_pwm_init(void)
{
int ret;
static haas1000_pwm_t pwm_dev[CONFIG_PWM_NUM];
int i;
for (i = 0; i < CONFIG_PWM_NUM; i++) {
pwm_dev[i].aos_pwm.dev.id = i;
pwm_dev[i].aos_pwm.ops = &haas1000_pwm_ops;
ret = aos_pwm_register(&(pwm_dev[i].aos_pwm));
if (ret != 0) {
return ret;
}
}
return 0;
}
LEVEL1_DRIVER_ENTRY(haas1000_pwm_init)
......@@ -72,7 +72,7 @@ static spi_ctx_obj_t spi_ctx[2] =
.spi_pin_DIO = HAL_IOMUX_PIN_P3_5,
.spi_fun_DI0 = HAL_IOMUX_FUNC_SPILCD_DI0,
.spi_fun_CLK = HAL_IOMUX_FUNC_SPILCD_CLK,
.spi_fun_CS0 = HAL_IOMUX_FUNC_AS_GPIO,
.spi_fun_CS0 = HAL_IOMUX_FUNC_SPILCD_CS0,
.spi_fun_DIO = HAL_IOMUX_FUNC_SPILCD_DIO,
.spi_dma_semaphore = NULL,
.spi_mutex_id = 0,
......
......@@ -128,7 +128,8 @@ source_file:
- "csi/iic.c"
- "csi/wdt.c"
- "csi/flash.c"
- "csi/pwm.c"
#- "csi/pwm.c"
- "aos_driver/pwm/pwm.c"
# - "hal/2ndboot/wdg.c"
# - "hal/2ndboot/sys.c"
# - "hal/2ndboot/uart.c"
......@@ -169,7 +170,7 @@ def_config:
CONFIG_U_PWM_DEV: 1
CONFIG_U_PWM_CORE: 1
CONFIG_I2C_NUM: 2
CONFIG_PWM_NUM: 2
CONFIG_PWM_NUM: 4
CONFIG_QSPI_NUM: 0
CONFIG_SPI_NUM: 2
CONFIG_TIMER_NUM: 1
......
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#include <drv/pwm.h>
#include <aos/pwm_core.h>
#include "device.h"
#include "objects.h"
#include "pinmap.h"
#define BIT_PWM_TIM_IDX_FLAG BIT(7)
#define BIT_PWM_TIM_IDX_SHIFT 7
#define PWM_TIMER 5
#define DIV_ROUND_CLOSEST(x, divisor)( \
{ \
typeof(x) __x = x; \
typeof(divisor) __d = divisor; \
(((typeof(x))-1) > 0 || \
((typeof(divisor))-1) > 0 || \
(((__x) > 0) == ((__d) > 0))) ? \
(((__x) + ((__d) / 2)) / (__d)) : \
(((__x) - ((__d) / 2)) / (__d)); \
} \
)
typedef struct {
aos_pwm_t aos_pwm;
uint8_t idx;
void *priv;
} rtl872xd_pwm_t;
/* Table elements express the pin to PWM channel number, they are:
* {pinName, km0_pin2chan, km4_pin2chan}
*/
static const u32 pin2chan[18][2] = {
{ PA_12, 0 },
{ PA_13, 1 },
{ PA_23, 2 },
{ PA_24, 3 },
{ PA_25, 4 },
{ PA_26, 5 },
{ PA_28, 6 },
{ PA_30, 7 },
{ PB_4, 8 },
{ PB_5, 9 },
{ PB_18, 10 },
{ PB_19, 11 },
{ PB_20, 12 },
{ PB_21, 13 },
{ PB_22, 14 },
{ PB_23, 15 },
{ PB_24, 16 },
{ PB_7, 17 } // this channel also can be PB_7
};
static RTIM_TypeDef *RTL872xD_PWM_TIM[2] = { TIM5, TIMM05 };
static u8 km4_ch_start[18] = { 0 };
static void rtl872xd_pwm_uninit(rtl872xd_pwm_t *pwm_dev)
{
uint32_t pwm_chan = pwm_dev->idx & (~BIT_PWM_TIM_IDX_FLAG);
uint8_t pwm_tim_idx = pwm_dev->idx >> BIT_PWM_TIM_IDX_SHIFT;
if (km4_ch_start[pwm_chan]) {
km4_ch_start[pwm_chan] = 0;
RTIM_CCxCmd(RTL872xD_PWM_TIM[pwm_tim_idx], pwm_chan, TIM_CCx_Disable);
/* stop timer5 if no pwm channels starts */
for (pwm_chan = 0; pwm_chan < 18; pwm_chan++) {
if (km4_ch_start[pwm_chan]) {
return;
}
}
RTIM_Cmd(RTL872xD_PWM_TIM[pwm_tim_idx], DISABLE);
}
if (pwm_dev && pwm_dev->priv) {
free(pwm_dev->priv);
pwm_dev->priv = NULL;
}
}
static int rtl872xd_pwm_out_config(rtl872xd_pwm_t *pwm_dev, uint32_t channel, uint32_t period_ns,
uint32_t pulse_width_ns, csi_pwm_polarity_t polarity)
{
uint32_t arr, tmp, ccrx;
uint32_t period;
float pulse, value, dc;
uint8_t pwm_tim_idx = pwm_dev->idx >> BIT_PWM_TIM_IDX_SHIFT;
TIM_CCInitTypeDef *TIM_CCInitStruct = (TIM_CCInitTypeDef *)pwm_dev->priv;
u32 prescaler = 0;
if (channel > 18) {
return 0;
}
RTIM_CCStructInit(TIM_CCInitStruct);
RTIM_CCxInit(RTL872xD_PWM_TIM[pwm_tim_idx], TIM_CCInitStruct, channel);
RTIM_CCxCmd(RTL872xD_PWM_TIM[pwm_tim_idx], channel, TIM_CCx_Enable);
PinName pin = pin2chan[channel][0];
if (km4_ch_start[channel] == 0) {
if (pwm_tim_idx) {
Pinmux_Config(pin, PINMUX_FUNCTION_PWM_LP);
} else {
Pinmux_Config(pin, PINMUX_FUNCTION_PWM_HS);
}
}
km4_ch_start[channel] = 1;
tmp = DIV_ROUND_CLOSEST(((uint64_t)period_ns * 40), 1000);
tmp = tmp / (prescaler + 1);
/*
* psr is 8bits
*/
if (tmp > 0x10000) {
prescaler = DIV_ROUND_CLOSEST(((uint64_t)period_ns * 40), 1000);
prescaler = DIV_ROUND_CLOSEST(prescaler, 0x10000);
if (prescaler > 0xff) {
prescaler = 0xff;
}
RTIM_PrescalerConfig(RTL872xD_PWM_TIM[pwm_tim_idx], prescaler, TIM_PSCReloadMode_Update);
}
/*
* arr is 16bits
*/
/*
* 40M oscilator
*/
arr = DIV_ROUND_CLOSEST(((uint64_t)period_ns * 40), 1000);
arr = DIV_ROUND_CLOSEST(arr, (prescaler + 1)) - 1;
if (arr > 0xffff) {
arr = 0xffff;
}
RTIM_ChangePeriod(RTL872xD_PWM_TIM[pwm_tim_idx], arr);
ccrx = DIV_ROUND_CLOSEST(((uint64_t)(period_ns - pulse_width_ns) * 40), 1000);
ccrx = (ccrx / (prescaler + 1)) & 0x0000ffff;
RTIM_CCRxSet(RTL872xD_PWM_TIM[pwm_tim_idx], ccrx, channel);
if (0 == polarity)
RTIM_CCxPolarityConfig(RTL872xD_PWM_TIM[pwm_tim_idx], TIM_CCPolarity_Low, channel);
else
RTIM_CCxPolarityConfig(RTL872xD_PWM_TIM[pwm_tim_idx], TIM_CCPolarity_High, channel);
return 0;
}
static int rtl872xd_pwm_out_start(rtl872xd_pwm_t *pwm_dev, uint32_t channel)
{
uint32_t pwm_chan = channel;
uint8_t pwm_tim_idx = pwm_dev->idx >> BIT_PWM_TIM_IDX_SHIFT;
RTIM_CCxCmd(RTL872xD_PWM_TIM[pwm_tim_idx], pwm_chan, TIM_CCx_Enable);
return 0;
}
static int rtl872xd_pwm_out_stop(rtl872xd_pwm_t *pwm_dev, uint32_t channel)
{
uint32_t pwm_chan = channel;
uint8_t pwm_tim_idx = pwm_dev->idx >> BIT_PWM_TIM_IDX_SHIFT;
RTIM_CCxCmd(RTL872xD_PWM_TIM[pwm_tim_idx], pwm_chan, TIM_CCx_Disable);
return 0;
}
static void rtl872xd_pwm_unregister(aos_pwm_t *pwm)
{
rtl872xd_pwm_t *pwm_dev = aos_container_of(pwm, rtl872xd_pwm_t, aos_pwm);
rtl872xd_pwm_uninit(pwm_dev);
}
static int rtl872xd_pwm_startup(aos_pwm_t *pwm)
{
return 0;
}
static void rtl872xd_pwm_shutdown(aos_pwm_t *pwm)
{
rtl872xd_pwm_t *pwm_dev = aos_container_of(pwm, rtl872xd_pwm_t, aos_pwm);
rtl872xd_pwm_out_stop(pwm_dev, pwm_dev->aos_pwm.dev.id);
}
static int rtl872xd_pwm_apply(aos_pwm_t *pwm, aos_pwm_attr_t const *attr)
{
uint32_t period;
uint32_t duty_cycle;
rtl872xd_pwm_t *pwm_dev = aos_container_of(pwm, rtl872xd_pwm_t, aos_pwm);
period = attr->period;
duty_cycle = attr->duty_cycle;
rtl872xd_pwm_out_config(pwm_dev, pwm_dev->aos_pwm.dev.id,
period, duty_cycle, attr->polarity);
if (attr->enabled)
rtl872xd_pwm_out_start(pwm_dev, pwm_dev->aos_pwm.dev.id);
else
rtl872xd_pwm_out_stop(pwm_dev, pwm_dev->aos_pwm.dev.id);
return 0;
}
static const aos_pwm_ops_t rtl872xd_pwm_ops = {
.unregister = rtl872xd_pwm_unregister,
.apply = rtl872xd_pwm_apply,
.shutdown = rtl872xd_pwm_shutdown,
.startup = rtl872xd_pwm_startup
};
static int rtl872xd_pwm_init(void)
{
int ret;
static rtl872xd_pwm_t pwm_dev[CONFIG_PWM_NUM];
int idx = 0, i;
RTIM_TimeBaseInitTypeDef TIM_InitStruct;
RTIM_TimeBaseStructInit(&TIM_InitStruct);
TIM_InitStruct.TIM_Idx = PWM_TIMER;
RTIM_TimeBaseInit(RTL872xD_PWM_TIM[idx], &TIM_InitStruct, TIMER5_IRQ, NULL, (u32)&TIM_InitStruct);
RTIM_Cmd(RTL872xD_PWM_TIM[idx], ENABLE);
for (i = 0; i < CONFIG_PWM_NUM; i++) {
pwm_dev[i].priv = (TIM_CCInitTypeDef *)malloc(sizeof(TIM_CCInitTypeDef));
pwm_dev[i].idx = idx << BIT_PWM_TIM_IDX_SHIFT;
pwm_dev[i].idx |= (i) & (~BIT_PWM_TIM_IDX_FLAG);
if (ret != 0) {
return ret;
}
pwm_dev[i].aos_pwm.dev.id = i;
pwm_dev[i].aos_pwm.ops = &rtl872xd_pwm_ops;
ret = aos_pwm_register(&(pwm_dev[i].aos_pwm));
if (ret != 0) {
return ret;
}
}
return 0;
}
LEVEL1_DRIVER_ENTRY(rtl872xd_pwm_init)
......@@ -166,7 +166,7 @@ source_file:
- csi_driver/adc/adc.c
- csi_driver/gpio/gpio.c
- csi_driver/iic/iic.c
- csi_driver/pwm/pwm.c
- aos_driver/pwm/pwm.c
- csi_driver/spi/spi.c
- csi_driver/spiflash/spiflash.c
- csi_driver/timer/timer.c
......
......@@ -9,13 +9,53 @@
#include <k_api.h>
#include <stdio.h>
#include <stdlib.h>
#include <uservice/uservice.h>
#include <uservice/eventid.h>
#include "aos/cli.h"
#include "haas_main.h"
#define AMP_TYPE_MAX_LEN 32
#define AMP_TYPE_JS "JS"
#define AMP_TYPE_PYTHON "Python"
extern int amp_main(void);
static void amp_set_command(int argc, char **argv)
{
if (argc < 2) {
printf("Usge: amp_set [JS/Python]\r\n");
return;
}
if (strcmp(argv[1], AMP_TYPE_JS) == 0) {
aos_kv_set("amp_type", AMP_TYPE_JS, strlen(AMP_TYPE_JS));
} else if (strcmp(argv[1], AMP_TYPE_PYTHON) == 0) {
aos_kv_set("amp_type", AMP_TYPE_PYTHON, strlen(AMP_TYPE_PYTHON));
}
}
/* reg args: fun, cmd, description*/
ALIOS_CLI_CMD_REGISTER(amp_set_command, amp_set, set amp startup type)
int application_start(int argc, char *argv[])
{
int count = 0;
int len = 0;
int ret = 0;
aos_task_t amp_task;
char amp_type[AMP_TYPE_MAX_LEN] = {0};
printf("haas dev demp entry here!\r\n");
len = 32;
ret = aos_kv_get("amp_type", amp_type, &len);
if ((ret == 0) && (strcmp(amp_type, AMP_TYPE_JS) == 0)) {
/* Start JS engine. */
aos_task_new_ext(&amp_task, "amp_task", amp_main, NULL, 8192, AOS_DEFAULT_APP_PRI - 2);
} else {
/* Start Python engine. */
haas_main(argc, argv);
}
while (1) {
aos_msleep(10000);
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册