[sync] sync code from internal

This commit is contained in:
jzlv 2023-02-24 21:33:12 +08:00
parent e70e482d21
commit dd161b698b
302 changed files with 36006 additions and 27903 deletions

BIN
BouffaloSDK.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

146
README.md
View file

@ -1,26 +1,30 @@
[![License](https://img.shields.io/badge/License-Apache--2.0-brightgreen)](LICENSE)
[![Release](https://img.shields.io/github/v/tag/bouffalolab/bl_mcu_sdk?color=s&label=release)]()
[中文版](README_zh.md)
# Introduction
**bl mcu sdk** is an MCU software development kit provided by the Bouffalo Lab Team, supports all the series of Bouffalo chips.
**BouffaloSDK** is an MCU software development kit provided by the Bouffalo Lab Team, supports all the series of Bouffalo chips.
# SDK Versions & Chip Support
# SDK Architecture
Note1: **drivers before v1.4.5 use v1.0hal + std, the later version will use v2.0 (lhal + soc)**。If you want to use **v1.4.5**, please checkout your branch to [release-v1.4.5](https://github.com/bouffalolab/bl_mcu_sdk/tree/release_v1.4.5).
![SDK Architecture](BouffaloSDK.png)
Note2: due to the non-generic peripherals, the code style and interface name in **soc** are still the previous version, but will be subsequently updated to the new code style.
# Code Directoryies
| CHIP | v1.4.5 | latest |
|:-------------:|:--------:|:-------:|
|BL602/BL604 | √ | √ |
|BL702/BL704/BL706 | √ | √ |
|BL616/BL618 | × | √ |
|BL808 | × | √ |
| Name | Description |
|:---:|:------:|
| bsp/board | clock, pinmux, memoryheap and console init |
| bsp/common | bsp common driver|
| components| components|
|docs | quick start、 api、demo doc|
|drivers/lhal| bouffalo common peripherals drivers which support all the chips|
|drivers/soc| bouffalo non-generic peripherals drivers|
|drivers/rfparam| rf param |
|examples| official samples|
|tools| tools |
## LHAL Support
# LHAL Support
**LHAL** is a low level hal driver for common peripherals designed by Bouffalo Lab, in order to support all the Bouffalo chips with the same api . Also it is convenient for users to use and port to other platforms.
@ -29,17 +33,18 @@ Note**√** means supported ; **×** means not supported; **○** means suppo
| Peripheral | BL602/BL604 | BL702/BL704/BL706 | BL616/BL618 | BL808 |
|:------------:|:--------------:|:--------------------:|:-----------:|:--------:|
| ADC | ○ | √ | √ | ○ |
| CAM | - | √ | √ | √ |
| CAM | - | × | × | × |
| CKS | ○ | √ | √ | ○ |
| DAC | ○ | √ | √ | ○ |
| DMA | ○ | √ | √ | √ |
| EFUSE | √ | √ | √ | √ |
| EFUSE | × | × | × | × |
| EMAC | - | √ | √ | √ |
| FLASH | √ | √ | √ | √ |
| GPIO | ○ | √ | √ | √ |
| I2C | ○ | √ | √ | √ |
| I2C | ○ | √ | √ | ○ |
| I2S | ○ | ○ | √ | ○ |
| IR | ○ | √ | √ | ○ |
| MJPEG | × | | √ | √ |
| MJPEG | × | × | √ | √ |
| PWM_v1 | ○ | √ | - | - |
| PWM_v2 | - | - | √ | √ |
| RTC | ○ | √ | √ | √ |
@ -54,56 +59,6 @@ Note**√** means supported ; **×** means not supported; **○** means suppo
| USB_v2 | - | - | √ | √ |
| WDG | ○ | √ | √ | ○ |
## Code Framework
```
bl_mcu_sdk
├── bsp
│ ├── board
│ │ └── bl602
│ │ └── bl702
│ │ └── bl616
│ │ └── bl808
│ └── common
├── components
│ ├── bflog
│ ├── cherryusb
│ ├── fatfs
│ ├── freertos
│ ├── lua
│ ├── lvgl
│ ├── lwip
│ └── shell
├── docs
├── drivers
│ ├── lhal
│ └── soc
├── examples
│ ├── bflog
│ ├── fatfs
│ ├── freertos
│ ├── helloworld
│ ├── lua
│ ├── lvgl
│ ├── peripherals
│ └── shell
└── tools
└── cmake
└── kconfig
└── make
```
- **bsp/board** : including clock, pinmux, memoryheap and console init
- **bsp/common** : including bsp common driver
- **components** : including third-party components
- **docs** : including docs
- **drivers/lhal** : including bouffalo common peripherals drivers which support all the chips
- **drivers/soc** : including bouffalo non-generic peripherals drivers
- **examples** : including samples
- **tools** : including compiler tools
# Environment Setup
## Toolchain
@ -114,7 +69,7 @@ bl_mcu_sdk
## Command Line Development
Before compiling with the command line, you need to select the corresponding toolchain according to your operating system, configure it to the system environment variables, and install the **make** or **ninja**, then you can do the following. For the details, you can visit [bl mcu sdk Environment Setup](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/index.html).
Before compiling with the command line, you need to select the corresponding toolchain according to your operating system, configure it to the system environment variables, and install the **make** or **ninja**, then you can do the following. For the details, you can visit [BouffaloSDK Environment Setup](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/index.html).
- Go to the demo directory where you want to compile and there are `main.c` and `Makefile` files in that directory
- Just execute the following command, take **BL616** as an example
@ -133,50 +88,65 @@ cd examples/helloworld
make ninja CHIP=bl616 BOARD=bl616dk
```
```
cd examples/helloworld
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
```
## CDK Development
TODO
## Debug
Only supports debug with CKLink currently. See [bl mcu sdk Debug Guide](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/debug.html).
Only supports debug with CKLink currently. See [BouffaloSDK Debug Guide](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/debug.html).
## Firmware Download
We recommend you to use this **BL DevCube** and download firmware with serial.
Note that if you are using linux, linux will deny access to the serial device due to permission issues, so add your own username to `dialout` for easy to use, restart your linux and then take effect. Or add `sudo` before command.
- [Bouffalo Lab Dev Cube](https://dev.bouffalolab.com/download)
- [Bouffalo Lab Dev Cube User Guide](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/devcube.html)
```
usermod -aG dialout xxx # xxx is your own name
```
```
cd examples/helloworld
make flash CHIP=chip_name COMX=xxx # chip_name should be bl602/bl702/bl616/bl808/bl606p, COMX in Windows, /dev/ttyxxx in Linux
```
- If you use **BL808** or **BL606P**, you need to add **CPU_ID** with m0 or d0.
```
cd examples/helloworld
make flash CHIP=chip_name CPU_ID=m0 COMX=xxx # chip_name should be bl602/bl702/bl616/bl808/bl606p, COMX in Windows, /dev/ttyxxx in Linux
```
If flash using serial port rather than USB, different USB2TTL chips support different max baudrates, need to pay attention to when flashing.
| chip | baudrate|
|:---:|:------:|
| ch340 | <= 500K |
| cp2102 | <= 2M |
| ft232 | <= 2M |
| bl702 | <= 8M |
| bl616 | <= 10M |
# Resources
## Chip Manual
**Chip Reference Manual** and **Chip Data Manual** are listed on [document](https://github.com/bouffalolab/bl_docs)
**Chip Reference Manual** and **Chip Data Manual** are listed on [document](https://dev.bouffalolab.com/document)
## Documentation Tutorial
To get more bl mcu sdk documentation tutorial, like api manual or peripheral demo and so on, please visit:
To get more BouffaloSDK documentation tutorial, like api manual or peripheral demo and so on, please visit:
- [bl mcu sdk v2.0 documentation tutorial](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/)
- [bl mcu sdk v1.4.5 documentation tutorial](https://dev.bouffalolab.com/media/doc/sdk/bl_mcu_sdk_en/index.html)
- [BouffaloSDK documentation tutorial](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/)
## Video Tutorial
- [BL706 MCU Development Series Video Tutorial](https://www.bilibili.com/video/BV1xK4y1P7ur)
TODO
## Forum
Bouffalolab Developer Forum: [https://bbs.bouffalolab.com/](https://bbs.bouffalolab.com/)
# License
**bl mcu sdk** follows the Apache License 2.0 open source license agreement. It can be used in commercial products for free and does not require public private code.
```
/*
* Copyright (c) 2022 Bouffalolab team
*
* SPDX-License-Identifier: Apache-2.0
*/
```

View file

@ -1,26 +1,30 @@
[![License](https://img.shields.io/badge/License-Apache--2.0-brightgreen)](LICENSE)
[![Release](https://img.shields.io/github/v/tag/bouffalolab/bl_mcu_sdk?color=s&label=release)]()
[English Version](README.md)
# 简介
**bl mcu sdk** 是 Bouffalo Lab 提供的 MCU 软件开发包,支持博流智能所有系列芯片。
**BouffaloSDK** 是 Bouffalo Lab 提供的软件开发包,支持博流智能所有系列芯片。
# SDK 版本与芯片支持情况
# SDK 架构
注意1**v1.4.5 版本之前的驱动库使用 1.0 版本hal + std之后的版本都将使用 2.0 版本 (lhal + soc)**。如果使用 **v1.4.5** ,请切换分支到 [release-v1.4.5](https://github.com/bouffalolab/bl_mcu_sdk/tree/release_v1.4.5)。
![SDK Architecture](BouffaloSDK.png)
注意2**soc** 由于是非通用的外设,代码风格和接口名还是延续之前版本,但是后续会更新到新的代码风格。
# 代码目录
| 芯片 | v1.4.5 | latest |
|:-------------:|:--------:|:-------:|
|BL602/BL604 | √ | √ |
|BL702/BL704/BL706 | √ | √ |
|BL616/BL618 | × | √ |
|BL808 | × | √ |
| 名称 | 描述|
|:---:|:------:|
| bsp/board | 包含时钟、引脚、内存管理和 console 的板级初始化 |
| bsp/common | 板级相关的常用外设驱动|
| components| 组件|
|docs | 快速上手、 api、demo 文档|
|drivers/lhal| 博流智能系列芯片通用外设驱动,支持所有系列芯片|
|drivers/soc| 博流智能系列芯片非通用外设驱动|
|drivers/rfparam| 射频参数配置|
|examples| 官方示例代码|
|tools| 工具 |
## LHAL 支持情况
# LHAL 支持
**LHAL** 是博流为统一通用外设接口而设计的驱动库,代码精炼并且支持博流所有系列芯片,方便用户使用和移植到其他平台。
@ -29,17 +33,18 @@
| 外设 | BL602/BL604 | BL702/BL704/BL706 | BL616/BL618 | BL808 |
|:------------:|:--------------:|:--------------------:|:-----------:|:--------:|
| ADC | ○ | √ | √ | ○ |
| CAM | - | √ | √ | √ |
| CAM | - | × | × | × |
| CKS | ○ | √ | √ | ○ |
| DAC | ○ | √ | √ | ○ |
| DMA | ○ | √ | √ | √ |
| EFUSE | | √ | √ | √ |
| EFUSE | × | √ | √ | √ |
| EMAC | - | √ | √ | √ |
| FLASH | √ | √ | √ | √ |
| GPIO | ○ | √ | √ | √ |
| I2C | ○ | √ | √ | √ |
| I2C | ○ | √ | √ | ○ |
| I2S | ○ | ○ | √ | ○ |
| IR | ○ | √ | √ | ○ |
| MJPEG | × | | √ | √ |
| MJPEG | × | × | √ | √ |
| PWM_v1 | ○ | √ | - | - |
| PWM_v2 | - | - | √ | √ |
| RTC | ○ | √ | √ | √ |
@ -54,56 +59,6 @@
| USB_v2 | - | - | √ | √ |
| WDG | ○ | √ | √ | ○ |
# 代码框架
```
bl_mcu_sdk
├── bsp
│ ├── board
│ │ └── bl602
│ │ └── bl702
│ │ └── bl616
│ │ └── bl808
│ └── common
├── components
│ ├── bflog
│ ├── cherryusb
│ ├── fatfs
│ ├── freertos
│ ├── lua
│ ├── lvgl
│ ├── lwip
│ └── shell
├── docs
├── drivers
│ ├── lhal
│ └── soc
├── examples
│ ├── bflog
│ ├── fatfs
│ ├── freertos
│ ├── helloworld
│ ├── lua
│ ├── lvgl
│ ├── peripherals
│ └── shell
└── tools
└── cmake
└── kconfig
└── make
```
- **bsp/board** : 包含时钟、引脚、内存管理和 console 的板级初始化
- **bsp/common** : 存放一些板级相关的常用外设驱动代码
- **components** : 存放第三方库公共组件
- **docs** : 存放教程文档以及其他帮助信息
- **drivers/lhal** : 存放博流智能系列芯片通用外设驱动,支持所有系列芯片
- **drivers/soc** : 存放博流智能系列芯片非通用外设驱动,各个芯片独有的部分
- **examples** : 存放官方提供的示例代码
- **tools** : 存放编译下载相关的工具包
# 环境搭建
## 工具链
@ -114,7 +69,7 @@ bl_mcu_sdk
## 命令行编译
在进行命令行编译之前,需要根据你的操作系统,选择对应的工具链,并配置到系统环境变量,并安装了 **make** 或者 **ninja** 工具,然后才能进行下面操作。更详细的搭建过程,参考 [bl mcu sdk 环境搭建](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/index.html).
在进行命令行编译之前,需要根据你的操作系统,选择对应的工具链,并配置到系统环境变量,并安装了 **make** 或者 **ninja** 工具,然后才能进行下面操作。更详细的搭建过程,参考 [BouffaloSDK 环境搭建](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/index.html).
- 进入要编译的 demo 目录,且该目录下有 `main.c``Makefile` 文件
- 执行下面命令即可,以 **BL616** 为例
@ -135,7 +90,7 @@ make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
```
cd examples/helloworld
make ninja CHIP=bl616 BOARD=bl616dk
make ninja CHIP=bl808 BOARD=bl808dk CPU_ID=m0
```
## CDK 编译
@ -144,43 +99,52 @@ TODO
## 调试
当前仅支持使用 CKLink 调试。详细参考 [bl mcu sdk 调试指南](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/debug.html)。
当前仅支持使用 CKLink 调试。详细参考 [BouffaloSDK 调试指南](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/debug.html)。
## 固件烧录
推荐使用 **BL DevCube** 并通过串口进行固件的烧录
需要注意,如果使用的是 linuxlinux 由于权限问题会拒绝访问串口设备,所以,为了方便后续使用,将你自己的用户名添加到 `dialout` 中。然后重启 linux 生效。或者在命令的前面加上 `sudo`
- [Bouffalo Lab Dev Cube](https://dev.bouffalolab.com/download)
- [Bouffalo Lab Dev Cube User Guide](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/get_started/devcube.html)
```
sudo usermod -aG dialout xxx # xxx 是你自己的用户名
```
```
cd examples/helloworld
make flash CHIP=chip_name COMX=xxx # chip_name should be bl602/bl702/bl616/bl808/bl606p, COMX in Windows, /dev/ttyxxx in Linux
```
- 如果使用 **BL808** 或者 **BL606P** ,需要添加 **CPU_ID**
```
cd examples/helloworld
make flash CHIP=chip_name CPU_ID=m0 COMX=xxx # chip_name should be bl602/bl702/bl616/bl808/bl606p, COMX in Windows, /dev/ttyxxx in Linux
```
如果使用串口烧录而非 USB 烧录,不同的 USB2TTL 芯片支持的最高波特率不一样,烧录的时候需要注意。
| 芯片 | 波特率|
|:---:|:------:|
| ch340 | <= 500K |
| cp2102 | <= 2M |
| ft232 | <= 2M |
| bl702 | <= 8M |
| bl616 | <= 10M |
# 芯片手册
芯片数据手册和参考手册见 [文档](https://github.com/bouffalolab/bl_docs)。
芯片数据手册和参考手册见 [文档](https://dev.bouffalolab.com/document)。
# 文档教程
获取更多 bl mcu sdk 开发相关的教程,如环境搭建、 api 手册、外设 demo 等,请参考:
获取更多 BouffaloSDK 开发相关的教程,如环境搭建、 api 手册、外设 demo 等,请参考:
- [bl mcu sdk v2.0 文档教程](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/)
- [bl mcu sdk v1.4.5 文档教程](https://dev.bouffalolab.com/media/doc/sdk/bl_mcu_sdk_zh/index.html)
- [BouffaloSDK 文档教程](https://bl-mcu-sdk.readthedocs.io/zh_CN/latest/)
# 视频教程
- [BL706 MCU 开发系列视频教程](https://www.bilibili.com/video/BV1xK4y1P7ur)
TODO
# 论坛
博流开发者交流论坛: [https://bbs.bouffalolab.com/](https://bbs.bouffalolab.com/)
# 许可协议
**bl mcu sdk** 遵循 Apache License 2.0 开源许可协议,可以免费在商业产品中使用,并且不需要公开私有代码。
```
/*
* Copyright (c) 2022 Bouffalolab team
*
* SPDX-License-Identifier: Apache-2.0
*/
```

View file

@ -24,10 +24,21 @@ if(CONFIG_BSP_LCD)
target_sources(app PRIVATE lcd/lcd.c)
target_sources(app PRIVATE lcd/font.c)
target_sources(app PRIVATE lcd/mipi_dbi/bl_mipi_dbi_typeb_pec.c)
target_sources(app PRIVATE lcd/mipi_dbi/bl_mipi_dbi.c)
target_sources(app PRIVATE lcd/mipi_dbi/ili9488_dbi.c)
target_sources(app PRIVATE lcd/mipi_dbi/ili9341_dbi.c)
target_sources(app PRIVATE lcd/spi/bl_spi_hard_4.c)
target_sources(app PRIVATE lcd/spi/ili9341_spi.c)
target_sources(app PRIVATE lcd/spi/ili9488_spi.c)
target_sources(app PRIVATE lcd/spi/st7796_spi.c)
target_sources(app PRIVATE lcd/spi/st7789v_spi.c)
target_sources(app PRIVATE lcd/mipi_dpi/bl_mipi_dpi_pec.c)
target_sources(app PRIVATE lcd/mipi_dpi/standard_dpi.c)
target_sources(app PRIVATE lcd/mipi_dpi/ili9488_dpi.c)
target_sources(app PRIVATE lcd/mipi_dpi/gc9503v_dpi.c)
sdk_add_include_directories(lcd)
endif()

View file

@ -25,6 +25,11 @@
#include "font.h"
#include "bflb_core.h"
#if defined(LCD_RESET_EN)
#include "bflb_gpio.h"
#include "bflb_mtimer.h"
#endif
uint8_t lcd_dir = 0;
uint16_t lcd_max_x = LCD_W - 1, lcd_max_y = LCD_H - 1;
@ -40,11 +45,43 @@ int lcd_init(void)
{
int res;
#if defined(LCD_RESET_EN)
struct bflb_device_s *gpio;
/* gpio init */
gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, LCD_RESET_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
/* lcd reset */
#if LCD_RESET_ACTIVE_LEVEL
bflb_gpio_set(gpio, LCD_RESET_PIN);
#else
bflb_gpio_reset(gpio, LCD_RESET_PIN);
#endif
bflb_mtimer_delay_ms(LCD_RESET_HOLD_MS);
/* lcd recovery */
#if LCD_RESET_ACTIVE_LEVEL
bflb_gpio_reset(gpio, LCD_RESET_PIN);
#else
bflb_gpio_set(gpio, LCD_RESET_PIN);
#endif
bflb_mtimer_delay_ms(LCD_RESET_DELAY);
#endif
res = _LCD_FUNC_DEFINE(init);
return res;
}
static int lcd_async_callback_enable(bool enable)
{
_LCD_FUNC_DEFINE(async_callback_enable, enable);
return 0;
}
int lcd_async_callback_register(void (*callback)(void))
{
_LCD_FUNC_DEFINE(async_callback_register, callback);
@ -281,13 +318,15 @@ int lcd_draw_str_ascii16(uint16_t x, uint16_t y, lcd_color_t color, lcd_color_t
uint8_t ch, temp;
uint16_t x0 = x;
lcd_async_callback_enable(false);
for (uint16_t i = 0; i < num && str[i]; i++) {
if (str[i] < 128) {
// if (x > LCD_W - 8) {
// x = x0;
// y += 16;
// }
if (x > LCD_W - 8 || y > LCD_H - 16)
if (x > lcd_max_x - 8) {
x = x0;
y += 16;
}
if (x > lcd_max_x - 8 || y > lcd_max_y - 16)
break;
ch = str[i];
@ -326,6 +365,8 @@ int lcd_draw_str_ascii16(uint16_t x, uint16_t y, lcd_color_t color, lcd_color_t
}
while (lcd_draw_is_busy()) {
};
lcd_async_callback_enable(true);
return 0;
}
#endif

View file

@ -26,42 +26,15 @@
#include "font.h"
#include "bflb_core.h"
#include "lcd_conf.h"
/* List of supported LCD */
/* mipi dbi interface
LCD_DBI_ILI9488
LCD_DISP_QSPI_GC9C01
*/
/* mipi dpi (RGB) interface
LCD_DPI_ILI9488
LCD_DPI_ST7701S
LCD_DPI_STANDARD
*/
/* mipi dsi vidio interface
LCD_DSI_VIDIO_ILI9881C
*/
/* spi interface
LCD_SPI_ILI9488
LCD_SPI_ILI9481
LCD_SPI_ILI9341
LCD_SPI_ST7796
LCD_SPI_ST7789V
*/
/* Select screen Type */
#define LCD_SPI_ST7789V
/* Do not modify the following */
#define LCD_INTERFACE_SPI 1
#define LCD_INTERFACE_DBI 2
#define LCD_INTERFACE_DPI 3
#define LCD_INTERFACE_DSI_VIDIO 4
/* */
#if defined LCD_DBI_ILI9488
#include "mipi_dbi/ili9488_dbi.h"
@ -71,6 +44,15 @@
#define LCD_COLOR_DEPTH ILI9488_DBI_COLOR_DEPTH
#define _LCD_FUNC_DEFINE(_func, ...) ili9488_dbi_##_func(__VA_ARGS__)
#elif defined LCD_DBI_ILI9341
#include "mipi_dbi/ili9341_dbi.h"
#define LCD_INTERFACE_TYPE LCD_INTERFACE_DBI
#define LCD_W ILI9341_DBI_W
#define LCD_H ILI9341_DBI_H
#define LCD_COLOR_DEPTH ILI9341_DBI_COLOR_DEPTH
#define _LCD_FUNC_DEFINE(_func, ...) ili9341_dbi_##_func(__VA_ARGS__)
#elif defined LCD_DISP_QSPI_GC9C01
#include "disp_qspi/gc9c01_disp_qspi.h"
@ -89,6 +71,15 @@
#define LCD_COLOR_DEPTH ILI9488_DPI_COLOR_DEPTH
#define _LCD_FUNC_DEFINE(_func, ...) ili9488_dpi_##_func(__VA_ARGS__)
#elif defined LCD_DPI_GC9503V
#include "mipi_dpi/gc9503v_dpi.h"
#define LCD_INTERFACE_TYPE LCD_INTERFACE_DPI
#define LCD_W GC9503V_DPI_W
#define LCD_H GC9503V_DPI_H
#define LCD_COLOR_DEPTH GC9503V_DPI_COLOR_DEPTH
#define _LCD_FUNC_DEFINE(_func, ...) gc9503v_dpi_##_func(__VA_ARGS__)
#elif defined LCD_DPI_ST7701S
#include "mipi_dpi/st7701s_dpi.h"

528
bsp/common/lcd/lcd_conf.h Normal file
View file

@ -0,0 +1,528 @@
#ifndef _LCD_CONF_H_
#define _LCD_CONF_H_
#if __has_include("lcd_conf_user.h")
/* User external configuration, User need to use this file as a template */
#include "lcd_conf_user.h"
#else
#warning "There is no user LCD conf file and the default conf will be used"
/* clang-format off */
/* Select screen Type, Optional:
mipi dbi interface
LCD_DBI_ILI9488
mipi dpi (RGB) interface
LCD_DPI_ILI9488
LCD_DPI_GC9503V
LCD_DPI_STANDARD
mipi dsi vidio interface
LCD_DSI_VIDIO_ILI9881C
spi interface
LCD_SPI_ILI9488
LCD_SPI_ILI9341
LCD_SPI_ST7796
LCD_SPI_ST7789V
*/
#define LCD_DBI_ILI9488
/* dbi ili9488 config */
#if defined LCD_DBI_ILI9488
/* Selecting interface type, more configuration of peripherals comes later
1: DBI peripheral, supported functions: typeC-3wire, typeC-4wire, typeB-x8(8080); (support chips: bl616, bl606p, bl808),
2: PEC simulation, supported functions: typeB-x8; (support chips: bl616),
*/
#define LCD_DBI_INTERFACE_TYPE 1
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* Selecting pixel format
1: rgb565 (16-bit, output rgb565)
2: nrgb8888 (32-bit, output rgb888)
*/
#define ILI9488_DBI_PIXEL_FORMAT 1
/* ILI9488 LCD width and height */
#define ILI9488_DBI_W 320
#define ILI9488_DBI_H 480
/* The offset of the area can be displayed */
#define ILI9488_DBI_OFFSET_X 0
#define ILI9488_DBI_OFFSET_Y 0
/* Color reversal, Some screens are required
0: disable
1: enable
*/
#define ILI9488_DBI_COLOR_REVERSAL 0
/* dbi ili9341 config */
#elif defined LCD_DBI_ILI9341
/* Selecting interface type, more configuration of peripherals comes later
1: DBI peripheral, supported functions: typeC-3wire, typeC-4wire, typeB-x8(8080); (support chips: bl616, bl606p, bl808),
2: PEC simulation, supported functions: typeB-x8; (support chips: bl616),
*/
#define LCD_DBI_INTERFACE_TYPE 1
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* Selecting pixel format
1: rgb565 (16-bit, output rgb565)
2: nrgb8888 (32-bit, output rgb888)
*/
#define ILI9341_DBI_PIXEL_FORMAT 1
/* ILI9341 LCD width and height */
#define ILI9341_DBI_W 240
#define ILI9341_DBI_H 320
/* The offset of the area can be displayed */
#define ILI9341_DBI_OFFSET_X 0
#define ILI9341_DBI_OFFSET_Y 0
/* Color reversal, Some screens are required
0: disable
1: enable
*/
#define ILI9341_DBI_COLOR_REVERSAL 0
#endif
/* dpi gc9503v config */
#if defined LCD_DPI_GC9503V
/* Selecting DPI working mode
1: DPI peripheral (support: bl808)
2: PEC simulation (support: bl616, bl628)
*/
#define GC9503V_DPI_MODE 2
/* Selecting initialization interface
1: Software spi 9-bit mode
*/
#define GC9503V_DPI_INIT_INTERFACE 1
#if(GC9503V_DPI_INIT_INTERFACE == 1)
#define GC9503V_DPI_SPI_CS_PIN GPIO_PIN_12
#define GC9503V_DPI_SPI_CLK_PIN GPIO_PIN_24
#define GC9503V_DPI_SPI_DAT_PIN GPIO_PIN_25
#endif
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* Selecting pixel format
1: rgb565 (16-bits)
2: nrgb8888 (32-bits, Do not support PEC simulation)
*/
#define GC9503V_DPI_PIXEL_FORMAT 1
/* ILI9488 LCD width and height */
#define GC9503V_DPI_W 480
#define GC9503V_DPI_H 480
/* dpi ili9488 config */
#elif defined LCD_DPI_ILI9488
/* Selecting DPI working mode
1: DPI peripheral (support: bl808)
2: PEC simulation (support: bl616, bl628)
*/
#define ILI9488_DPI_MODE 2
/* Selecting initialization interface
1: Hardware spi 8-bit mode
2: Hardware dbi peripheral typeC (support: bl616, bl606p, bl808)
*/
#define ILI9488_DPI_INIT_INTERFACE 1
#if(ILI9488_DPI_INIT_INTERFACE == 1)
#define ILI9488_DPI_SPI_CS_PIN GPIO_PIN_20
#define ILI9488_DPI_SPI_DC_PIN GPIO_PIN_3
#endif
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* Selecting pixel format
1: rgb565 (16-bits)
2: nrgb8888 (32-bits, Do not support PEC simulation)
*/
#define ILI9488_DPI_PIXEL_FORMAT 1
/* ILI9488 LCD width and height */
#define ILI9488_DPI_W 320
#define ILI9488_DPI_H 480
/* dpi standard config */
#elif defined LCD_DPI_STANDARD
/* Selecting DPI working mode
1: DPI peripheral (support: bl808)
2: PEC simulation (support: bl616, bl628)
*/
#define STANDARD_DPI_MODE 2
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 0
/* Selecting pixel format
1: rgb565 (16-bits)
2: nrgb8888 (32-bits, Do not support PEC simulation)
*/
#define STANDARD_DPI_PIXEL_FORMAT 1
/* STANDARD LCD width and height */
#define STANDARD_DPI_W 800
#define STANDARD_DPI_H 480
/* RGB timing parameter Settings
Total Width = HSW + HBP + Active_Width + HFP
Total Height = VSW + VBP + Active_Height + VFP */
/* Hsync Pulse Width */
#define STANDARD_DPI_HSW 4
/* Hsync Back Porch */
#define STANDARD_DPI_HBP 82
/* Hsync Front Porch */
#define STANDARD_DPI_HFP 14
/* Vsync Pulse Width */
#define STANDARD_DPI_VSW 5
/* Vsync Back Porch */
#define STANDARD_DPI_VBP 6
/* Vsync Front Porch */
#define STANDARD_DPI_VFP 39
/* Maximum refresh frame rate per second, Used to automatically calculate the clock frequency */
#define STANDARD_DPI_FRAME_RATE 70
/* spi ili9488 config */
#elif defined LCD_SPI_ILI9488
/* Selecting interface type, more configuration of peripherals comes later
1: SPI peripheral, supported functions: spi-4wire,
*/
#define LCD_SPI_INTERFACE_TYPE 1
/* Selecting pixel format
1: rgb565
*/
#define ILI9488_SPI_PIXEL_FORMAT 1
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* ILI9488 LCD width and height */
#define ILI9488_SPI_W 320
#define ILI9488_SPI_H 480
/* The offset of the area can be displayed */
#define ILI9488_SPI_OFFSET_X 0
#define ILI9488_SPI_OFFSET_Y 0
/* Color reversal, Some screens are required
0: disable
1: enable
*/
#define ILI9488_SPI_COLOR_REVERSAL 0
/* spi ili9341 config */
#elif defined LCD_SPI_ILI9341
/* Selecting interface type, more configuration of peripherals comes later
1: SPI peripheral, supported functions: spi-4wire,
*/
#define LCD_SPI_INTERFACE_TYPE 1
/* Selecting pixel format
1: rgb565, 16-bit/pixel
*/
#define ILI9341_SPI_PIXEL_FORMAT 1
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* LCD width and height */
#define ILI9341_SPI_W 240
#define ILI9341_SPI_H 320
/* The offset of the area can be displayed */
#define ILI9341_SPI_OFFSET_X 0
#define ILI9341_SPI_OFFSET_Y 0
/* Color reversal, Some screens are required
0: disable
1: enable
*/
#define ILI341_SPI_COLOR_REVERSAL 0
/* spi st7789v config */
#elif defined LCD_SPI_ST7789V
/* Selecting interface type, more configuration of peripherals comes later
1: SPI peripheral, supported functions: spi-4wire,
*/
#define LCD_SPI_INTERFACE_TYPE 1
/* Selecting pixel format
1: rgb565
*/
#define ST7789V_SPI_PIXEL_FORMAT 1
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* LCD width and height */
#define ST7789V_SPI_W 320
#define ST7789V_SPI_H 480
/* The offset of the area can be displayed */
#define ST7789V_SPI_OFFSET_X 0
#define ST7789V_SPI_OFFSET_Y 0
/* spi st7796 config */
#elif defined LCD_SPI_ST7796
/* Selecting interface type, more configuration of peripherals comes later
1: SPI peripheral, supported functions: spi-4wire,
*/
#define LCD_SPI_INTERFACE_TYPE 1
/* Selecting pixel format
1: rgb565
*/
#define ST7796_SPI_PIXEL_FORMAT 1
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* LCD width and height */
#define ST7796_SPI_W 320
#define ST7796_SPI_H 480
/* The offset of the area can be displayed */
#define ST7796_SPI_OFFSET_X 0
#define ST7796_SPI_OFFSET_Y 0
/* Color reversal, Some screens are required
0: disable
1: enable
*/
#define ST7796_SPI_COLOR_REVERSAL 0
#endif
/********** PEC simulation DPI configuration **********/
#if ((defined ILI9488_DPI_MODE) && (ILI9488_DPI_MODE == 2)) || \
((defined GC9503V_DPI_MODE) && (GC9503V_DPI_MODE == 2)) || \
((defined STANDARD_DPI_MODE) && (STANDARD_DPI_MODE == 2))
/* supports 16-wire and 8-wire-latch output modes */
/* For internal use, do not modify */
#define LCD_PEC_SIMU_DPI_ENABLE
/* dma used by pec */
#define LCD_PEC_DPI_DMA_NAME "dma0_ch3"
/* The mode of data latch.
0: 16-bit *1-cycle date out;
1: 8-bit *2-cycle date out, Low 8-bit latch, high 8-bit pass-through, Additional latch devices are required */
#define LCD_PEC_DPI_DATA_LATCH_MODE 1
/* enable the lcd reset function
0: Does not care about lcd hard reset
1: use gpio to reset the lcd
*/
#define LCD_RESET_EN 1
/* Signal polarity selection */
#define LCD_PEC_DPI_V_SYNC_SIN_POL 0
#define LCD_PEC_DPI_H_SYNC_SIN_POL 0
#define LCD_PEC_DPI_DE_SIN_POL 1
/* Selecting pin
The numbers of some pins must be consecutive, and cannot cross the 32 boundary.
Rules: PIN_DE = PIN_CLK + 1; PIN_LATCH = PIN_CLK + 2;
PIN_VSYNC = PIN_HSYNC + 1;
PIN_DATA_n = PIN_DATA_START + n;
*/
#define LCD_DPI_PEC_SIMU_PIN_CLK GPIO_PIN_32
#define LCD_DPI_PEC_SIMU_PIN_HSYNC GPIO_PIN_18
#define LCD_DPI_PEC_SIMU_PIN_DATA_START GPIO_PIN_24 /* 8-wire(latch mode) or 16-wire */
/* Maximum number of DPI invalid rows, >= (VHW + VBP + VFP) */
#define LCD_DPI_PEC_INVALID_LIN_MAX 300
/* cache num of dma_lli, >= 2,
Performance is best when the value is no less than the number of disp_buffs used */
#define LCD_DPI_PEC_DMA_LLI_CACHE_NUM 3
#endif
/********** DBI peripheral configuration ***********/
#if (defined(LCD_DBI_INTERFACE_TYPE) && (LCD_DBI_INTERFACE_TYPE == 1))
/* Select the working mode of DBI
1: DBI TypeC 4-wire mode
2: DBI TypeC 3-wire mode
3: DBI TypeB x8 mode (8080)
4: DBI QSPI mode (Not the mipi standard. Extra support for QSPI mode)
*/
#define LCD_DBI_WORK_MODE 1
/* dma used by DBI */
#define LCD_DBI_DMA_NAME "dma0_ch3"
/* The maximum amount of data to be transferred affects the number of LLI memory pools */
#define DBI_DBI_DATA_SIZE_MAX (800 * 640 * 4)
/* pin cfg */
#if(LCD_DBI_WORK_MODE == 1)
#define LCD_DBI_TYPEC_PIN_CLK GPIO_PIN_12
#define LCD_DBI_TYPEC_PIN_CS GPIO_PIN_13
#define LCD_DBI_TYPEC_PIN_DAT GPIO_PIN_14
#define LCD_DBI_TYPEC_PIN_DC GPIO_PIN_15
#elif(LCD_DBI_WORK_MODE == 2)
#define LCD_DBI_TYPEC_PIN_CLK GPIO_PIN_12
#define LCD_DBI_TYPEC_PIN_CS GPIO_PIN_13
#define LCD_DBI_TYPEC_PIN_DAT GPIO_PIN_14
#elif(LCD_DBI_WORK_MODE == 3)
#define LCD_DBI_TYPEB_PIN_WR GPIO_PIN_4
#define LCD_DBI_TYPEB_PIN_CS GPIO_PIN_5
#define LCD_DBI_TYPEB_PIN_RD GPIO_PIN_6
#define LCD_DBI_TYPEB_PIN_DC GPIO_PIN_7
#define LCD_DBI_TYPEB_PIN_DAT0 GPIO_PIN_8
#define LCD_DBI_TYPEB_PIN_DAT1 GPIO_PIN_9
#define LCD_DBI_TYPEB_PIN_DAT2 GPIO_PIN_10
#define LCD_DBI_TYPEB_PIN_DAT3 GPIO_PIN_11
#define LCD_DBI_TYPEB_PIN_DAT4 GPIO_PIN_12
#define LCD_DBI_TYPEB_PIN_DAT5 GPIO_PIN_13
#define LCD_DBI_TYPEB_PIN_DAT6 GPIO_PIN_14
#define LCD_DBI_TYPEB_PIN_DAT7 GPIO_PIN_15
#elif(LCD_DBI_WORK_MODE == 4)
#define LCD_DBI_QSPI_PIN_CLK GPIO_PIN_10
#define LCD_DBI_QSPI_PIN_CS GPIO_PIN_11
#define LCD_DBI_QSPI_PIN_DAT0 GPIO_PIN_12
#define LCD_DBI_QSPI_PIN_DAT1 GPIO_PIN_13
#define LCD_DBI_QSPI_PIN_DAT2 GPIO_PIN_14
#define LCD_DBI_QSPI_PIN_DAT3 GPIO_PIN_15
#endif
#endif
/********** PEC simulation DBI configuration ***********/
#if (defined(LCD_DBI_INTERFACE_TYPE) && (LCD_DBI_INTERFACE_TYPE == 2))
/* pec simulation mipi-dbi-typeB config, only 8-wire is supported, the read operation is not supported */
/* dma used by pec */
#define LCD_PEC_DBI_B_DMA_NAME "dma0_ch3"
/* The maximum amount of data to be transferred affects the number of LLI memory pools */
#define DBI_PEC_DBI_DATA_SIZE_MAX (800 * 640 * 4)
/* Selecting pin */
#define LCD_DBI_PEC_SIMU_PIN_DC GPIO_PIN_23
#define LCD_DBI_PEC_SIMU_PIN_WR GPIO_PIN_34
#define LCD_DBI_PEC_SIMU_PIN_DATA GPIO_PIN_24 /* The lowest line of an 8-bit data line */
#endif
/********** SPI hard 4-wire configuration ***********/
#if (defined(LCD_SPI_INTERFACE_TYPE) && (LCD_SPI_INTERFACE_TYPE == 1))
/* spi idx */
#define LCD_SPI_HARD_4_NAME "spi0"
/* dma used by spi */
#define LCD_SPI_HARD_4_DMA_NAME "dma0_ch3"
/* The maximum pixel cnt to be transferred affects the number of LLI memory pools */
#define LCD_SPI_HARD_4_PIXEL_CNT_MAX (800 * 640)
/* spi pin, hardware controlled */
#define LCD_SPI_HARD_4_PIN_CLK GPIO_PIN_13
#define LCD_SPI_HARD_4_PIN_DAT GPIO_PIN_15
/* cs/dc pin, software controlled */
#define LCD_SPI_HARD_4_PIN_CS GPIO_PIN_14
#define LCD_SPI_HARD_4_PIN_DC GPIO_PIN_16
#endif
/********** lcd reset configuration ***********/
#if (defined(LCD_RESET_EN) && LCD_RESET_EN)
/* lcd reset signal pin, please leave blank if not needed */
#define LCD_RESET_PIN GPIO_PIN_12
/* lcd reset signal active level
0: lcd reset at low level
1: lcd reset at high level
*/
#define LCD_RESET_ACTIVE_LEVEL 0
/* lcd reset active hold time (ms) */
#define LCD_RESET_HOLD_MS 10
/* lcd recovery time after reset end (ms) */
#define LCD_RESET_DELAY 100
#endif
#endif
/* clang-format on */
#endif

View file

@ -0,0 +1,303 @@
#include "../lcd.h"
#if (defined(LCD_DBI_INTERFACE_TYPE) && (LCD_DBI_INTERFACE_TYPE == 1))
#if (__has_include("bflb_dbi.h"))
#if ((LCD_DBI_WORK_MODE == 4) && (DBI_QSPI_SUPPORT == 0))
#error : "The DBI of this chip does not support QSPI mode."
#endif
#include "bl_mipi_dbi.h"
#include "bflb_dbi.h"
#include "bflb_dma.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#define LCD_DBI_DMA_LLI_NUM (DBI_DBI_DATA_SIZE_MAX / 4 / 4064 + 1)
/* asynchronous flush interrupt callback */
typedef void (*dbi_callback)(void);
static volatile dbi_callback dbi_async_callback = NULL;
static volatile bool dbi_async_callback_en_flag = true;
/* dma device */
static struct bflb_device_s *dbi_dma_hd;
/* pec dbi typeB device */
static struct bflb_device_s *dbi_hd;
/* The memory space of DMA */
static struct bflb_dma_channel_lli_pool_s dma_tx_llipool[LCD_DBI_DMA_LLI_NUM];
static struct bflb_dma_channel_lli_transfer_s dma_tx_transfers[1];
static volatile bool dbi_async_flag = false;
static volatile bool dbi_async_cycle_fill_flag = false;
static void dbi_tc_callback(int irq, void *arg)
{
/* disable dbi dma */
bflb_dbi_link_txdma(dbi_hd, false);
/* clear flag and mask int */
bflb_dbi_int_clear(dbi_hd, DBI_INTCLR_TC);
bflb_dbi_tcint_mask(dbi_hd, true);
if (dbi_async_flag == false && dbi_async_cycle_fill_flag == false) {
return;
}
if (dbi_async_cycle_fill_flag == true) {
/* enable dma addr increment */
bflb_dma_feature_control(dbi_dma_hd, DMA_CMD_SET_SRCADDR_INCREMENT, true);
}
/* disable DMA request for dbi */
bflb_dbi_link_txdma(dbi_hd, false);
dbi_async_flag = false;
dbi_async_cycle_fill_flag = false;
/* async callback */
if (dbi_async_callback_en_flag && dbi_async_callback != NULL) {
dbi_async_callback();
}
}
int lcd_dbi_async_callback_register(void (*callback)(void))
{
dbi_async_callback = callback;
return 0;
}
int lcd_dbi_async_callback_enable(bool enable)
{
dbi_async_callback_en_flag = enable;
return 0;
}
int lcd_dbi_init(lcd_dbi_init_t *dbi_parra)
{
struct bflb_device_s *gpio;
/* dbi cfg */
struct bflb_dbi_config_s dbi_cfg = {
.clk_mode = DBI_CLOCK_MODE_1,
.clk_freq_hz = dbi_parra->clock_freq,
.tx_fifo_threshold = 3,
#if (LCD_DBI_WORK_MODE == 4)
.cmd_wire_mode = dbi_parra->cmd_wire_dual_en,
.addr_wire_mode = dbi_parra->addr_wire_dual_en,
.data_wire_mode = dbi_parra->data_wire_dual_en,
#endif
};
/* dma cfg */
struct bflb_dma_channel_config_s dma_dbi_config = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_DBI_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR4,
.dst_burst_count = DMA_BURST_INCR4,
.src_width = DMA_DATA_WIDTH_32BIT,
.dst_width = DMA_DATA_WIDTH_32BIT,
};
#if (LCD_DBI_WORK_MODE == 1)
/* dbi typeC 4-wire mode */
dbi_cfg.dbi_mode = DBI_MODE_TYPE_C_4_WIRE;
uint32_t dbi_gpio_func = GPIO_FUNC_DBI_C;
uint8_t dbi_gpio_list[] = { LCD_DBI_TYPEC_PIN_CLK, LCD_DBI_TYPEC_PIN_CS, LCD_DBI_TYPEC_PIN_DAT, LCD_DBI_TYPEC_PIN_DC };
#elif (LCD_DBI_WORK_MODE == 2)
/* dbi typeC 3-wire mode */
dbi_cfg.dbi_mode = DBI_MODE_TYPE_C_3_WIRE;
uint32_t dbi_gpio_func = GPIO_FUNC_DBI_C;
uint8_t dbi_gpio_list[] = { LCD_DBI_TYPEC_PIN_CLK, LCD_DBI_TYPEC_PIN_CS, LCD_DBI_TYPEC_PIN_DAT };
#elif (LCD_DBI_WORK_MODE == 3)
/* dbi typeB x8 mode */
dbi_cfg.dbi_mode = DBI_MODE_TYPE_B;
uint32_t dbi_gpio_func = GPIO_FUNC_DBI_B;
uint8_t dbi_gpio_list[] = { LCD_DBI_TYPEB_PIN_WR, LCD_DBI_TYPEB_PIN_CS, LCD_DBI_TYPEB_PIN_RD, LCD_DBI_TYPEB_PIN_DC,
LCD_DBI_TYPEB_PIN_DAT0, LCD_DBI_TYPEB_PIN_DAT1, LCD_DBI_TYPEB_PIN_DAT2, LCD_DBI_TYPEB_PIN_DAT3,
LCD_DBI_TYPEB_PIN_DAT4, LCD_DBI_TYPEB_PIN_DAT5, LCD_DBI_TYPEB_PIN_DAT6, LCD_DBI_TYPEB_PIN_DAT7 };
#elif (LCD_DBI_WORK_MODE == 4)
/* dbi Ex QSPI */
dbi_cfg.dbi_mode = DBI_MODE_EX_QSPI;
uint32_t dbi_gpio_func = GPIO_FUNC_DBI_QSPI;
uint8_t dbi_gpio_list[] = { LCD_DBI_QSPI_PIN_CLK, LCD_DBI_QSPI_PIN_CS,
LCD_DBI_QSPI_PIN_DAT0, LCD_DBI_QSPI_PIN_DAT1, LCD_DBI_QSPI_PIN_DAT2, LCD_DBI_QSPI_PIN_DAT3 };
#endif
if (dbi_parra->pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_RGB565) {
dbi_cfg.pixel_input_format = DBI_PIXEL_INPUT_FORMAT_RGB_565;
dbi_cfg.pixel_output_format = DBI_PIXEL_OUTPUT_FORMAT_RGB_565;
} else if (dbi_parra->pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888) {
dbi_cfg.pixel_input_format = DBI_PIXEL_INPUT_FORMAT_NRGB_8888;
dbi_cfg.pixel_output_format = DBI_PIXEL_INPUT_FORMAT_NRGB_8888;
}
/* gpio init */
gpio = bflb_device_get_by_name("gpio");
for (uint8_t i = 0; i < sizeof(dbi_gpio_list) / sizeof(dbi_gpio_list[0]); i++) {
bflb_gpio_init(gpio, dbi_gpio_list[i], dbi_gpio_func | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
}
/* dbi init */
dbi_hd = bflb_device_get_by_name("dbi");
bflb_dbi_init(dbi_hd, &dbi_cfg);
/* cs continuous mode */
bflb_dbi_feature_control(dbi_hd, DBI_CMD_CS_CONTINUE, true);
/* dbi tx intertupt init */
bflb_dbi_tcint_mask(dbi_hd, true);
bflb_irq_attach(dbi_hd->irq_num, dbi_tc_callback, NULL);
bflb_irq_enable(dbi_hd->irq_num);
/* dma init */
dbi_dma_hd = bflb_device_get_by_name(LCD_DBI_DMA_NAME);
bflb_dma_channel_init(dbi_dma_hd, &dma_dbi_config);
return 0;
}
#if (LCD_DBI_WORK_MODE == 4)
int lcd_dbi_ex_qspi_addr_cfg(uint8_t addr_byte_size, uint32_t addr_val)
{
bflb_dbi_qspi_set_addr(dbi_hd, addr_byte_size, addr_val);
return 0;
}
#endif
int lcd_dbi_is_busy(void)
{
if (dbi_async_flag || dbi_async_cycle_fill_flag) {
return 1;
} else {
return 0;
}
}
int lcd_dbi_transmit_cmd_para(uint8_t cmd, uint32_t *para, size_t para_num)
{
bflb_dbi_send_cmd_data(dbi_hd, cmd, para_num, (void *)para);
return 0;
}
int lcd_dbi_transmit_cmd_pixel_sync(uint8_t cmd, uint32_t *pixel, size_t pixel_num)
{
bflb_dbi_send_cmd_pixel(dbi_hd, cmd, pixel_num, (void *)pixel);
return 0;
}
int lcd_dbi_transmit_cmd_pixel_async(uint8_t cmd, uint32_t *pixel, size_t pixel_num)
{
uint32_t data_size;
dbi_async_flag = true;
/* get data size */
data_size = bflb_dbi_feature_control(dbi_hd, DBI_CMD_GET_SIZE_OF_PIXEL_CNT, pixel_num);
/* dma transfers cfg */
dma_tx_transfers[0].src_addr = (uint32_t)pixel;
dma_tx_transfers[0].dst_addr = DMA_ADDR_DBI_TDR;
dma_tx_transfers[0].nbytes = data_size;
bflb_dma_channel_lli_reload(dbi_dma_hd, dma_tx_llipool, LCD_DBI_DMA_LLI_NUM, dma_tx_transfers, 1);
/* clean cache */
bflb_l1c_dcache_clean_range((void *)pixel, data_size);
/* trigger dbi data transfer */
bflb_dbi_send_cmd_pixel(dbi_hd, cmd, pixel_num, NULL);
/* unmask int */
bflb_dbi_tcint_mask(dbi_hd, false);
/* enabled DMA request for dbi */
bflb_dbi_link_txdma(dbi_hd, true);
/* enable dma */
bflb_dma_channel_start(dbi_dma_hd);
return 0;
}
int lcd_dbi_transmit_cmd_pixel_fill_sync(uint8_t cmd, uint32_t pixel_val, size_t pixel_num)
{
uint32_t words_cnt;
uint8_t fifo_cnt;
/* get data size */
words_cnt = bflb_dbi_feature_control(dbi_hd, DBI_CMD_GET_SIZE_OF_PIXEL_CNT, pixel_num) / 4;
/* trigger dbi data transfer */
bflb_dbi_send_cmd_pixel(dbi_hd, cmd, pixel_num, NULL);
/* fill data into fifo */
for (; words_cnt > 0;) {
fifo_cnt = bflb_dbi_feature_control(dbi_hd, DBI_CMD_GET_TX_FIFO_CNT, 0);
fifo_cnt = words_cnt > fifo_cnt ? fifo_cnt : words_cnt;
words_cnt -= fifo_cnt;
for (; fifo_cnt > 0; fifo_cnt--) {
putreg32(pixel_val, DMA_ADDR_DBI_TDR);
}
}
/* wait transfer complete */
while ((bflb_dbi_get_intstatus(dbi_hd) & DBI_INTSTS_TC) == 0) {
};
/* clear end flag */
bflb_dbi_int_clear(dbi_hd, DBI_INTCLR_TC);
return 0;
}
int lcd_dbi_transmit_cmd_pixel_fill_async(uint8_t cmd, uint32_t pixel_val, size_t pixel_num)
{
uint32_t data_size;
dbi_async_cycle_fill_flag = true;
/* get data size */
data_size = bflb_dbi_feature_control(dbi_hd, DBI_CMD_GET_SIZE_OF_PIXEL_CNT, pixel_num);
/* dma cycle fill mode */
bflb_dma_feature_control(dbi_dma_hd, DMA_CMD_SET_SRCADDR_INCREMENT, false);
/* dma transfers cfg */
dma_tx_transfers[0].src_addr = (uint32_t)&pixel_val;
dma_tx_transfers[0].dst_addr = DMA_ADDR_DBI_TDR;
dma_tx_transfers[0].nbytes = data_size;
bflb_dma_channel_lli_reload(dbi_dma_hd, dma_tx_llipool, LCD_DBI_DMA_LLI_NUM, dma_tx_transfers, 1);
/* clean cache */
bflb_l1c_dcache_clean_range((void *)&pixel_val, sizeof(pixel_val));
/* trigger dbi data transfer */
bflb_dbi_send_cmd_pixel(dbi_hd, cmd, pixel_num, NULL);
/* unmask int */
bflb_dbi_tcint_mask(dbi_hd, false);
/* enabled DMA request for dbi */
bflb_dbi_link_txdma(dbi_hd, true);
/* enable dma */
bflb_dma_channel_start(dbi_dma_hd);
return 0;
}
#else
#error "Devices that do not support PEC-DBI! Replace the driver port (lcd_conf.h)"
#endif
#endif

View file

@ -0,0 +1,42 @@
#ifndef _BL_MIPI_DBI_PORT_H
#define _BL_MIPI_DBI_PORT_H
#include "../lcd_conf.h"
#if (defined(LCD_DBI_INTERFACE_TYPE) && (LCD_DBI_INTERFACE_TYPE == 1))
/* Do not modify this file ! */
/* Optional pixel format */
#define LCD_DBI_LCD_PIXEL_FORMAT_RGB565 1
#define LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888 2
typedef struct {
uint32_t pixel_format;
uint32_t clock_freq; /* No use */
#if (LCD_DBI_WORK_MODE == 4)
uint8_t cmd_wire_dual_en;
uint8_t addr_wire_dual_en;
uint8_t data_wire_dual_en;
#endif
} lcd_dbi_init_t;
int lcd_dbi_init(lcd_dbi_init_t *dbi_parra);
#if (LCD_DBI_WORK_MODE == 4)
int lcd_dbi_ex_qspi_addr_cfg(uint8_t addr_byte_size, uint32_t addr_val);
#endif
int lcd_dbi_transmit_cmd_para(uint8_t cmd, uint32_t *para, size_t para_num);
int lcd_dbi_transmit_cmd_pixel_sync(uint8_t cmd, uint32_t *pixel, size_t pixel_num);
int lcd_dbi_transmit_cmd_pixel_fill_sync(uint8_t cmd, uint32_t pixel_val, size_t pixel_num);
int lcd_dbi_is_busy(void);
int lcd_dbi_async_callback_enable(bool enable);
int lcd_dbi_async_callback_register(void (*callback)(void));
int lcd_dbi_transmit_cmd_pixel_async(uint8_t cmd, uint32_t *pixel, size_t pixel_num);
int lcd_dbi_transmit_cmd_pixel_fill_async(uint8_t cmd, uint32_t pixel_val, size_t pixel_num);
#endif
#endif

View file

@ -0,0 +1,375 @@
#include "../lcd.h"
#if (defined(LCD_DBI_INTERFACE_TYPE) && (LCD_DBI_INTERFACE_TYPE == 2))
#if (defined(BL616) && __has_include("bflb_pec_ip.h"))
#include "bl_mipi_dbi_typeb_pec.h"
#include "bflb_pec_ip.h"
#include "bflb_dma.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#define LCD_DBI_PEC_DMA_LLI_NUM (DBI_PEC_DBI_DATA_SIZE_MAX / 4 / 4064 + 1)
/* asynchronous flush interrupt callback */
typedef void (*pec_dbi_b_callback)(void);
static volatile pec_dbi_b_callback pec_dbi_b_async_callback = NULL;
static volatile bool pec_dbi_b_async_callback_en_flag = true;
/* dma device */
static struct bflb_device_s *pec_dbi_b_dma_handle;
static struct bflb_dma_channel_config_s dma_pec_config;
/* pec dbi typeB device */
static struct bflb_pec_dbi_b_s pec_dbi_b_handle;
/* The memory space of DMA */
static struct bflb_dma_channel_lli_pool_s dma_tx_llipool[LCD_DBI_PEC_DMA_LLI_NUM];
static struct bflb_dma_channel_lli_transfer_s dma_tx_transfers[1];
static volatile uint32_t pixel_format;
static volatile bool pec_dbi_b_async_flag = false;
static volatile bool pec_dbi_b_async_cycle_fill_flag = false;
/**
* @brief pec_dbi_b_dma_flush_callback
*
* @return
*/
static void pec_dbi_b_dma_flush_callback(void *args)
{
/* disable pec dma */
bflb_pec_dbi_b_dma_enable(&pec_dbi_b_handle, false);
if (pec_dbi_b_async_flag == false && pec_dbi_b_async_cycle_fill_flag == false) {
return;
}
if (pec_dbi_b_async_cycle_fill_flag == true) {
/* enable dma addr increment */
bflb_dma_feature_control(pec_dbi_b_dma_handle, DMA_CMD_SET_SRCADDR_INCREMENT, true);
}
pec_dbi_b_async_flag = false;
pec_dbi_b_async_cycle_fill_flag = false;
/* async callback */
if (pec_dbi_b_async_callback_en_flag && pec_dbi_b_async_callback != NULL) {
pec_dbi_b_async_callback();
}
}
/**
* @brief pec_dbi_b_async_callback_register
*
* @return int
*/
int pec_dbi_b_async_callback_register(void (*callback)(void))
{
pec_dbi_b_async_callback = callback;
return 0;
}
/**
* @brief pec_dbi_b_async_callback_enable
*
* @return int
*/
int pec_dbi_b_async_callback_enable(bool enable)
{
pec_dbi_b_async_callback_en_flag = enable;
return 0;
}
/**
* @brief pec_dbi_b_init
*
* @return int
*/
int pec_dbi_b_init(lcd_mipi_dbi_init_t *dbi_parra)
{
/* pec gpio init */
struct bflb_device_s *gpio;
gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, LCD_DBI_PEC_SIMU_PIN_DC, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
bflb_gpio_init(gpio, LCD_DBI_PEC_SIMU_PIN_WR, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
for (uint8_t i = 0; i < 8; i++) {
bflb_gpio_init(gpio, LCD_DBI_PEC_SIMU_PIN_DATA + i, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
}
/* pec init */
pec_dbi_b_handle.clk_src = 40 * 1000 * 1000;
pec_dbi_b_handle.clk = 10 * 1000 * 1000;
pixel_format = dbi_parra->pixel_format;
if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_RGB565) {
pec_dbi_b_handle.pixel_format = PEC_DBI_B_PIXEL_FORMAT_RGB565;
} else if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888) {
pec_dbi_b_handle.pixel_format = PEC_DBI_B_PIXEL_FORMAT_NRGB8888;
}
pec_dbi_b_handle.pin_dc = LCD_DBI_PEC_SIMU_PIN_DC;
pec_dbi_b_handle.pin_wr = LCD_DBI_PEC_SIMU_PIN_WR;
pec_dbi_b_handle.pin_data = LCD_DBI_PEC_SIMU_PIN_DATA;
pec_dbi_b_handle.pec = PEC0;
pec_dbi_b_handle.sm = PEC_SM3;
pec_dbi_b_handle.fifo_threshold = 3;
bflb_pec_dbi_b_init(&pec_dbi_b_handle);
/* dma init */
dma_pec_config.direction = DMA_MEMORY_TO_PERIPH;
dma_pec_config.src_req = DMA_REQUEST_NONE;
dma_pec_config.dst_req = DMA_REQUEST_PEC0_SM0_TX + pec_dbi_b_handle.sm;
dma_pec_config.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE;
dma_pec_config.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE;
dma_pec_config.src_burst_count = DMA_BURST_INCR4;
dma_pec_config.dst_burst_count = DMA_BURST_INCR4;
dma_pec_config.src_width = DMA_DATA_WIDTH_32BIT;
dma_pec_config.dst_width = DMA_DATA_WIDTH_32BIT;
pec_dbi_b_dma_handle = bflb_device_get_by_name(LCD_PEC_DBI_B_DMA_NAME);
bflb_dma_channel_init(pec_dbi_b_dma_handle, &dma_pec_config);
/* dma int cfg */
bflb_dma_channel_irq_attach(pec_dbi_b_dma_handle, pec_dbi_b_dma_flush_callback, NULL);
return 0;
}
/**
* @brief pec_dbi_b_dma_is_busy, After the call ili9488_spi_draw_picture_dma must check this,
* if pec_dbi_b_dma_is_busy() == 1, Don't allow other draw !!
* can run in the DMA interrupt callback function.
*
* @return int 0:draw end; 1:Being draw
*/
int pec_dbi_b_dma_is_busy(void)
{
if (pec_dbi_b_async_flag || pec_dbi_b_async_cycle_fill_flag) {
return 1;
} else {
return 0;
}
}
int pec_dbi_b_transmit_cmd_para(uint8_t cmd, uint32_t *para, size_t para_num)
{
uint32_t pec_dbi_head;
uint32_t pec_dbi_fifo_address;
int fifo_cnt = 0;
/* Build pec-dbi control head */
pec_dbi_head = bflb_pec_dbi_b_build_head(&pec_dbi_b_handle, PEC_DBI_TRANSMIT_MODE_CMD, cmd, para_num);
/* get pec tx fifo address */
pec_dbi_fifo_address = bflb_pec_dbi_b_get_fifo_address(&pec_dbi_b_handle);
/* uint8 to uint32 */
para_num = (para_num + 3) / 4;
/* get tx fifo level */
do {
fifo_cnt = bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle);
} while (fifo_cnt == 0);
/* Write control head with cmd */
putreg32(pec_dbi_head, pec_dbi_fifo_address);
fifo_cnt--;
/* Write parameter */
for (size_t i = 0; i < para_num; i++) {
/* Get the available fifo depth */
while (fifo_cnt == 0) {
fifo_cnt = bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle);
}
putreg32(para[i], pec_dbi_fifo_address);
fifo_cnt--;
}
return 0;
}
int pec_dbi_b_transmit_cmd_pixel_sync(uint8_t cmd, uint32_t *pixel, size_t pixel_num)
{
uint32_t pec_dbi_head;
uint32_t pec_dbi_fifo_address;
int fifo_cnt = 0;
/* Build pec-dbi control head */
pec_dbi_head = bflb_pec_dbi_b_build_head(&pec_dbi_b_handle, PEC_DBI_TRANSMIT_MODE_PIXEL, cmd, pixel_num);
/* get pec tx fifo address (rgb565) */
pec_dbi_fifo_address = bflb_pec_dbi_b_get_fifo_address(&pec_dbi_b_handle);
if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_RGB565) {
/* uint16 to uint32 */
pixel_num = (pixel_num + 1) / 2;
} else if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888) {
pixel_num = pixel_num;
}
/* get tx fifo level */
do {
fifo_cnt = bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle);
} while (fifo_cnt == 0);
/* Write control head */
putreg32(pec_dbi_head, pec_dbi_fifo_address);
fifo_cnt--;
/* Write pixel */
for (size_t i = 0; i < pixel_num; i++) {
/* Get the available fifo depth */
while (fifo_cnt == 0) {
fifo_cnt = bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle);
}
putreg32(pixel[i], pec_dbi_fifo_address);
fifo_cnt--;
}
return 0;
}
int pec_dbi_b_transmit_cmd_pixel_async(uint8_t cmd, uint32_t *pixel, size_t pixel_num)
{
uint32_t pec_dbi_head;
uint32_t pec_dbi_fifo_address;
pec_dbi_b_async_flag = true;
/* Build pec-dbi control head */
pec_dbi_head = bflb_pec_dbi_b_build_head(&pec_dbi_b_handle, PEC_DBI_TRANSMIT_MODE_PIXEL, cmd, pixel_num);
/* get pec tx fifo address */
pec_dbi_fifo_address = bflb_pec_dbi_b_get_fifo_address(&pec_dbi_b_handle);
if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_RGB565) {
/* uint16 to uint32 */
pixel_num = (pixel_num + 1) / 2;
} else if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888) {
pixel_num = pixel_num;
}
/* get tx fifo level */
while (bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle) == 0) {
};
/* Write control head */
putreg32(pec_dbi_head, pec_dbi_fifo_address);
/* Use dma to do asynchronous writes */
bflb_pec_dbi_b_dma_enable(&pec_dbi_b_handle, true);
/* dma transfers cfg */
dma_tx_transfers[0].src_addr = (uint32_t)pixel;
dma_tx_transfers[0].dst_addr = pec_dbi_fifo_address;
dma_tx_transfers[0].nbytes = pixel_num * 4;
bflb_dma_channel_lli_reload(pec_dbi_b_dma_handle, dma_tx_llipool, LCD_DBI_PEC_DMA_LLI_NUM, dma_tx_transfers, 1);
/* clean cache */
bflb_l1c_dcache_clean_range((void *)pixel, pixel_num * 4);
/* enable dma */
bflb_dma_channel_start(pec_dbi_b_dma_handle);
return 0;
}
int pec_dbi_b_transmit_cmd_pixel_fill_sync(uint8_t cmd, uint32_t pixel_val, size_t pixel_num)
{
uint32_t pec_dbi_head;
uint32_t pec_dbi_fifo_address;
int fifo_cnt = 0;
/* Build pec-dbi control head */
pec_dbi_head = bflb_pec_dbi_b_build_head(&pec_dbi_b_handle, PEC_DBI_TRANSMIT_MODE_PIXEL, cmd, pixel_num);
/* get pec tx fifo address */
pec_dbi_fifo_address = bflb_pec_dbi_b_get_fifo_address(&pec_dbi_b_handle);
if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_RGB565) {
/* uint16 to uint32 */
pixel_num = (pixel_num + 1) / 2;
} else if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888) {
pixel_num = pixel_num;
}
/* get tx fifo level */
do {
fifo_cnt = bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle);
} while (fifo_cnt == 0);
/* Write control head */
putreg32(pec_dbi_head, pec_dbi_fifo_address);
fifo_cnt--;
/* Write pixel */
for (size_t i = 0; i < pixel_num; i++) {
/* Get the available fifo depth */
while (fifo_cnt == 0) {
fifo_cnt = bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle);
}
putreg32(pixel_val, pec_dbi_fifo_address);
fifo_cnt--;
}
return 0;
}
int pec_dbi_b_transmit_cmd_pixel_fill_async(uint8_t cmd, uint32_t pixel_val, size_t pixel_num)
{
uint32_t pec_dbi_head;
uint32_t pec_dbi_fifo_address;
pec_dbi_b_async_cycle_fill_flag = true;
/* Build pec-dbi control head */
pec_dbi_head = bflb_pec_dbi_b_build_head(&pec_dbi_b_handle, PEC_DBI_TRANSMIT_MODE_PIXEL, cmd, pixel_num);
/* get pec tx fifo address */
pec_dbi_fifo_address = bflb_pec_dbi_b_get_fifo_address(&pec_dbi_b_handle);
if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_RGB565) {
/* uint16 to uint32 */
pixel_num = (pixel_num + 1) / 2;
} else if (pixel_format == LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888) {
pixel_num = pixel_num;
}
/* get tx fifo level */
while (bflb_pec_dbi_b_get_fifo_cnt(&pec_dbi_b_handle) == 0) {
};
/* Write control head */
putreg32(pec_dbi_head, pec_dbi_fifo_address);
/* Use dma to do asynchronous writes */
bflb_pec_dbi_b_dma_enable(&pec_dbi_b_handle, true);
/* dma cycle fill mode */
bflb_dma_feature_control(pec_dbi_b_dma_handle, DMA_CMD_SET_SRCADDR_INCREMENT, false);
/* dma transfers cfg */
dma_tx_transfers[0].src_addr = (uint32_t)&pixel_val;
dma_tx_transfers[0].dst_addr = pec_dbi_fifo_address;
dma_tx_transfers[0].nbytes = pixel_num * 4;
bflb_dma_channel_lli_reload(pec_dbi_b_dma_handle, dma_tx_llipool, LCD_DBI_PEC_DMA_LLI_NUM, dma_tx_transfers, 1);
/* clean cache */
bflb_l1c_dcache_clean_range((void *)&pixel_val, sizeof(pixel_val));
/* enable dma */
bflb_dma_channel_start(pec_dbi_b_dma_handle);
return 0;
}
#else
#error "Devices that do not support PEC-DBI! Replace the driver port (lcd_conf.h)"
#endif
#endif

View file

@ -0,0 +1,32 @@
#ifndef _BL_MIPI_DBI_PORT_H
#define _BL_MIPI_DBI_PORT_H
#include "../lcd_conf.h"
#if (defined(LCD_DBI_INTERFACE_TYPE) && (LCD_DBI_INTERFACE_TYPE == 2))
/* Do not modify this file ! */
/* Optional pixel format */
#define LCD_DBI_LCD_PIXEL_FORMAT_RGB565 1
#define LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888 2
typedef struct {
uint16_t pixel_format;
uint32_t clock_freq; /* No use */
} lcd_mipi_dbi_init_t;
int pec_dbi_b_init(lcd_mipi_dbi_init_t *dbi_parra);
int pec_dbi_b_transmit_cmd_para(uint8_t cmd, uint32_t *para, size_t para_num);
int pec_dbi_b_transmit_cmd_pixel_sync(uint8_t cmd, uint32_t *pixel, size_t pixel_num);
int pec_dbi_b_transmit_cmd_pixel_fill_sync(uint8_t cmd, uint32_t pixel_val, size_t pixel_num);
int pec_dbi_b_dma_is_busy(void);
int pec_dbi_b_async_callback_register(void (*callback)(void));
int pec_dbi_b_async_callback_enable(bool enable);
int pec_dbi_b_transmit_cmd_pixel_async(uint8_t cmd, uint32_t *pixel, size_t pixel_num);
int pec_dbi_b_transmit_cmd_pixel_fill_async(uint8_t cmd, uint32_t pixel_val, size_t pixel_num);
#endif
#endif

View file

@ -0,0 +1,340 @@
/**
* @file ili9341_dbi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "../lcd.h"
#include "ili9341_dbi.h"
#if defined(LCD_DBI_ILI9341)
#if (LCD_DBI_INTERFACE_TYPE == 1)
/* dbi */
#include "bl_mipi_dbi.h"
#define lcd_dbi_init lcd_dbi_init
#define lcd_dbi_isbusy lcd_dbi_is_busy
#define lcd_dbi_transmit_cmd_para lcd_dbi_transmit_cmd_para
#define lcd_dbi_transmit_cmd_pixel_sync lcd_dbi_transmit_cmd_pixel_sync
#define lcd_dbi_transmit_cmd_pixel_fill_sync lcd_dbi_transmit_cmd_pixel_fill_sync
#define lcd_dbi_sync_callback_enable lcd_dbi_async_callback_enable
#define lcd_dbi_async_callback_register lcd_dbi_async_callback_register
#define lcd_dbi_transmit_cmd_pixel_async lcd_dbi_transmit_cmd_pixel_async
#define lcd_dbi_transmit_cmd_pixel_fill_async lcd_dbi_transmit_cmd_pixel_fill_async
lcd_dbi_init_t dbi_para = {
.clock_freq = 40 * 1000 * 1000,
#if (ILI9341_DBI_PIXEL_FORMAT == 1)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_RGB565,
#elif (ILI9341_DBI_PIXEL_FORMAT == 2)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#elif (LCD_DBI_INTERFACE_TYPE == 2)
/* pec sumi dbi 8080 x8 */
#include "bl_mipi_dbi_typeb_pec.h"
#define lcd_dbi_init pec_dbi_b_init
#define lcd_dbi_isbusy pec_dbi_b_dma_is_busy
#define lcd_dbi_transmit_cmd_para pec_dbi_b_transmit_cmd_para
#define lcd_dbi_transmit_cmd_pixel_sync pec_dbi_b_transmit_cmd_pixel_sync
#define lcd_dbi_transmit_cmd_pixel_fill_sync pec_dbi_b_transmit_cmd_pixel_fill_sync
#define lcd_dbi_sync_callback_enable pec_dbi_b_async_callback_enable
#define lcd_dbi_async_callback_register pec_dbi_b_async_callback_register
#define lcd_dbi_transmit_cmd_pixel_async pec_dbi_b_transmit_cmd_pixel_async
#define lcd_dbi_transmit_cmd_pixel_fill_async pec_dbi_b_transmit_cmd_pixel_fill_async
lcd_mipi_dbi_init_t dbi_para = {
.clock_freq = 20 * 1000 * 1000,
#if (ILI9341_DBI_PIXEL_FORMAT == 1)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_RGB565,
#elif (ILI9341_DBI_PIXEL_FORMAT == 2)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#else
#error "Configuration error"
#endif
const ili9341_dbi_init_cmd_t ili9341_dbi_init_cmds[] = {
{ 0x01, NULL, 0 },
{ 0xFF, NULL, 20 },
{ 0x11, NULL, 0 }, /* Exit sleep */
{ 0xFF, NULL, 120 },
{ 0xCF, "\x00\xd9\x30", 3 },
{ 0xED, "\x64\x03\x12\x81", 4 },
{ 0xE8, "\x85\x01\x78", 3 },
{ 0xCB, "\x39\x2C\x00\x34\x02", 5 },
{ 0xF7, "\x20", 1 },
{ 0xEA, "\x00\x00", 2 },
{ 0xC0, "\x23", 1 }, /*Power control*/
{ 0xC1, "\x12", 1 }, /*Power control */
{ 0xC2, "\x11", 1 },
{ 0xC5, "\x40\x30", 2 }, /*VCOM control 1*/
{ 0xC7, "\xa9", 1 }, /*VCOM control 2*/
{ 0x36, "\x08", 1 }, /*Memory Access Control*/
#if (ILI9341_DBI_PIXEL_FORMAT == 1)
{ 0x3A, "\x55", 1 }, /* Interface Pixel Format RGB565 */
#elif (ILI9341_DBI_PIXEL_FORMAT == 2)
{ 0x3A, "\x66", 1 }, /* Interface Pixel Format RGB666 */
#endif
{ 0xB1, "\x00\x18", 2 }, /* Frame Rate Control */
{ 0xB6, "\x0a\xa2", 2 }, /* Display Function Control */
{ 0x0C, "\xd5", 1 }, /* display pixel format,RGB 16bits,MCU 16bits */
{ 0xF2, "\x00", 1 }, /* 3Gamma Function Disable */
{ 0xF7, "\x20", 1 },
{ 0x26, "\x01", 1 }, /* Gamma curve selected */
{ 0xE0, "\x1F\x1A\x18\x0A\x0F\x06\x45\x87\x32\x0A\x07\x02\x07\x05\x00", 15 }, /* Set Gamma */
{ 0XE1, "\x00\x25\x27\x05\x10\x09\x3A\x78\x4D\x05\x18\x0D\x38\x3A\x1F", 15 }, /* Set Gamma */
{ 0xB7, "\x07", 1 },
#if ILI9341_DBI_COLOR_REVERSAL
{ 0x21, NULL, 0 }, /* Color reversal */
#endif
{ 0x29, NULL, 0 }, /* Display On */
{ 0xFF, NULL, 10 },
};
/**
* @brief ili9341_dbi_async_callback_enable
*
* @return
*/
void ili9341_dbi_async_callback_enable(bool enable)
{
lcd_dbi_sync_callback_enable(enable);
}
/**
* @brief ili9341_dbi_async_callback_register
*
* @return
*/
void ili9341_dbi_async_callback_register(void (*callback)(void))
{
lcd_dbi_async_callback_register(callback);
}
/**
* @brief ili9341_dbi_draw_is_busy, After the call ili9341_dbi_draw_picture_dma must check this,
* if ili9341_dbi_draw_is_busy() == 1, Don't allow other draw !!
* can run in the DMA interrupt callback function.
*
* @return int 0:draw end; 1:Being draw
*/
int ili9341_dbi_draw_is_busy(void)
{
return lcd_dbi_isbusy();
}
/**
* @brief ili9341_dbi_init
*
* @return int
*/
int ili9341_dbi_init()
{
lcd_dbi_init(&dbi_para);
for (uint16_t i = 0; i < (sizeof(ili9341_dbi_init_cmds) / sizeof(ili9341_dbi_init_cmd_t)); i++) {
if (ili9341_dbi_init_cmds[i].cmd == 0xFF && ili9341_dbi_init_cmds[i].data == NULL && ili9341_dbi_init_cmds[i].databytes) {
bflb_mtimer_delay_ms(ili9341_dbi_init_cmds[i].databytes);
} else {
lcd_dbi_transmit_cmd_para(ili9341_dbi_init_cmds[i].cmd, (void *)(ili9341_dbi_init_cmds[i].data), ili9341_dbi_init_cmds[i].databytes);
}
}
return 0;
}
/**
* @brief
*
* @param dir
* @param mir_flag
*/
int ili9341_dbi_set_dir(uint8_t dir, uint8_t mir_flag)
{
uint8_t param;
switch (dir) {
case 0:
if (!mir_flag)
param = 0x00;
else
param = 0x01;
break;
case 1:
if (!mir_flag)
param = 0x60;
else
param = 0x20;
break;
case 2:
if (!mir_flag)
param = 0xC0;
else
param = 0x80;
break;
case 3:
if (!mir_flag)
param = 0xA0;
else
param = 0xE0;
break;
default:
return -1;
break;
}
lcd_dbi_transmit_cmd_para(0x36, (void *)&param, 1);
return dir;
}
/**
* @brief ili9341_dbi_set_draw_window
*
* @param x1
* @param y1
* @param x2
* @param y2
*/
void ili9341_dbi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
#if ILI9341_DBI_OFFSET_X
x1 += ILI9341_DBI_OFFSET_X;
x2 += ILI9341_DBI_OFFSET_X;
#endif
#if ILI9341_DBI_OFFSET_Y
y1 += ILI9341_DBI_OFFSET_Y;
y2 += ILI9341_DBI_OFFSET_Y;
#endif
uint8_t param[4];
param[0] = (y1 >> 8) & 0xFF;
param[1] = y1 & 0xFF;
param[2] = (y2 >> 8) & 0xFF;
param[3] = y2 & 0xFF;
lcd_dbi_transmit_cmd_para(0x2B, (void *)param, 4);
param[0] = (x1 >> 8) & 0xFF;
param[1] = x1 & 0xFF;
param[2] = (x2 >> 8) & 0xFF;
param[3] = x2 & 0xFF;
lcd_dbi_transmit_cmd_para(0x2A, (void *)param, 4);
}
/**
* @brief ili9341_dbi_draw_point
*
* @param x
* @param y
* @param color
*/
void ili9341_dbi_draw_point(uint16_t x, uint16_t y, ili9341_dbi_color_t color)
{
/* set window */
ili9341_dbi_set_draw_window(x, y, x, y);
lcd_dbi_transmit_cmd_pixel_sync(0x2C, (void *)&color, 1);
}
/**
* @brief ili9341_dbi_draw_area
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param color
*/
void ili9341_dbi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_dbi_color_t color)
{
uint32_t pixel_num = (x2 - x1 + 1) * (y2 - y1 + 1);
uint32_t color_src;
#if ILI9341_DBI_COLOR_DEPTH == 16
color_src = color << 16 | color;
#elif ILI9341_DBI_COLOR_DEPTH == 32
color_src = color;
#endif
/* set window */
ili9341_dbi_set_draw_window(x1, y1, x2, y2);
lcd_dbi_transmit_cmd_pixel_fill_sync(0x2C, color_src, pixel_num);
}
/**
* @brief ili9341_dbi_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
* After the call, No other operations are allowed until (ili9341_dbi_draw_is_busy()==0)
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void ili9341_dbi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_dbi_color_t *picture)
{
uint32_t pixel_num = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9341_dbi_set_draw_window(x1, y1, x2, y2);
lcd_dbi_transmit_cmd_pixel_async(0x2C, (void *)picture, pixel_num);
}
/**
* @brief ili9341_dbi_draw_picture,BlockingUsing DMA acceleration,Waiting for the draw end
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void ili9341_dbi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_dbi_color_t *picture)
{
uint32_t pixel_num = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9341_dbi_set_draw_window(x1, y1, x2, y2);
lcd_dbi_transmit_cmd_pixel_sync(0x2C, (void *)picture, pixel_num);
}
#endif

View file

@ -0,0 +1,59 @@
/**
* @file ili9341_dpi.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef _ILI9341_DBI_H_
#define _ILI9341_DBI_H_
#include "../lcd_conf.h"
#if defined LCD_DBI_ILI9341
/* Do not modify the following */
#if (ILI9341_DBI_PIXEL_FORMAT == 1)
#define ILI9341_DBI_COLOR_DEPTH 16
typedef uint16_t ili9341_dbi_color_t;
#elif (ILI9341_DBI_PIXEL_FORMAT == 2)
#define ILI9341_DBI_COLOR_DEPTH 32
typedef uint32_t ili9341_dbi_color_t;
#endif
typedef struct {
uint8_t cmd; /* 0xFF : delay(databytes)ms */
const char *data;
uint8_t databytes; /* Num of data in data; or delay time */
} ili9341_dbi_init_cmd_t;
int ili9341_dbi_init();
void ili9341_dbi_async_callback_enable(bool enable);
void ili9341_dbi_async_callback_register(void (*callback)(void));
int ili9341_dbi_set_dir(uint8_t dir, uint8_t mir_flag);
void ili9341_dbi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void ili9341_dbi_draw_point(uint16_t x, uint16_t y, ili9341_dbi_color_t color);
void ili9341_dbi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_dbi_color_t color);
void ili9341_dbi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_dbi_color_t *picture);
void ili9341_dbi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_dbi_color_t *picture);
int ili9341_dbi_draw_is_busy(void);
#endif
#endif

View file

@ -0,0 +1,333 @@
/**
* @file ili9488_dbi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "../lcd.h"
#include "ili9488_dbi.h"
#if defined(LCD_DBI_ILI9488)
#if (LCD_DBI_INTERFACE_TYPE == 1)
/* dbi */
#include "bl_mipi_dbi.h"
#define lcd_dbi_init lcd_dbi_init
#define lcd_dbi_isbusy lcd_dbi_is_busy
#define lcd_dbi_transmit_cmd_para lcd_dbi_transmit_cmd_para
#define lcd_dbi_transmit_cmd_pixel_sync lcd_dbi_transmit_cmd_pixel_sync
#define lcd_dbi_transmit_cmd_pixel_fill_sync lcd_dbi_transmit_cmd_pixel_fill_sync
#define lcd_dbi_sync_callback_enable lcd_dbi_async_callback_enable
#define lcd_dbi_async_callback_register lcd_dbi_async_callback_register
#define lcd_dbi_transmit_cmd_pixel_async lcd_dbi_transmit_cmd_pixel_async
#define lcd_dbi_transmit_cmd_pixel_fill_async lcd_dbi_transmit_cmd_pixel_fill_async
lcd_dbi_init_t dbi_para = {
.clock_freq = 40 * 1000 * 1000,
#if (ILI9488_DBI_PIXEL_FORMAT == 1)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_RGB565,
#elif (ILI9488_DBI_PIXEL_FORMAT == 2)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#elif (LCD_DBI_INTERFACE_TYPE == 2)
/* pec sumi dbi 8080 x8 */
#include "bl_mipi_dbi_typeb_pec.h"
#define lcd_dbi_init pec_dbi_b_init
#define lcd_dbi_isbusy pec_dbi_b_dma_is_busy
#define lcd_dbi_transmit_cmd_para pec_dbi_b_transmit_cmd_para
#define lcd_dbi_transmit_cmd_pixel_sync pec_dbi_b_transmit_cmd_pixel_sync
#define lcd_dbi_transmit_cmd_pixel_fill_sync pec_dbi_b_transmit_cmd_pixel_fill_sync
#define lcd_dbi_sync_callback_enable pec_dbi_b_async_callback_enable
#define lcd_dbi_async_callback_register pec_dbi_b_async_callback_register
#define lcd_dbi_transmit_cmd_pixel_async pec_dbi_b_transmit_cmd_pixel_async
#define lcd_dbi_transmit_cmd_pixel_fill_async pec_dbi_b_transmit_cmd_pixel_fill_async
lcd_mipi_dbi_init_t dbi_para = {
.clock_freq = 20 * 1000 * 1000,
#if (ILI9488_DBI_PIXEL_FORMAT == 1)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_RGB565,
#elif (ILI9488_DBI_PIXEL_FORMAT == 2)
.pixel_format = LCD_DBI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#else
#error "Configuration error"
#endif
const ili9488_dbi_init_cmd_t ili9488_dbi_init_cmds[] = {
{ 0x01, NULL, 0 }, /* software reset */
{ 0xFF, NULL, 10 }, /* delay 10ms */
{ 0x11, NULL, 0 }, /* Sleep Out */
{ 0xFF, NULL, 120 }, /* delay 120ms */
{ 0xE0, "\x00\x07\x0F\x0D\x1B\x0A\x3C\x78\x4A\x07\x0E\x09\x1B\x1E\x0F", 15 }, /* PGAMCTRL (Positive Gamma Control) */
{ 0xE1, "\x00\x22\x24\x26\x12\x07\x36\x47\x47\x06\x0A\x07\x30\x37\x0F", 15 }, /* NGAMCTRL (Negative Gamma Control) */
{ 0xC0, "\x10\x10", 2 }, /* Power Control 1 */
{ 0xC1, "\x41", 1 }, /* Power Control 2 */
{ 0xC5, "\x00\x2C\x80", 3 }, /* VCOM Control */
{ 0x36, "\x08", 1 }, /* Memory Access Control */
#if (ILI9488_DBI_PIXEL_FORMAT == 1)
{ 0x3A, "\x55", 1 }, /* Interface Pixel Format RGB565 */
#elif (ILI9488_DBI_PIXEL_FORMAT == 2)
{ 0x3A, "\x66", 1 }, /* Interface Pixel Format RGB666 */
#endif
{ 0xB0, "\x00", 1 }, /* Interface Mode Control */
{ 0xB1, "\xB0", 1 }, /* Frame rate 70Hz */
{ 0xB4, "\x02", 1 }, /* Display Inversion Control */
{ 0xB6, "\x02\x22", 2 }, /* Display Function Control */
{ 0xE9, "\x00", 1 }, /* Set Image Function */
{ 0xF7, "\xA9\x51\x2C\x82", 4 }, /* Adjust Control 3 */
#if ILI9488_DBI_COLOR_REVERSAL
{ 0x21, NULL, 0 }, /* Color reversal */
#endif
{ 0x29, NULL, 0 }, /* Display On */
{ 0xFF, NULL, 10 },
};
/**
* @brief ili9488_dbi_async_callback_enable
*
* @return
*/
void ili9488_dbi_async_callback_enable(bool enable)
{
lcd_dbi_sync_callback_enable(enable);
}
/**
* @brief ili9488_dbi_async_callback_register
*
* @return
*/
void ili9488_dbi_async_callback_register(void (*callback)(void))
{
lcd_dbi_async_callback_register(callback);
}
/**
* @brief ili9488_dbi_draw_is_busy, After the call ili9488_dbi_draw_picture_dma must check this,
* if ili9488_dbi_draw_is_busy() == 1, Don't allow other draw !!
* can run in the DMA interrupt callback function.
*
* @return int 0:draw end; 1:Being draw
*/
int ili9488_dbi_draw_is_busy(void)
{
return lcd_dbi_isbusy();
}
/**
* @brief ili9488_dbi_init
*
* @return int
*/
int ili9488_dbi_init()
{
lcd_dbi_init(&dbi_para);
for (uint16_t i = 0; i < (sizeof(ili9488_dbi_init_cmds) / sizeof(ili9488_dbi_init_cmd_t)); i++) {
if (ili9488_dbi_init_cmds[i].cmd == 0xFF && ili9488_dbi_init_cmds[i].data == NULL && ili9488_dbi_init_cmds[i].databytes) {
bflb_mtimer_delay_ms(ili9488_dbi_init_cmds[i].databytes);
} else {
lcd_dbi_transmit_cmd_para(ili9488_dbi_init_cmds[i].cmd, (void *)(ili9488_dbi_init_cmds[i].data), ili9488_dbi_init_cmds[i].databytes);
}
}
return 0;
}
/**
* @brief
*
* @param dir
* @param mir_flag
*/
int ili9488_dbi_set_dir(uint8_t dir, uint8_t mir_flag)
{
uint8_t param;
switch (dir) {
case 0:
if (!mir_flag)
param = 0x00;
else
param = 0x01;
break;
case 1:
if (!mir_flag)
param = 0x60;
else
param = 0x20;
break;
case 2:
if (!mir_flag)
param = 0xC0;
else
param = 0x80;
break;
case 3:
if (!mir_flag)
param = 0xA0;
else
param = 0xE0;
break;
default:
return -1;
break;
}
lcd_dbi_transmit_cmd_para(0x36, (void *)&param, 1);
return dir;
}
/**
* @brief ili9488_dbi_set_draw_window
*
* @param x1
* @param y1
* @param x2
* @param y2
*/
void ili9488_dbi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
#if ILI9488_DBI_OFFSET_X
x1 += ILI9488_DBI_OFFSET_X;
x2 += ILI9488_DBI_OFFSET_X;
#endif
#if ILI9488_DBI_OFFSET_Y
y1 += ILI9488_DBI_OFFSET_Y;
y2 += ILI9488_DBI_OFFSET_Y;
#endif
uint8_t param[4];
param[0] = (y1 >> 8) & 0xFF;
param[1] = y1 & 0xFF;
param[2] = (y2 >> 8) & 0xFF;
param[3] = y2 & 0xFF;
lcd_dbi_transmit_cmd_para(0x2B, (void *)param, 4);
param[0] = (x1 >> 8) & 0xFF;
param[1] = x1 & 0xFF;
param[2] = (x2 >> 8) & 0xFF;
param[3] = x2 & 0xFF;
lcd_dbi_transmit_cmd_para(0x2A, (void *)param, 4);
}
/**
* @brief ili9488_dbi_draw_point
*
* @param x
* @param y
* @param color
*/
void ili9488_dbi_draw_point(uint16_t x, uint16_t y, ili9488_dbi_color_t color)
{
/* set window */
ili9488_dbi_set_draw_window(x, y, x, y);
lcd_dbi_transmit_cmd_pixel_sync(0x2C, (void *)&color, 1);
}
/**
* @brief ili9488_dbi_draw_area
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param color
*/
void ili9488_dbi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_dbi_color_t color)
{
uint32_t pixel_num = (x2 - x1 + 1) * (y2 - y1 + 1);
uint32_t color_src;
#if ILI9488_DBI_COLOR_DEPTH == 16
color_src = color << 16 | color;
#elif ILI9488_DBI_COLOR_DEPTH == 32
color_src = color;
#endif
/* set window */
ili9488_dbi_set_draw_window(x1, y1, x2, y2);
lcd_dbi_transmit_cmd_pixel_fill_sync(0x2C, color_src, pixel_num);
}
/**
* @brief ili9488_dbi_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
* After the call, No other operations are allowed until (ili9488_dbi_draw_is_busy()==0)
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void ili9488_dbi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_dbi_color_t *picture)
{
uint32_t pixel_num = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9488_dbi_set_draw_window(x1, y1, x2, y2);
lcd_dbi_transmit_cmd_pixel_async(0x2C, (void *)picture, pixel_num);
}
/**
* @brief ili9488_dbi_draw_picture,BlockingUsing DMA acceleration,Waiting for the draw end
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void ili9488_dbi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_dbi_color_t *picture)
{
uint32_t pixel_num = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9488_dbi_set_draw_window(x1, y1, x2, y2);
lcd_dbi_transmit_cmd_pixel_sync(0x2C, (void *)picture, pixel_num);
}
#endif

View file

@ -0,0 +1,59 @@
/**
* @file ili9488_dpi.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef _ILI9488_DBI_H_
#define _ILI9488_DBI_H_
#include "../lcd_conf.h"
#if defined LCD_DBI_ILI9488
/* Do not modify the following */
#if (ILI9488_DBI_PIXEL_FORMAT == 1)
#define ILI9488_DBI_COLOR_DEPTH 16
typedef uint16_t ili9488_dbi_color_t;
#elif (ILI9488_DBI_PIXEL_FORMAT == 2)
#define ILI9488_DBI_COLOR_DEPTH 32
typedef uint32_t ili9488_dbi_color_t;
#endif
typedef struct {
uint8_t cmd; /* 0xFF : delay(databytes)ms */
const char *data;
uint8_t databytes; /* Num of data in data; or delay time */
} ili9488_dbi_init_cmd_t;
int ili9488_dbi_init();
void ili9488_dbi_async_callback_enable(bool enable);
void ili9488_dbi_async_callback_register(void (*callback)(void));
int ili9488_dbi_set_dir(uint8_t dir, uint8_t mir_flag);
void ili9488_dbi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void ili9488_dbi_draw_point(uint16_t x, uint16_t y, ili9488_dbi_color_t color);
void ili9488_dbi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_dbi_color_t color);
void ili9488_dbi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_dbi_color_t *picture);
void ili9488_dbi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_dbi_color_t *picture);
int ili9488_dbi_draw_is_busy(void);
#endif
#endif

View file

@ -0,0 +1,382 @@
/**
* @file bl_mipi_dpi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "../lcd.h"
#if (defined LCD_PEC_SIMU_DPI_ENABLE)
#if (defined(BL616) && __has_include("bflb_pec_ip.h"))
#include "bl_mipi_dpi_pec.h"
#include "bflb_pec_ip.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#include "bflb_dma.h"
#include "hardware/dma_reg.h"
/* Video memory used for this frame, Update in frame interrupt*/
static volatile void *screen_last = NULL;
typedef void (*standard_dpi_callback)(void);
static volatile standard_dpi_callback lcd_mipi_dpi_frame_callback = NULL;
static volatile standard_dpi_callback lcd_mipi_dpi_frame_swap_callback = NULL;
struct bflb_device_s *pec_dpi_dma_handle;
/* DMA linked list of PEC controls data */
static struct bflb_dma_channel_lli_pool_s dma_lli_dpi_header, dma_dpi_lli_tail;
/* DMA linked list of display buffer */
static struct bflb_dma_channel_lli_pool_s dma_lli_dpi_pool[LCD_DPI_PEC_DMA_LLI_CACHE_NUM][DPI_PEC_VALID_PIXEL_MAX / DMA_MAX_COUNT + 1];
/* Invalid row control parameter, Will be sent to PEC before and after the buffer */
static uint32_t pec_dpi_invalid_lin_para[(LCD_DPI_PEC_INVALID_LIN_MAX + 1) * 2];
/* dma lli cache table */
static volatile pec_dpi_dma_lli_cache_t dma_lli_cache_table[LCD_DPI_PEC_DMA_LLI_CACHE_NUM];
/* Total number of dma_transfer */
static volatile uint32_t pec_dpi_dma_lli_num;
/* next display buffer */
static volatile void *next_disp_buffer;
/* record pix_format, width, height */
static volatile uint16_t pix_format, width, height;
static int pec_dpi_dma_lli_init(lcd_mipi_dpi_init_t *dpi_para);
static int pec_dpi_dma_lli_update(void *disp_buff);
static void pec_dpi_dma_interrupt(void *arg);
int lcd_mipi_dpi_init(lcd_mipi_dpi_init_t *dpi_para)
{
if (dpi_para == NULL) {
return -1;
}
if (dpi_para->frame_buff == NULL) {
return -1;
}
/* pec gpio init */
struct bflb_device_s *gpio;
gpio = bflb_device_get_by_name("gpio");
/* clk pin */
bflb_gpio_init(gpio, LCD_DPI_PEC_SIMU_PIN_CLK, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
#if (LCD_PEC_DPI_DE_MODE)
/* de pin */
bflb_gpio_init(gpio, LCD_DPI_PEC_SIMU_PIN_CLK + 1, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
#endif
#if (LCD_PEC_DPI_DATA_LATCH_MODE)
/* latch pin */
bflb_gpio_init(gpio, LCD_DPI_PEC_SIMU_PIN_CLK + 2, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
#endif
/* hsync pin */
bflb_gpio_init(gpio, LCD_DPI_PEC_SIMU_PIN_HSYNC, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
/* vsync pin */
bflb_gpio_init(gpio, LCD_DPI_PEC_SIMU_PIN_HSYNC + 1, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
#if (LCD_PEC_DPI_DATA_LATCH_MODE)
/* data pin x8 */
for (uint8_t i = 0; i < 8; i++) {
bflb_gpio_init(gpio, LCD_DPI_PEC_SIMU_PIN_DATA_START + i, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
}
#else
/* data pin x16 */
for (uint8_t i = 0; i < 16; i++) {
bflb_gpio_init(gpio, LCD_DPI_PEC_SIMU_PIN_DATA_START + i, GPIO_FUNC_PEC | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_2);
}
#endif
/* pec init */
struct bflb_pec_dpi_s dpi_pec;
pix_format = dpi_para->pixel_format;
width = dpi_para->width;
height = dpi_para->height;
if (dpi_para->pixel_format == LCD_MIPI_DPI_PIXEL_FORMAT_RGB565) {
dpi_pec.data_format = 16;
} else if (dpi_para->pixel_format == LCD_MIPI_DPI_PIXEL_FORMAT_NRGB888) {
dpi_pec.data_format = 24;
} else {
return -2;
}
/* pec init */
dpi_pec.width = dpi_para->width;
dpi_pec.height = dpi_para->height;
dpi_pec.hsw = dpi_para->hsw;
dpi_pec.hbp = dpi_para->hbp;
dpi_pec.hfp = dpi_para->hfp;
dpi_pec.vsw = dpi_para->vsw;
dpi_pec.vbp = dpi_para->vbp;
dpi_pec.vfp = dpi_para->vfp;
dpi_pec.data_latch_mode = LCD_PEC_DPI_DATA_LATCH_MODE;
dpi_pec.de_sig_enable = LCD_PEC_DPI_DE_MODE;
dpi_pec.de_sig_polarity = LCD_PEC_DPI_DE_SIN_POL;
dpi_pec.v_sync_sig_polarity = LCD_PEC_DPI_V_SYNC_SIN_POL;
dpi_pec.h_sync_sig_polarity = LCD_PEC_DPI_H_SYNC_SIN_POL;
dpi_pec.invalid_row_para = pec_dpi_invalid_lin_para;
dpi_pec.frame_rate = dpi_para->frame_rate;
dpi_pec.pin_clk = LCD_DPI_PEC_SIMU_PIN_CLK;
dpi_pec.pin_hs = LCD_DPI_PEC_SIMU_PIN_HSYNC;
dpi_pec.pin_data = LCD_DPI_PEC_SIMU_PIN_DATA_START;
dpi_pec.pec = PEC_ID_USE;
dpi_pec.sm = SM_ID_USE;
bflb_pec_dpi_init(&dpi_pec);
/* dma lli init */
pec_dpi_dma_lli_init(dpi_para);
pec_dpi_dma_lli_update(dpi_para->frame_buff);
/* init DMA */
pec_dpi_dma_handle = bflb_device_get_by_name(LCD_PEC_DPI_DMA_NAME);
struct bflb_dma_channel_config_s tx_config = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_PEC_USE,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR4,
.dst_burst_count = DMA_BURST_INCR4,
.src_width = DMA_DATA_WIDTH_32BIT,
.dst_width = DMA_DATA_WIDTH_32BIT,
};
bflb_dma_channel_init(pec_dpi_dma_handle, &tx_config);
/* attach interrupt */
bflb_dma_channel_irq_attach(pec_dpi_dma_handle, pec_dpi_dma_interrupt, NULL);
/* update lli to register */
uint32_t channel_base = pec_dpi_dma_handle->reg_base;
putreg32(dma_lli_dpi_header.src_addr, channel_base + DMA_CxSRCADDR_OFFSET);
putreg32(dma_lli_dpi_header.dst_addr, channel_base + DMA_CxDSTADDR_OFFSET);
putreg32(dma_lli_dpi_header.nextlli, channel_base + DMA_CxLLI_OFFSET);
putreg32(dma_lli_dpi_header.control.WORD, channel_base + DMA_CxCONTROL_OFFSET);
/* start dma */
bflb_dma_channel_start(pec_dpi_dma_handle);
return 0;
}
int lcd_mipi_dpi_screen_switch(void *screen_buffer)
{
/* clean cache */
if (pix_format == LCD_MIPI_DPI_PIXEL_FORMAT_RGB565) {
bflb_l1c_dcache_clean_range((void *)(screen_buffer), width * height * 2);
} else if (pix_format == LCD_MIPI_DPI_PIXEL_FORMAT_NRGB888) {
bflb_l1c_dcache_clean_range((void *)(screen_buffer), width * height * 4);
}
next_disp_buffer = screen_buffer;
return 0;
}
void *lcd_mipi_dpi_get_screen_using(void)
{
return (void *)screen_last;
}
static void pec_dpi_dma_interrupt(void *arg)
{
uint8_t swap_flag = 0;
/* update dma for frame */
pec_dpi_dma_lli_update((void *)next_disp_buffer);
/* stop dma channel */
bflb_dma_channel_stop(pec_dpi_dma_handle);
/* update lli to register */
uint32_t channel_base = pec_dpi_dma_handle->reg_base;
putreg32(dma_lli_dpi_header.src_addr, channel_base + DMA_CxSRCADDR_OFFSET);
putreg32(dma_lli_dpi_header.dst_addr, channel_base + DMA_CxDSTADDR_OFFSET);
putreg32(dma_lli_dpi_header.nextlli, channel_base + DMA_CxLLI_OFFSET);
putreg32(dma_lli_dpi_header.control.WORD, channel_base + DMA_CxCONTROL_OFFSET);
/* start dma channel */
bflb_dma_channel_start(pec_dpi_dma_handle);
if (screen_last != next_disp_buffer) {
swap_flag = 1;
screen_last = next_disp_buffer;
}
if (lcd_mipi_dpi_frame_callback != NULL) {
lcd_mipi_dpi_frame_callback();
}
if (lcd_mipi_dpi_frame_swap_callback != 0 && swap_flag) {
lcd_mipi_dpi_frame_swap_callback();
}
}
int lcd_mipi_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void))
{
if (callback_type == LCD_MIPI_DPI_FRAME_INT_TYPE_SWAP) {
lcd_mipi_dpi_frame_swap_callback = callback;
} else if (callback_type == LCD_MIPI_DPI_FRAME_INT_TYPE_CYCLE) {
lcd_mipi_dpi_frame_callback = callback;
}
return 0;
}
static int pec_dpi_dma_lli_init(lcd_mipi_dpi_init_t *dpi_para)
{
uint16_t i, j;
uint32_t temp, dma_count;
/* get total number of dma_transfer */
if (dpi_para->pixel_format == LCD_MIPI_DPI_PIXEL_FORMAT_RGB565) {
dma_count = (dpi_para->width * dpi_para->height) * 2 / 4;
} else if (dpi_para->pixel_format == LCD_MIPI_DPI_PIXEL_FORMAT_NRGB888) {
dma_count = (dpi_para->width * dpi_para->height);
} else {
return -1;
}
if (dma_count == 0) {
return -1;
}
/* Initialize DMA and controls data lli */
dma_lli_dpi_header.control.bits.SBSize = DMA_BURST_INCR4;
dma_lli_dpi_header.control.bits.dst_min_mode = 0;
dma_lli_dpi_header.control.bits.DBSize = DMA_BURST_INCR4;
dma_lli_dpi_header.control.bits.dst_add_mode = 0;
dma_lli_dpi_header.control.bits.SWidth = DMA_DATA_WIDTH_32BIT;
dma_lli_dpi_header.control.bits.DWidth = DMA_DATA_WIDTH_32BIT;
dma_lli_dpi_header.control.bits.fix_cnt = 0;
dma_lli_dpi_header.control.bits.SI = DMA_ADDR_INCREMENT_ENABLE;
dma_lli_dpi_header.control.bits.DI = DMA_ADDR_INCREMENT_DISABLE;
dma_lli_dpi_header.control.bits.I = 0;
dma_lli_dpi_header.dst_addr = 0x2005A010; // PEC_BASE + PEC_TXF0_OFFSET + SM_ID_USE * 4;
dma_lli_dpi_header.src_addr = (uint32_t)(uintptr_t)pec_dpi_invalid_lin_para;
dma_lli_dpi_header.control.bits.TransferSize = (dpi_para->vsw + dpi_para->vbp) * 2 + 1;
dma_lli_dpi_header.nextlli = (uint32_t)(uintptr_t)NULL;
dma_dpi_lli_tail = dma_lli_dpi_header;
dma_dpi_lli_tail.control.bits.I = 1;
dma_dpi_lli_tail.src_addr = (uint32_t)(uintptr_t)&pec_dpi_invalid_lin_para[(dpi_para->vsw + dpi_para->vbp + 1) * 2];
dma_dpi_lli_tail.control.bits.TransferSize = dpi_para->vfp * 2;
bflb_l1c_dcache_clean_range(pec_dpi_invalid_lin_para, sizeof(pec_dpi_invalid_lin_para));
bflb_l1c_dcache_clean_range((void *)&dma_dpi_lli_tail, sizeof(dma_dpi_lli_tail));
/* Initialize display buffer data lli, but do not load data */
dma_lli_dpi_pool[0][0].control.bits.SBSize = DMA_BURST_INCR4;
dma_lli_dpi_pool[0][0].control.bits.dst_min_mode = 0;
dma_lli_dpi_pool[0][0].control.bits.DBSize = DMA_BURST_INCR4;
dma_lli_dpi_pool[0][0].control.bits.dst_add_mode = 0;
dma_lli_dpi_pool[0][0].control.bits.SWidth = DMA_DATA_WIDTH_32BIT;
dma_lli_dpi_pool[0][0].control.bits.DWidth = DMA_DATA_WIDTH_32BIT;
dma_lli_dpi_pool[0][0].control.bits.fix_cnt = 0;
dma_lli_dpi_pool[0][0].control.bits.SI = DMA_ADDR_INCREMENT_ENABLE;
dma_lli_dpi_pool[0][0].control.bits.DI = DMA_ADDR_INCREMENT_DISABLE;
dma_lli_dpi_pool[0][0].control.bits.I = 0;
dma_lli_dpi_pool[0][0].dst_addr = 0x2005A010; //PEC_BASE + PEC_TXF0_OFFSET + SM_ID_USE * 4;
dma_lli_dpi_pool[0][0].src_addr = (uint32_t)(uintptr_t)(NULL);
dma_lli_dpi_pool[0][0].control.bits.TransferSize = DMA_MAX_COUNT;
dma_lli_dpi_pool[0][0].nextlli = (uint32_t)(uintptr_t)NULL;
for (i = 0; i < LCD_DPI_PEC_DMA_LLI_CACHE_NUM; i++) {
temp = dma_count;
for (j = 0; temp > 0; j++) {
dma_lli_dpi_pool[i][j] = dma_lli_dpi_pool[0][0];
dma_lli_dpi_pool[i][j].nextlli = (uint32_t)(uintptr_t)(&dma_lli_dpi_pool[i][j + 1]);
temp = (temp > DMA_MAX_COUNT) ? (temp - DMA_MAX_COUNT) : (0);
}
dma_lli_dpi_pool[i][j - 1].nextlli = (uint32_t)(uintptr_t)(&dma_dpi_lli_tail);
dma_lli_dpi_pool[i][j - 1].control.bits.TransferSize = dma_count % DMA_MAX_COUNT;
bflb_l1c_dcache_clean_range((void *)dma_lli_dpi_pool[i], sizeof(struct bflb_dma_channel_lli_pool_s) * (j + 1));
}
pec_dpi_dma_lli_num = j;
for (i = 0; i < LCD_DPI_PEC_DMA_LLI_CACHE_NUM; i++) {
dma_lli_cache_table[i].disp_buff = NULL;
dma_lli_cache_table[i].dma_lli = dma_lli_dpi_pool[i];
dma_lli_cache_table[i].lru_value = LCD_DPI_PEC_DMA_LLI_CACHE_NUM;
}
return 0;
}
static int pec_dpi_dma_lli_update(void *disp_buff)
{
uint16_t idx, idx_oldest = 0, lru_v = 0;
/* Looking for the cache table */
for (idx = 0; idx < LCD_DPI_PEC_DMA_LLI_CACHE_NUM; idx++) {
if (dma_lli_cache_table[idx].disp_buff == disp_buff) {
lru_v = dma_lli_cache_table[idx].lru_value;
break;
} else if (dma_lli_cache_table[idx].lru_value > lru_v) {
lru_v = dma_lli_cache_table[idx].lru_value;
idx_oldest = idx;
}
}
/* Not cached, Add to the cache table */
if (idx >= LCD_DPI_PEC_DMA_LLI_CACHE_NUM) {
idx = idx_oldest;
/* update dma lli */
struct bflb_dma_channel_lli_pool_s *lli_p = dma_lli_cache_table[idx].dma_lli;
for (uint16_t i = 0; i < pec_dpi_dma_lli_num; i++) {
lli_p[i].src_addr = (uint32_t)(uintptr_t)(disp_buff) + (i * DMA_MAX_COUNT * 4);
}
bflb_l1c_dcache_clean_range((void *)lli_p, sizeof(struct bflb_dma_channel_lli_pool_s) * pec_dpi_dma_lli_num);
dma_lli_cache_table[idx].disp_buff = disp_buff;
}
dma_lli_dpi_header.nextlli = (uint32_t)(uintptr_t)(dma_lli_cache_table[idx].dma_lli);
/* update cache table lru_value */
dma_lli_cache_table[idx].lru_value = 0;
for (idx = 0; idx < LCD_DPI_PEC_DMA_LLI_CACHE_NUM; idx++) {
if (dma_lli_cache_table[idx].lru_value < lru_v) {
dma_lli_cache_table[idx].lru_value++;
}
}
return 0;
}
#else
#error "Devices that do not support PEC-DPI! Replace the driver port (lcd_conf.h)"
#endif
#endif

View file

@ -0,0 +1,89 @@
/**
* @file bl_mipi_dpi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef _BL_MIPI_DPI_H_
#define _BL_MIPI_DPI_H_
#include "../lcd_conf.h"
#if defined LCD_PEC_SIMU_DPI_ENABLE
/* Do not modify this file ! */
#define LCD_MIPI_DPI_PIXEL_FORMAT_RGB565 0
#define LCD_MIPI_DPI_PIXEL_FORMAT_NRGB888 1
#define LCD_MIPI_DPI_FRAME_INT_TYPE_CYCLE 0
#define LCD_MIPI_DPI_FRAME_INT_TYPE_SWAP 1
typedef struct {
uint16_t width; /* LCD Active Width */
uint16_t height; /* LCD Active Height */
/* Total Width = HSW + HBP + Active_Width + HFP */
uint16_t hsw; /* LCD HSW (Hsync Pulse Width) */
uint16_t hbp; /* LCD HBP (Hsync Back Porch) */
uint16_t hfp; /* LCD HFP (Hsync Front Porch) */
/* Total Height = VSW + VBP + Active_Height + VFP */
uint16_t vsw; /* LCD VSW (Vsync Pulse Width) */
uint16_t vbp; /* LCD VBP (Vsync Back Porch) */
uint16_t vfp; /* LCD VFP (Vsync Front Porch) */
uint16_t frame_rate; /* Maximum refresh frame rate per second, Used to automatically calculate the clock frequency */
uint16_t pixel_format;
void *frame_buff; /* The frame buffer */
} lcd_mipi_dpi_init_t;
typedef struct {
void *disp_buff;
void *dma_lli;
uint16_t lru_value;
} pec_dpi_dma_lli_cache_t;
/* PEC select */
#define PEC_ID_USE PEC0
#define SM_ID_USE PEC_SM0
/* DMA select */
#define DMA_MAX_COUNT 4032
#define DMA_REQUEST_PEC_USE DMA_REQUEST_PEC0_SM0_TX
#if ((defined ILI9488_DPI_MODE) && (ILI9488_DPI_MODE == 2))
#define DPI_PEC_VALID_PIXEL_MAX (ILI9488_DPI_W * ILI9488_DPI_H)
#elif ((defined GC9503V_DPI_MODE) && (GC9503V_DPI_MODE == 2))
#define DPI_PEC_VALID_PIXEL_MAX (GC9503V_DPI_W * GC9503V_DPI_H)
#elif ((defined STANDARD_DPI_MODE) && (STANDARD_DPI_MODE == 2))
#define DPI_PEC_VALID_PIXEL_MAX (STANDARD_DPI_W * STANDARD_DPI_W)
#else
/* Maximum number of DPI valid pixels, >= (Width * Height) */
#define DPI_PEC_VALID_PIXEL_MAX (800 * 480)
#endif
int lcd_mipi_dpi_init(lcd_mipi_dpi_init_t *dpi_para);
int lcd_mipi_dpi_screen_switch(void *screen_buffer);
void *lcd_mipi_dpi_get_screen_using(void);
int lcd_mipi_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void));
#endif
#endif

View file

@ -0,0 +1,223 @@
/**
* @file gc9503v_dpi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "../lcd.h"
#if defined(LCD_DPI_GC9503V)
#include "gc9503v_dpi.h"
#include "bl_mipi_dpi_pec.h"
#include "bflb_mtimer.h"
#include "bflb_gpio.h"
/* mipi dpi (RGB) paramant */
static lcd_mipi_dpi_init_t dpi_para = {
.width = GC9503V_DPI_W, /* LCD Active Width */
.height = GC9503V_DPI_H, /* LCD Active Height */
/* Total Width = HSW + HBP + Active_Width + HFP */
.hsw = 10, /* LCD HSW (Hsync Pulse Width) */
.hbp = 10, /* LCD HBP (Hsync Back Porch) */
.hfp = 10, /* LCD HFP (Hsync Front Porch) */
/* Total Height = VSW + VBP + Active_Height + VFP */
.vsw = 3, /* LCD VSW (Vsync Pulse Width) */
.vbp = 12, /* LCD VBP (Vsync Back Porch) */
.vfp = 14, /* LCD VFP (Vsync Front Porch) */
.frame_rate = 60, /* Maximum refresh frame rate per second, Used to automatically calculate the clock frequency */
#if (GC9503V_DPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_MIPI_DPI_PIXEL_FORMAT_RGB565,
#endif
.frame_buff = NULL,
};
#if (GC9503V_DPI_INIT_INTERFACE == 1)
static struct bflb_device_s *gc9503v_gpio;
/* gpio spi init */
static void gc9503v_soft_spi_init(void)
{
/* gpio24 spi clk init */
/* gpio25 spi mosi init */
/* gpio12 spi cs init */
gc9503v_gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gc9503v_gpio, GC9503V_DPI_SPI_CS_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
bflb_gpio_init(gc9503v_gpio, GC9503V_DPI_SPI_CLK_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
bflb_gpio_init(gc9503v_gpio, GC9503V_DPI_SPI_DAT_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
GC9503V_SPI_CS_HIGH;
GC9503V_SPI_CLK_HIGH;
GC9503V_SPI_MOSI_HIGH;
}
/* gpio spi send byte */
static ATTR_TCM_SECTION void spi_send_byte(uint8_t data)
{
for (uint32_t i = 0; i < 8; i++) {
GC9503V_SPI_CLK_LOW;
if (data & 0x80) {
GC9503V_SPI_MOSI_HIGH;
} else {
GC9503V_SPI_MOSI_LOW;
}
GC9503V_SPI_CLK_HIGH;
data <<= 1;
DUMMY_DELAY;
}
}
/* spi write cmd */
static ATTR_TCM_SECTION int gc9503v_spi_write_cmd(uint8_t cmd)
{
GC9503V_SPI_CLK_LOW;
GC9503V_SPI_CS_LOW;
GC9503V_SPI_MOSI_LOW;
GC9503V_SPI_CLK_HIGH;
spi_send_byte(cmd);
GC9503V_SPI_CLK_LOW;
GC9503V_SPI_CS_HIGH;
GC9503V_SPI_MOSI_HIGH;
return 0;
}
/* spi write data */
static ATTR_TCM_SECTION int gc9503v_spi_write_data_byte(uint8_t data)
{
GC9503V_SPI_CLK_LOW;
GC9503V_SPI_CS_LOW;
GC9503V_SPI_MOSI_HIGH;
GC9503V_SPI_CLK_HIGH;
spi_send_byte(data);
GC9503V_SPI_CLK_LOW;
GC9503V_SPI_CS_HIGH;
GC9503V_SPI_MOSI_HIGH;
return 0;
}
#endif
static const gc9503v_dpi_init_cmd_t gc9503v_dpi_mode_init_cmds[] = {
{ 0x10, NULL, 0 }, /* enter sleep mode */
{ 0xF0, "\x55\xAA\x52\x08\x00", 5 },
{ 0xF6, "\x5A\x87", 2 },
{ 0xC1, "\x3F", 1 },
{ 0xC2, "\x0E", 1 },
{ 0xC6, "\xF8", 1 },
{ 0xC9, "\x10", 1 },
{ 0xCD, "\x25", 1 },
{ 0xF8, "\x8A", 1 },
{ 0xAC, "\x45", 1 },
{ 0xA0, "\xDD", 1 },
{ 0xA7, "\x47", 1 },
{ 0xFA, "\x00\x00\x00\x04", 4 },
{ 0xA3, "\xEE", 1 },
{ 0xFD, "\x28\x28\x00", 3 },
{ 0x71, "\x48", 1 },
{ 0x72, "\x48", 1 },
{ 0x73, "\x00\x44", 2 },
{ 0x97, "\xEE", 1 },
{ 0x83, "\x93", 1 },
{ 0x9A, "\x72", 1 },
{ 0x9B, "\x5A", 1 },
{ 0x82, "\x2C\x2C", 2 },
{ 0xB1, "\x10", 1 },
{ 0x6D, "\x00\x1F\x19\x1A\x10\x0E\x0C\x0A\x02\x07\x1E\x1E\x1E\x1E\x1E\x1E\x1E\x1E\x1E\x1E\x1E\x1E\x08\x01\x09\x0B\x0D\x0F\x1A\x19\x1F\x00", 32 },
{ 0x64, "\x38\x05\x01\xDB\x03\x03\x38\x04\x01\xDC\x03\x03\x7A\x7A\x7A\x7A", 16 },
{ 0x65, "\x38\x03\x01\xDD\x03\x03\x38\x02\x01\xDE\x03\x03\x7A\x7A\x7A\x7A", 16 },
{ 0x66, "\x38\x01\x01\xDF\x03\x03\x38\x00\x01\xE0\x03\x03\x7A\x7A\x7A\x7A", 16 },
{ 0x67, "\x30\x01\x01\xE1\x03\x03\x30\x02\x01\xE2\x03\x03\x7A\x7A\x7A\x7A", 16 },
{ 0x68, "\x00\x08\x15\x08\x15\x7A\x7A\x08\x15\x08\x15\x7A\x7A", 13 },
{ 0x60, "\x38\x08\x7A\x7A\x38\x09\x7A\x7A", 8 },
{ 0x63, "\x31\xE4\x7A\x7A\x31\xE5\x7A\x7A", 8 },
{ 0x6B, "\x07", 1 },
{ 0x7A, "\x08\x13", 2 },
{ 0x7B, "\x08\x13", 2 },
{ 0xD1, "\x00\x00\x00\x04\x00\x12\x00\x18\x00\x21\x00\x2A\x00\x35\x00\x47\x00\x56\x00\x90\x00\xE5\x01\x68\x01\xD5\x01\xD7\x02\x36\x02\xA6\x02\xEE\x03\x48\x03\xA0\x03\xBA\x03\xC5\x03\xD0\x03\xE0\x03\xEA\x03\xFA\x03\xFF", 52 },
{ 0xD2, "\x00\x00\x00\x04\x00\x12\x00\x18\x00\x21\x00\x2A\x00\x35\x00\x47\x00\x56\x00\x90\x00\xE5\x01\x68\x01\xD5\x01\xD7\x02\x36\x02\xA6\x02\xEE\x03\x48\x03\xA0\x03\xBA\x03\xC5\x03\xD0\x03\xE0\x03\xEA\x03\xFA\x03\xFF", 52 },
{ 0xD3, "\x00\x00\x00\x04\x00\x12\x00\x18\x00\x21\x00\x2A\x00\x35\x00\x47\x00\x56\x00\x90\x00\xE5\x01\x68\x01\xD5\x01\xD7\x02\x36\x02\xA6\x02\xEE\x03\x48\x03\xA0\x03\xBA\x03\xC5\x03\xD0\x03\xE0\x03\xEA\x03\xFA\x03\xFF", 52 },
{ 0xD4, "\x00\x00\x00\x04\x00\x12\x00\x18\x00\x21\x00\x2A\x00\x35\x00\x47\x00\x56\x00\x90\x00\xE5\x01\x68\x01\xD5\x01\xD7\x02\x36\x02\xA6\x02\xEE\x03\x48\x03\xA0\x03\xBA\x03\xC5\x03\xD0\x03\xE0\x03\xEA\x03\xFA\x03\xFF", 52 },
{ 0xD5, "\x00\x00\x00\x04\x00\x12\x00\x18\x00\x21\x00\x2A\x00\x35\x00\x47\x00\x56\x00\x90\x00\xE5\x01\x68\x01\xD5\x01\xD7\x02\x36\x02\xA6\x02\xEE\x03\x48\x03\xA0\x03\xBA\x03\xC5\x03\xD0\x03\xE0\x03\xEA\x03\xFA\x03\xFF", 52 },
{ 0xD6, "\x00\x00\x00\x04\x00\x12\x00\x18\x00\x21\x00\x2A\x00\x35\x00\x47\x00\x56\x00\x90\x00\xE5\x01\x68\x01\xD5\x01\xD7\x02\x36\x02\xA6\x02\xEE\x03\x48\x03\xA0\x03\xBA\x03\xC5\x03\xD0\x03\xE0\x03\xEA\x03\xFA\x03\xFF", 52 },
{ 0x3A, "\x66", 1 }, /* pixel format set 16bits:0x55;18bits:0x66 */
{ 0x11, NULL, 0 }, /* sleep out */
{ 0xFF, NULL, 200 }, /* delay 200ms */
{ 0x29, NULL, 0 }, /* display on */
{ 0xFF, NULL, 30 }, /* delay 30ms */
};
int ATTR_TCM_SECTION gc9503v_dpi_init(gc9503v_dpi_color_t *screen_buffer)
{
#if (GC9503V_DPI_INIT_INTERFACE == 1)
/* spi init */
gc9503v_soft_spi_init();
for (uint16_t i = 0; i < (sizeof(gc9503v_dpi_mode_init_cmds) / sizeof(gc9503v_dpi_init_cmd_t)); i++) {
if ((gc9503v_dpi_mode_init_cmds[i].cmd == 0xFF) && (gc9503v_dpi_mode_init_cmds[i].data == NULL) && (gc9503v_dpi_mode_init_cmds[i].databytes)) {
bflb_mtimer_delay_ms(gc9503v_dpi_mode_init_cmds[i].databytes);
} else {
/* send register address */
gc9503v_spi_write_cmd(gc9503v_dpi_mode_init_cmds[i].cmd);
bflb_mtimer_delay_us(22);
/* send register data */
for (uint8_t j = 0; j < (gc9503v_dpi_mode_init_cmds[i].databytes); j++) {
gc9503v_spi_write_data_byte(gc9503v_dpi_mode_init_cmds[i].data[j]);
bflb_mtimer_delay_us(22);
}
}
}
#endif
/* mipi dpi init */
if (screen_buffer == NULL) {
return -1;
}
dpi_para.frame_buff = (void *)screen_buffer;
return lcd_mipi_dpi_init(&dpi_para);
}
int gc9503v_dpi_screen_switch(gc9503v_dpi_color_t *screen_buffer)
{
return lcd_mipi_dpi_screen_switch((void *)screen_buffer);
}
gc9503v_dpi_color_t *gc9503v_dpi_get_screen_using(void)
{
return (gc9503v_dpi_color_t *)lcd_mipi_dpi_get_screen_using();
}
int gc9503v_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void))
{
if (callback_type == FRAME_INT_TYPE_CYCLE) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_CYCLE, callback);
} else if (callback_type == FRAME_INT_TYPE_SWAP) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_SWAP, callback);
}
return 0;
}
#endif

View file

@ -0,0 +1,86 @@
/**
* @file gc9503v_dpi.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef _GC9503V_DPI_H_
#define _GC9503V_DPI_H_
#include "../lcd_conf.h"
/* Do not modify the following information */
#if defined LCD_DPI_GC9503V
#if (GC9503V_DPI_INIT_INTERFACE == 1)
/* Software spi 9-bit mode PIN */
#define GC9503V_SPI_CS_HIGH bflb_gpio_set(gc9503v_gpio, GC9503V_DPI_SPI_CS_PIN)
#define GC9503V_SPI_CS_LOW bflb_gpio_reset(gc9503v_gpio, GC9503V_DPI_SPI_CS_PIN)
#define GC9503V_SPI_CLK_HIGH bflb_gpio_set(gc9503v_gpio, GC9503V_DPI_SPI_CLK_PIN)
#define GC9503V_SPI_CLK_LOW bflb_gpio_reset(gc9503v_gpio, GC9503V_DPI_SPI_CLK_PIN)
#define GC9503V_SPI_MOSI_HIGH bflb_gpio_set(gc9503v_gpio, GC9503V_DPI_SPI_DAT_PIN)
#define GC9503V_SPI_MOSI_LOW bflb_gpio_reset(gc9503v_gpio, GC9503V_DPI_SPI_DAT_PIN)
#define DUMMY_DELAY \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop"); \
asm volatile("nop");
#endif
#if (GC9503V_DPI_PIXEL_FORMAT == 1)
#define GC9503V_DPI_COLOR_DEPTH 16
typedef uint16_t gc9503v_dpi_color_t;
#elif (GC9503V_DPI_PIXEL_FORMAT == 2)
#define GC9503V_DPI_COLOR_DEPTH 32
typedef uint32_t gc9503v_dpi_color_t;
#else
#error "GC9503V pixel format select error"
#endif
/* Gc9503v needs to be initialized using the DBI(typeC) or SPI interface */
typedef struct {
uint8_t cmd; /* 0xFF : delay(databytes)ms */
const char *data;
uint8_t databytes; /* Num of data in data; or delay time */
} gc9503v_dpi_init_cmd_t;
int gc9503v_dpi_init(gc9503v_dpi_color_t *screen_buffer);
int gc9503v_dpi_screen_switch(gc9503v_dpi_color_t *screen_buffer);
gc9503v_dpi_color_t *gc9503v_dpi_get_screen_using(void);
int gc9503v_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void));
#endif
#endif

View file

@ -0,0 +1,240 @@
/**
* @file ili9488_dpi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "../lcd.h"
#if defined(LCD_DPI_ILI9488)
#include "bflb_mtimer.h"
#include "bflb_gpio.h"
#include "ili9488_dpi.h"
#include "bl_mipi_dpi_pec.h"
#if (ILI9488_DPI_INIT_INTERFACE == 2)
#if defined(BL808)
#include "bl808_dbi.h"
#elif defined(BL616)
#include "bl616_dbi.h"
#endif
#elif (ILI9488_DPI_INIT_INTERFACE == 1)
#include "bflb_spi.h"
// #define ILI9488_SPI_INDEX SPI0_INDEX
#define ILI9488_SPI_ID 0
#define ILI9488_SPI_NAME "spi0"
#endif
/* mipi dpi (RGB) paramant */
static lcd_mipi_dpi_init_t dpi_para = {
.width = ILI9488_DPI_W, /* LCD Active Width */
.height = ILI9488_DPI_H, /* LCD Active Height */
/* Total Width = HSW + HBP + Active_Width + HFP */
.hsw = 4, /* LCD HSW (Hsync Pulse Width) */
.hbp = 4, /* LCD HBP (Hsync Back Porch) */
.hfp = 12, /* LCD HFP (Hsync Front Porch) */
/* Total Height = VSW + VBP + Active_Height + VFP */
.vsw = 6, /* LCD VSW (Vsync Pulse Width) */
.vbp = 6, /* LCD VBP (Vsync Back Porch) */
.vfp = 18, /* LCD VFP (Vsync Front Porch) */
.frame_rate = 60, /* Maximum refresh frame rate per second, Used to automatically calculate the clock frequency */
#if (ILI9488_DPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_MIPI_DPI_PIXEL_FORMAT_RGB565,
#endif
.frame_buff = NULL,
};
#if (ILI9488_DPI_INIT_INTERFACE == 2)
/* dbi config */
static DBI_CFG_Type dbiCfg = {
.mode = DBI_TYPE_C_4_WIRE, /* DBI type B or C select */
.pixelFormat = DBI_PIXEL_RGB888, /* DBI pixel format */
.fifoFormat = DBI_FIFO_888_NBGR, /* DBI fifo format */
.continueEn = ENABLE, /* Enable:CS will stay asserted between each consecutive pixel, disable:CS will de-assert between each pixel */
.dummyEn = DISABLE, /* Enable:dummy cycle will be inserted between command phase adn data phase, disable:no dummy cycle */
.dummyCnt = 0, /* Dummy cycle count,effective only in type C(fixed to 1 in type B) */
.clkPhase = DBI_SCL_CLK_PHASE_0, /* DBI clock phase */
.clkPolarity = DBI_SCL_CLK_POLARITY_LOW, /* DBI clock polarity */
.period.startLen = 9,
.period.dataPhase0Len = 9,
.period.dataPhase1Len = 9,
.period.intervalLen = 9
};
#elif (ILI9488_DPI_INIT_INTERFACE == 1)
static struct bflb_device_s *ili9488_gpio;
static struct bflb_device_s *ili9488_spi;
/* spi write cmd */
static int ili9488_spi_write_cmd(uint8_t cmd)
{
ILI9488_SPI_DC_LOW;
ILI9488_SPI_CS_LOW;
bflb_spi_poll_send(ili9488_spi, cmd);
ILI9488_SPI_CS_HIGH;
ILI9488_SPI_DC_HIGH;
return 0;
}
/* spi write data */
static int ili9488_spi_write_data_byte(uint8_t data)
{
ILI9488_SPI_CS_LOW;
bflb_spi_poll_send(ili9488_spi, data);
ILI9488_SPI_CS_HIGH;
return 0;
}
#endif
static const ili9488_dpi_init_cmd_t ili9488_dpi_mode_init_cmds[] = {
{ 0x01, NULL, 0 }, /* software reset */
{ 0xFF, NULL, 10 }, /* delay 10ms */
{ 0x11, NULL, 0 }, /* Sleep Out */
{ 0xFF, NULL, 120 }, /* delay 120ms */
{ 0xE0, "\x00\x07\x0F\x0D\x1B\x0A\x3C\x78\x4A\x07\x0E\x09\x1B\x1E\x0F", 15 }, /* PGAMCTRL (Positive Gamma Control) */
{ 0xE1, "\x00\x22\x24\x26\x12\x07\x36\x47\x47\x06\x0A\x07\x30\x37\x0F", 15 }, /* NGAMCTRL (Negative Gamma Control) */
{ 0xC0, "\x10\x10", 2 }, /* Power Control 1 */
{ 0xC1, "\x41", 1 }, /* Power Control 2 */
{ 0xC5, "\x00\x20\xd0", 3 }, /* VCOM Control */
{ 0x36, "\x08", 1 }, /* Memory Access Control */
{ 0x3A, "\x50", 1 }, /* Interface Pixel 16bits/pixel*/
{ 0xB0, "\x00", 1 }, /* Interface Mode Control */
{ 0xB1, "\xB0", 1 }, /* Frame rate 70Hz */
{ 0xB4, "\x02", 1 }, /* Display Inversion Control */
// { 0xB5, "\x08\x08\x06\x12", 4},/* Display Inversion Control */
{ 0xB6, "\x30\x22\x3B", 3 }, /* Display Function Control, DE Mode */
{ 0xBE, "\x00\x04", 1 },
{ 0xE9, "\x00", 1 }, /* Set Image Function */
{ 0xF7, "\xA9\x51\x2C\x82", 4 }, /* Adjust Control 3 */
{ 0x29, NULL, 0 }, /* Display On */
{ 0xFF, NULL, 10 },
};
int ili9488_dpi_init(ili9488_dpi_color_t *screen_buffer)
{
/* Ili9488 needs to be initialized using the DBI(typeC) or SPI interface */
#if (ILI9488_DPI_INIT_INTERFACE == 2)
DBI_Init(&dbiCfg);
for (uint16_t i = 0; i < (sizeof(ili9488_dpi_mode_init_cmds) / sizeof(ili9488_dpi_init_cmd_t)); i++) {
if (ili9488_dpi_mode_init_cmds[i].cmd == 0xFF) {
bflb_mtimer_delay_ms(ili9488_dpi_mode_init_cmds[i].databytes);
} else {
DBI_SetPhaseState(ENABLE, DISABLE);
DBI_SendCmdWithNormalData(ili9488_dpi_mode_init_cmds[i].cmd, 0, NULL);
DBI_SetPhaseState(DISABLE, ENABLE);
for (uint8_t j = 0; j < ili9488_dpi_mode_init_cmds[i].databytes; j++) {
DBI_SendCmdWithNormalData(0xFF, 1, (uint8_t *)&ili9488_dpi_mode_init_cmds[i].data[j]);
}
}
}
DBI_SetPhaseState(DISABLE, DISABLE);
#elif (ILI9488_DPI_INIT_INTERFACE == 1)
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = 8 * 1000 * 1000,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* CS and DC pin init */
ili9488_gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(ili9488_gpio, ILI9488_DPI_SPI_CS_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(ili9488_gpio, ILI9488_DPI_SPI_DC_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
ILI9488_SPI_CS_HIGH;
ILI9488_SPI_DC_HIGH;
/* spi init */
ili9488_spi = bflb_device_get_by_name(ILI9488_SPI_NAME);
bflb_spi_init(ili9488_spi, &spi_cfg);
for (uint16_t i = 0; i < (sizeof(ili9488_dpi_mode_init_cmds) / sizeof(ili9488_dpi_init_cmd_t)); i++) {
if ((ili9488_dpi_mode_init_cmds[i].cmd == 0xFF) && (ili9488_dpi_mode_init_cmds[i].data == NULL) && (ili9488_dpi_mode_init_cmds[i].databytes)) {
bflb_mtimer_delay_ms(ili9488_dpi_mode_init_cmds[i].databytes);
} else {
/* send register address */
ili9488_spi_write_cmd(ili9488_dpi_mode_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (ili9488_dpi_mode_init_cmds[i].databytes & 0x7F); j++) {
ili9488_spi_write_data_byte(ili9488_dpi_mode_init_cmds[i].data[j]);
}
}
}
#endif
if (screen_buffer == NULL) {
return -1;
}
/* mipi dpi init */
dpi_para.frame_buff = (void *)screen_buffer;
return lcd_mipi_dpi_init(&dpi_para);
}
int ili9488_dpi_screen_switch(ili9488_dpi_color_t *screen_buffer)
{
return lcd_mipi_dpi_screen_switch((void *)screen_buffer);
}
ili9488_dpi_color_t *ili9488_dpi_get_screen_using(void)
{
return (ili9488_dpi_color_t *)lcd_mipi_dpi_get_screen_using();
}
int ili9488_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void))
{
if (callback_type == FRAME_INT_TYPE_CYCLE) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_CYCLE, callback);
} else if (callback_type == FRAME_INT_TYPE_SWAP) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_SWAP, callback);
}
return 0;
}
#endif

View file

@ -0,0 +1,66 @@
/**
* @file ili9488_dpi.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef _ILI9488_DPI_H_
#define _ILI9488_DPI_H_
#include "../lcd_conf.h"
/* Do not modify the following information */
#if defined LCD_DPI_ILI9488
/* Select SPI Initialize interface pin */
#if ILI9488_DPI_INIT_INTERFACE == 1
#define ILI9488_SPI_CS_HIGH bflb_gpio_set(ili9488_gpio, ILI9488_DPI_SPI_CS_PIN)
#define ILI9488_SPI_CS_LOW bflb_gpio_reset(ili9488_gpio, ILI9488_DPI_SPI_CS_PIN)
#define ILI9488_SPI_DC_HIGH bflb_gpio_set(ili9488_gpio, ILI9488_DPI_SPI_DC_PIN)
#define ILI9488_SPI_DC_LOW bflb_gpio_reset(ili9488_gpio, ILI9488_DPI_SPI_DC_PIN)
#endif
#if (ILI9488_DPI_PIXEL_FORMAT == 1)
#define ILI9488_DPI_COLOR_DEPTH 16
typedef uint16_t ili9488_dpi_color_t;
#elif (ILI9488_DPI_PIXEL_FORMAT == 2)
#define ILI9488_DPI_COLOR_DEPTH 32
typedef uint32_t ili9488_dpi_color_t;
#else
#error "ILI9488 pixel format select error"
#endif
/* Ili9488 needs to be initialized using the DBI(typeC) or SPI interface */
typedef struct {
uint8_t cmd; /* 0xFF : delay(databytes)ms */
const char *data;
uint8_t databytes; /* Num of data in data; or delay time */
} ili9488_dpi_init_cmd_t;
int ili9488_dpi_init(ili9488_dpi_color_t *screen_buffer);
int ili9488_dpi_screen_switch(ili9488_dpi_color_t *screen_buffer);
ili9488_dpi_color_t *ili9488_dpi_get_screen_using(void);
int ili9488_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void));
#endif
#endif

View file

@ -0,0 +1,85 @@
/**
* @file standard_dpi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "../lcd.h"
#if defined(LCD_DPI_STANDARD)
#include "standard_dpi.h"
#include "bl_mipi_dpi_pec.h"
/* mipi dpi (RGB) paramant */
static lcd_mipi_dpi_init_t dpi_para = {
.width = STANDARD_DPI_W, /* LCD Active Width */
.height = STANDARD_DPI_H, /* LCD Active Height */
/* Total Width = HSW + HBP + Active_Width + HFP */
.hsw = STANDARD_DPI_HSW, /* LCD HSW (Hsync Pulse Width) */
.hbp = STANDARD_DPI_HBP, /* LCD HBP (Hsync Back Porch) */
.hfp = STANDARD_DPI_HFP, /* LCD HFP (Hsync Front Porch) */
/* Total Height = VSW + VBP + Active_Height + VFP */
.vsw = STANDARD_DPI_VSW, /* LCD VSW (Vsync Pulse Width) */
.vbp = STANDARD_DPI_VBP, /* LCD VBP (Vsync Back Porch) */
.vfp = STANDARD_DPI_VFP, /* LCD VFP (Vsync Front Porch) */
.frame_rate = STANDARD_DPI_FRAME_RATE, /* Maximum refresh frame rate per second, Used to automatically calculate the clock frequency */
#if (STANDARD_DPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_MIPI_DPI_PIXEL_FORMAT_RGB565,
#endif
.frame_buff = NULL,
};
int standard_dpi_init(standard_dpi_color_t *screen_buffer)
{
if (screen_buffer == NULL) {
return -1;
}
/* mipi dpi init */
dpi_para.frame_buff = (void *)screen_buffer;
return lcd_mipi_dpi_init(&dpi_para);
}
int standard_dpi_screen_switch(standard_dpi_color_t *screen_buffer)
{
return lcd_mipi_dpi_screen_switch((void *)screen_buffer);
}
standard_dpi_color_t *standard_dpi_get_screen_using(void)
{
return (standard_dpi_color_t *)lcd_mipi_dpi_get_screen_using();
}
int standard_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void))
{
if (callback_type == FRAME_INT_TYPE_CYCLE) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_CYCLE, callback);
} else if (callback_type == FRAME_INT_TYPE_SWAP) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_SWAP, callback);
}
return 0;
}
#endif

View file

@ -0,0 +1,47 @@
/**
* @file standard_dpi.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef _STANDARD_DBI_H_
#define _STANDARD_DBI_H_
#include "../lcd_conf.h"
#if defined LCD_DPI_STANDARD
/* Do not modify the following */
#if (STANDARD_DPI_PIXEL_FORMAT == 1)
#define STANDARD_DPI_COLOR_DEPTH 16
typedef uint16_t standard_dpi_color_t;
#elif (STANDARD_DPI_PIXEL_FORMAT == 2)
#define STANDARD_DPI_COLOR_DEPTH 32
typedef uint32_t standard_dpi_color_t;
#endif
int standard_dpi_init(standard_dpi_color_t *screen_buffer);
int standard_dpi_screen_switch(standard_dpi_color_t *screen_buffer);
standard_dpi_color_t *standard_dpi_get_screen_using(void);
int standard_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void));
#endif
#endif

View file

@ -0,0 +1,376 @@
#include "../lcd.h"
#if (defined(LCD_SPI_INTERFACE_TYPE) && (LCD_SPI_INTERFACE_TYPE == 1))
#if (__has_include("bflb_spi.h"))
#include "bl_spi_hard_4.h"
#include "bflb_spi.h"
#include "bflb_dma.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#define LCD_SPI_HARD_4_DMA_LLI_NUM (LCD_SPI_HARD_4_PIXEL_CNT_MAX / 4064 + 1)
/* asynchronous flush interrupt callback */
typedef void (*spi_callback)(void);
static volatile spi_callback spi_async_callback = NULL;
static volatile bool spi_async_callback_en_flag = true;
/* dma device */
static struct bflb_device_s *spi_dma_hd;
/* spi */
static struct bflb_device_s *spi_hd;
/* goio */
static struct bflb_device_s *gpio;
/* The memory space of DMA */
static struct bflb_dma_channel_lli_pool_s dma_tx_llipool[LCD_SPI_HARD_4_DMA_LLI_NUM];
static struct bflb_dma_channel_lli_transfer_s dma_tx_transfers[1];
static uint32_t spi_tx_fifo_address;
static volatile bool spi_async_flag = false;
static volatile bool spi_async_cycle_fill_flag = false;
static uint8_t pixel_format;
static void spi_dma_callback(void *arg)
{
/* Wait for the SPI bus to be idle */
while (bflb_spi_isbusy(spi_hd)) {
__ASM volatile("nop");
};
/* Switch the SPI to non-DMA mode */
bflb_spi_link_txdma(spi_hd, false);
/* clear rx fifo */
bflb_spi_feature_control(spi_hd, SPI_CMD_CLEAR_RX_FIFO, 0);
LCD_SPI_HARD_4_CS_HIGH;
/* 8-bit data */
bflb_spi_feature_control(spi_hd, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_8BIT);
if (spi_async_flag == false && spi_async_cycle_fill_flag == false) {
return;
}
if (spi_async_cycle_fill_flag == true) {
/* enable dma addr increment */
bflb_dma_feature_control(spi_dma_hd, DMA_CMD_SET_SRCADDR_INCREMENT, true);
}
spi_async_flag = false;
spi_async_cycle_fill_flag = false;
/* async callback */
if (spi_async_callback_en_flag && spi_async_callback != NULL) {
spi_async_callback();
}
}
int lcd_spi_hard_4_async_callback_register(void (*callback)(void))
{
spi_async_callback = callback;
return 0;
}
int lcd_spi_hard_4_async_callback_enable(bool enable)
{
spi_async_callback_en_flag = enable;
return 0;
}
int lcd_spi_hard_4_init(lcd_spi_hard_4_init_t *dbi_parra)
{
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = dbi_parra->clock_freq,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* dma cfg */
struct bflb_dma_channel_config_s dma_spi_tx_cfg = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_SPI0_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR4,
.dst_burst_count = DMA_BURST_INCR4,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT,
};
pixel_format = dbi_parra->pixel_format;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = (2 * 4 - 1);
spi_cfg.rx_fifo_threshold = (2 * 4 - 1);
spi_cfg.byte_order = SPI_BYTE_MSB;
#elif
spi_cfg.tx_fifo_threshold = 4 - 1;
spi_cfg.rx_fifo_threshold = 4 - 1;
#endif
spi_hd = bflb_device_get_by_name(LCD_SPI_HARD_4_NAME);
/* CS and DC pin init */
gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_CS, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_DC, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
LCD_SPI_HARD_4_CS_HIGH;
LCD_SPI_HARD_4_DC_HIGH;
if (spi_hd->idx == 0) {
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_CLK, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_DAT, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
}
#if defined(GPIO_FUNC_SPI1)
else if (spi_hd->idx == 1) {
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_CLK, GPIO_FUNC_SPI1 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_DAT, GPIO_FUNC_SPI1 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
}
#endif
/* spi init */
bflb_spi_init(spi_hd, &spi_cfg);
/* spi enabled continuous mode */
// bflb_spi_feature_control(spi_hd, SPI_CMD_SET_CS_INTERVAL, true);
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
dma_spi_tx_cfg.src_width = DMA_DATA_WIDTH_16BIT;
dma_spi_tx_cfg.dst_width = DMA_DATA_WIDTH_16BIT;
}
if (spi_hd->idx == 0) {
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI0_TX;
spi_tx_fifo_address = DMA_ADDR_SPI0_TDR;
}
#if defined(DMA_REQUEST_SPI1_TX)
else if (spi_hd->idx == 1) {
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI1_TX;
spi_tx_fifo_address = DMA_ADDR_SPI1_TDR;
}
#endif
/* dma init */
spi_dma_hd = bflb_device_get_by_name(LCD_SPI_HARD_4_DMA_NAME);
bflb_dma_channel_init(spi_dma_hd, &dma_spi_tx_cfg);
/* dma int cfg */
bflb_dma_channel_irq_attach(spi_dma_hd, spi_dma_callback, NULL);
return 0;
}
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_num)
{
for (size_t i = 0; i < color_num; i++) {
dst[i] = (src[i] << 8) | (src[i] >> 8);
}
return 0;
}
#endif
int lcd_spi_hard_4_is_busy(void)
{
if (spi_async_flag || spi_async_cycle_fill_flag) {
return 1;
} else {
return 0;
}
}
int lcd_spi_hard_4_transmit_cmd_para(uint8_t cmd, uint32_t *para, size_t para_num)
{
LCD_SPI_HARD_4_DC_LOW;
LCD_SPI_HARD_4_CS_LOW;
/* send cmd */
bflb_spi_poll_send(spi_hd, cmd);
LCD_SPI_HARD_4_DC_HIGH;
/* send para */
if (para_num && para != NULL) {
bflb_spi_poll_exchange(spi_hd, para, NULL, para_num);
}
LCD_SPI_HARD_4_CS_HIGH;
return 0;
}
int lcd_spi_hard_4_transmit_cmd_pixel_sync(uint8_t cmd, uint32_t *pixel, size_t pixel_num)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
lcd_swap_color_data16(picture, picture, pixel_num);
#endif
LCD_SPI_HARD_4_DC_LOW;
LCD_SPI_HARD_4_CS_LOW;
/* send cmd */
bflb_spi_poll_send(spi_hd, cmd);
LCD_SPI_HARD_4_DC_HIGH;
if (pixel_num && pixel != NULL) {
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
/* spi 16-bit data mode */
bflb_spi_feature_control(spi_hd, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
}
/* send pixel */
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
bflb_spi_poll_exchange(spi_hd, pixel, NULL, pixel_num * 2);
}
/* spi 8-bit data mode */
bflb_spi_feature_control(spi_hd, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_8BIT);
}
LCD_SPI_HARD_4_CS_HIGH;
return 0;
}
int lcd_spi_hard_4_transmit_cmd_pixel_async(uint8_t cmd, uint32_t *pixel, size_t pixel_num)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
lcd_swap_color_data16(picture, picture, pixel_num);
#endif
LCD_SPI_HARD_4_DC_LOW;
LCD_SPI_HARD_4_CS_LOW;
/* send cmd */
bflb_spi_poll_send(spi_hd, cmd);
LCD_SPI_HARD_4_DC_HIGH;
if (pixel_num && pixel != NULL) {
spi_async_flag = true;
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
/* spi 16-bit data mode */
bflb_spi_feature_control(spi_hd, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
}
/* enable spi dma mode */
bflb_spi_link_txdma(spi_hd, true);
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)pixel;
dma_tx_transfers[0].dst_addr = spi_tx_fifo_address;
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
dma_tx_transfers[0].nbytes = pixel_num * 2;
/* clean cache */
bflb_l1c_dcache_clean_range((void *)pixel, pixel_num * 2);
}
bflb_dma_channel_lli_reload(spi_dma_hd, dma_tx_llipool, LCD_SPI_HARD_4_DMA_LLI_NUM, dma_tx_transfers, 1);
bflb_dma_channel_start(spi_dma_hd);
} else {
LCD_SPI_HARD_4_CS_HIGH;
}
return 0;
}
int lcd_spi_hard_4_transmit_cmd_pixel_fill_sync(uint8_t cmd, uint32_t pixel_val, size_t pixel_num)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
pixel_val = ((pixel_val >> 8) & 0xFF) | pixel_val << 8;
#endif
LCD_SPI_HARD_4_DC_LOW;
LCD_SPI_HARD_4_CS_LOW;
/* send cmd */
bflb_spi_poll_send(spi_hd, cmd);
LCD_SPI_HARD_4_DC_HIGH;
if (pixel_num) {
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
/* spi 16-bit data mode */
bflb_spi_feature_control(spi_hd, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
}
/* send pixel */
for (size_t i = 0; i < pixel_num; i++) {
bflb_spi_poll_send(spi_hd, pixel_val);
}
/* spi 8-bit data mode */
bflb_spi_feature_control(spi_hd, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_8BIT);
}
LCD_SPI_HARD_4_CS_HIGH;
return 0;
}
int lcd_spi_hard_4_transmit_cmd_pixel_fill_async(uint8_t cmd, uint32_t pixel_val, size_t pixel_num)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
pixel_val = ((pixel_val >> 8) & 0xFF) | pixel_val << 8;
#endif
LCD_SPI_HARD_4_DC_LOW;
LCD_SPI_HARD_4_CS_LOW;
/* send cmd */
bflb_spi_poll_send(spi_hd, cmd);
LCD_SPI_HARD_4_DC_HIGH;
if (pixel_num) {
spi_async_cycle_fill_flag = true;
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
/* spi 16-bit data mode */
bflb_spi_feature_control(spi_hd, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
}
/* enable spi dma mode */
bflb_spi_link_txdma(spi_hd, true);
/* disable dma src_addr_inc */
bflb_dma_feature_control(spi_hd, DMA_CMD_SET_SRCADDR_INCREMENT, false);
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)&pixel_val;
dma_tx_transfers[0].dst_addr = spi_tx_fifo_address;
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
dma_tx_transfers[0].nbytes = pixel_num * 2;
}
/* clean cache */
bflb_l1c_dcache_clean_range((void *)&pixel_val, sizeof(pixel_val));
bflb_dma_channel_lli_reload(spi_dma_hd, dma_tx_llipool, LCD_SPI_HARD_4_DMA_LLI_NUM, dma_tx_transfers, 1);
bflb_dma_channel_start(spi_dma_hd);
} else {
LCD_SPI_HARD_4_CS_HIGH;
}
return 0;
}
#else
#error "Devices that do not support SPI! Replace the driver port (lcd_conf.h)"
#endif
#endif

View file

@ -0,0 +1,38 @@
#ifndef _BL_SPI_HARD_4_H
#define _BL_SPI_HARD_4_H
#include "../lcd_conf.h"
#if (defined(LCD_SPI_INTERFACE_TYPE) && (LCD_SPI_INTERFACE_TYPE == 1))
/* Do not modify this file ! */
/* Optional pixel format */
#define LCD_SPI_LCD_PIXEL_FORMAT_RGB565 1
#define LCD_SPI_LCD_PIXEL_FORMAT_NRGB8888 2
#define LCD_SPI_HARD_4_CS_HIGH bflb_gpio_set(gpio, LCD_SPI_HARD_4_PIN_CS)
#define LCD_SPI_HARD_4_CS_LOW bflb_gpio_reset(gpio, LCD_SPI_HARD_4_PIN_CS)
#define LCD_SPI_HARD_4_DC_HIGH bflb_gpio_set(gpio, LCD_SPI_HARD_4_PIN_DC)
#define LCD_SPI_HARD_4_DC_LOW bflb_gpio_reset(gpio, LCD_SPI_HARD_4_PIN_DC)
typedef struct {
uint32_t pixel_format;
uint32_t clock_freq;
} lcd_spi_hard_4_init_t;
int lcd_spi_hard_4_init(lcd_spi_hard_4_init_t *spi_parra);
int lcd_spi_hard_4_transmit_cmd_para(uint8_t cmd, uint32_t *para, size_t para_num);
int lcd_spi_hard_4_transmit_cmd_pixel_sync(uint8_t cmd, uint32_t *pixel, size_t pixel_num);
int lcd_spi_hard_4_transmit_cmd_pixel_fill_sync(uint8_t cmd, uint32_t pixel_val, size_t pixel_num);
int lcd_spi_hard_4_is_busy(void);
int lcd_spi_hard_4_async_callback_enable(bool enable);
int lcd_spi_hard_4_async_callback_register(void (*callback)(void));
int lcd_spi_hard_4_transmit_cmd_pixel_async(uint8_t cmd, uint32_t *pixel, size_t pixel_num);
int lcd_spi_hard_4_transmit_cmd_pixel_fill_async(uint8_t cmd, uint32_t pixel_val, size_t pixel_num);
#endif
#endif

View file

@ -25,37 +25,35 @@
#if defined(LCD_SPI_ILI9341)
#include "bflb_mtimer.h"
#include "bflb_spi.h"
#include "bflb_dma.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#include "ili9341_spi.h"
#if (LCD_SPI_INTERFACE_TYPE == 1)
#include "bl_spi_hard_4.h"
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
#define ILI9341_SPI_ID 1
#define ILI9341_SPI_NAME "spi1"
#define ILI9341_SPI_DMA_NAME "dma2_ch0"
#else
#define ILI9341_SPI_ID 0
#define ILI9341_SPI_NAME "spi0"
#define ILI9341_SPI_DMA_NAME "dma0_ch3"
#define lcd_spi_init lcd_spi_hard_4_init
#define lcd_spi_isbusy lcd_spi_hard_4_is_busy
#define lcd_spi_transmit_cmd_para lcd_spi_hard_4_transmit_cmd_para
#define lcd_spi_transmit_cmd_pixel_sync lcd_spi_hard_4_transmit_cmd_pixel_sync
#define lcd_spi_transmit_cmd_pixel_fill_sync lcd_spi_hard_4_transmit_cmd_pixel_fill_sync
#define lcd_spi_sync_callback_enable lcd_spi_hard_4_async_callback_enable
#define lcd_spi_async_callback_register lcd_spi_hard_4_async_callback_register
#define lcd_spi_transmit_cmd_pixel_async lcd_spi_hard_4_transmit_cmd_pixel_async
#define lcd_spi_transmit_cmd_pixel_fill_async lcd_spi_hard_4_transmit_cmd_pixel_fill_async
static lcd_spi_hard_4_init_t spi_para = {
.clock_freq = 40 * 1000 * 1000,
#if (ILI9341_SPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_RGB565,
#elif (ILI9341_SPI_PIXEL_FORMAT == 2)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#define ILI9341_DMA_LLI_NUM (ILI9341_SPI_W * ILI9341_SPI_H / 4064 + 1)
#else
/* asynchronous flush interrupt callback */
typedef void (*ili9341_spi_callback)(void);
static volatile ili9341_spi_callback ili9341_spi_async_callback = NULL;
static volatile bool ili9341_spi_sync_flush_flag = false;
#error "Configuration error"
static struct bflb_device_s *ili9341_gpio;
static struct bflb_device_s *ili9341_spi;
static struct bflb_device_s *ili9341_dma_spi_tx;
/* The memory space of DMA */
static struct bflb_dma_channel_lli_pool_s dam_tx_llipool[ILI9341_DMA_LLI_NUM];
static struct bflb_dma_channel_lli_transfer_s dma_tx_transfers[1];
#endif
const ili9341_spi_init_cmd_t ili9341_spi_init_cmds[] = {
{ 0x01, NULL, 0 },
@ -93,24 +91,13 @@ const ili9341_spi_init_cmd_t ili9341_spi_init_cmds[] = {
};
/**
* @brief ili9341_spi_dma_flush_callback
* @brief ili9341_spi_async_callback_enable
*
* @return
*/
void ili9341_spi_dma_flush_callback(void *arg)
void ili9341_spi_async_callback_enable(bool enable)
{
if (ili9341_spi_sync_flush_flag == true) {
ili9341_spi_sync_flush_flag = false;
return;
}
while (ili9341_spi_draw_is_busy()) {
__ASM volatile("nop");
};
if (ili9341_spi_async_callback != NULL) {
ili9341_spi_async_callback();
}
lcd_spi_sync_callback_enable(enable);
}
/**
@ -120,123 +107,7 @@ void ili9341_spi_dma_flush_callback(void *arg)
*/
void ili9341_spi_async_callback_register(void (*callback)(void))
{
ili9341_spi_async_callback = callback;
}
/**
* @brief ili9341_spi_init
*
* @return int 0:succes 1:error
*/
static int ili9341_spi_peripheral_init(void)
{
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = 40 * 1000 * 1000,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* dma */
struct bflb_dma_channel_config_s dma_spi_tx_cfg = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_SPI0_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR1,
.dst_burst_count = DMA_BURST_INCR1,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT,
};
/* CS and DC pin init */
ili9341_gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(ili9341_gpio, ILI9341_SPI_CS_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(ili9341_gpio, ILI9341_SPI_DC_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
ILI9341_SPI_CS_HIGH;
ILI9341_SPI_DC_HIGH;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 2 * 4 - 1;
spi_cfg.rx_fifo_threshold = 2 * 4 - 1;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 4 - 1;
spi_cfg.rx_fifo_threshold = 4 - 1;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
spi_cfg.byte_order = SPI_BYTE_MSB;
#endif
/* spi init */
ili9341_spi = bflb_device_get_by_name(ILI9341_SPI_NAME);
bflb_spi_init(ili9341_spi, &spi_cfg);
/* spi enabled continuous mode */
bflb_spi_feature_control(ili9341_spi, SPI_CMD_SET_CS_INTERVAL, true);
#if (ILI9341_SPI_ID == 0)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI0_TX;
#elif (ILI9341_SPI_ID == 1)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI1_TX;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#endif
/* dma init */
ili9341_dma_spi_tx = bflb_device_get_by_name(ILI9341_SPI_DMA_NAME);
bflb_dma_channel_init(ili9341_dma_spi_tx, &dma_spi_tx_cfg);
/* dma int cfg */
bflb_dma_channel_irq_attach(ili9341_dma_spi_tx, ili9341_spi_dma_flush_callback, NULL);
return 0;
}
/**
* @brief ili9341_spi_write_cmd
*
* @param cmd
* @return int 0:succes 1:error
*/
static int ili9341_spi_write_cmd(uint8_t cmd)
{
ILI9341_SPI_DC_LOW;
ILI9341_SPI_CS_LOW;
bflb_spi_poll_send(ili9341_spi, cmd);
ILI9341_SPI_CS_HIGH;
ILI9341_SPI_DC_HIGH;
return 0;
}
/**
* @brief ili9341_spi_write_data_byte
*
* @param data
* @return int 0:succes 1:error
*/
static int ili9341_spi_write_data_byte(uint8_t data)
{
ILI9341_SPI_CS_LOW;
bflb_spi_poll_send(ili9341_spi, data);
ILI9341_SPI_CS_HIGH;
return 0;
lcd_spi_async_callback_register(callback);
}
/**
@ -248,23 +119,7 @@ static int ili9341_spi_write_data_byte(uint8_t data)
*/
int ili9341_spi_draw_is_busy(void)
{
if (bflb_dma_channel_isbusy(ili9341_dma_spi_tx)) {
return 1;
} else {
/* Wait for the SPI bus to be idle */
while (bflb_spi_isbusy(ili9341_spi)) {
__ASM volatile("nop");
};
/* Switch the SPI to non-DMA mode */
bflb_spi_link_txdma(ili9341_spi, false);
/* clear rx fifo */
bflb_spi_feature_control(ili9341_spi, SPI_CMD_CLEAR_RX_FIFO, 0);
/* */
ILI9341_SPI_CS_HIGH;
/* 8-bit data */
bflb_spi_feature_control(ili9341_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_8BIT);
return 0;
}
return lcd_spi_isbusy();
}
/**
@ -274,48 +129,19 @@ int ili9341_spi_draw_is_busy(void)
*/
int ili9341_spi_init()
{
int res = ili9341_spi_peripheral_init();
if (res < 0) {
return res;
}
lcd_spi_init(&spi_para);
for (uint16_t i = 0; i < (sizeof(ili9341_spi_init_cmds) / sizeof(ili9341_spi_init_cmd_t)); i++) {
if (ili9341_spi_init_cmds[i].cmd == 0xFF && ili9341_spi_init_cmds[i].data == NULL) {
for (uint16_t i = 0; i < (sizeof(ili9341_spi_init_cmds) / sizeof(ili9341_spi_init_cmds[0])); i++) {
if (ili9341_spi_init_cmds[i].cmd == 0xFF && ili9341_spi_init_cmds[i].data == NULL && ili9341_spi_init_cmds[i].databytes) {
bflb_mtimer_delay_ms(ili9341_spi_init_cmds[i].databytes);
} else {
/* send register address */
ili9341_spi_write_cmd(ili9341_spi_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (ili9341_spi_init_cmds[i].databytes); j++) {
ili9341_spi_write_data_byte(ili9341_spi_init_cmds[i].data[j]);
lcd_spi_transmit_cmd_para(ili9341_spi_init_cmds[i].cmd, (void *)(ili9341_spi_init_cmds[i].data), ili9341_spi_init_cmds[i].databytes);
}
}
}
ili9341_spi_set_draw_window(0, 0, ILI9341_SPI_H, ILI9341_SPI_W);
return res;
}
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
/**
* @brief lcd_swap_color_data16
*
* @param dst destination
* @param src source
* @param color_num color num
* @return int
*/
static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_num)
{
for (size_t i = 0; i < color_num; i++) {
dst[i] = (src[i] << 8) | (src[i] >> 8);
}
return 0;
}
#endif
/**
* @brief
*
@ -357,8 +183,7 @@ int ili9341_spi_set_dir(uint8_t dir, uint8_t mir_flag)
break;
}
ili9341_spi_write_cmd(0x36);
ili9341_spi_write_data_byte(param);
lcd_spi_transmit_cmd_para(0x36, (void *)&param, 1);
return dir;
}
@ -371,7 +196,7 @@ int ili9341_spi_set_dir(uint8_t dir, uint8_t mir_flag)
* @param x2
* @param y2
*/
void ili9341_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
void ili9341_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
#if ILI9341_SPI_OFFSET_X
x1 += ILI9341_SPI_OFFSET_X;
@ -382,19 +207,21 @@ void ili9341_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t
y2 += ILI9341_SPI_OFFSET_Y;
#endif
ili9341_spi_write_cmd(0x2a);
ili9341_spi_write_data_byte(x1 >> 8);
ili9341_spi_write_data_byte(x1);
ili9341_spi_write_data_byte(x2 >> 8);
ili9341_spi_write_data_byte(x2);
int8_t param[4];
ili9341_spi_write_cmd(0x2b);
ili9341_spi_write_data_byte(y1 >> 8);
ili9341_spi_write_data_byte(y1);
ili9341_spi_write_data_byte(y2 >> 8);
ili9341_spi_write_data_byte(y2);
param[0] = (x1 >> 8) & 0xFF;
param[1] = x1 & 0xFF;
param[2] = (x2 >> 8) & 0xFF;
param[3] = x2 & 0xFF;
ili9341_spi_write_cmd(0x2c);
lcd_spi_transmit_cmd_para(0x2A, (void *)param, 4);
param[0] = (y1 >> 8) & 0xFF;
param[1] = y1 & 0xFF;
param[2] = (y2 >> 8) & 0xFF;
param[3] = y2 & 0xFF;
lcd_spi_transmit_cmd_para(0x2B, (void *)param, 4);
}
/**
@ -406,16 +233,10 @@ void ili9341_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t
*/
void ili9341_spi_draw_point(uint16_t x, uint16_t y, ili9341_spi_color_t color)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
color = ((color >> 8) & 0xFF) | color << 8;
#endif
/* set window */
ili9341_spi_set_draw_window(x, y, x, y);
ILI9341_SPI_DC_HIGH;
ILI9341_SPI_CS_LOW;
bflb_spi_poll_send(ili9341_spi, color & 0x00ff);
bflb_spi_poll_send(ili9341_spi, (color >> 8) & 0x00ff);
ILI9341_SPI_CS_HIGH;
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)&color, 1);
}
/**
@ -429,57 +250,12 @@ void ili9341_spi_draw_point(uint16_t x, uint16_t y, ili9341_spi_color_t color)
*/
void ili9341_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_spi_color_t color)
{
uint32_t pixelDataSize, PixelCount = (x2 - x1 + 1) * (y2 - y1 + 1);
uint32_t __attribute__((aligned(64))) color_src;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
color_src = color;
#else
color_src = ((color >> 8) & 0xFF) | color << 8;
#endif
/* clean cache */
bflb_l1c_dcache_clean_range((void *)&color_src, sizeof(color_src));
uint32_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9341_spi_set_draw_window(x1, y1, x2, y2);
/* get pixel Data Size */
pixelDataSize = PixelCount * 2;
/* spi 16-bit mode */
bflb_spi_feature_control(ili9341_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* enable spi dma mode */
bflb_spi_link_txdma(ili9341_spi, true);
ILI9341_SPI_CS_LOW;
/* sync mode flag, temporary shutdown interrupt */
ili9341_spi_sync_flush_flag = true;
/* disable dma src_addr_inc */
bflb_dma_feature_control(ili9341_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, false);
/* cfg and start dma */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)&color_src;
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI1_TDR;
#else
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
#endif
dma_tx_transfers[0].nbytes = pixelDataSize;
bflb_dma_channel_lli_reload(ili9341_dma_spi_tx, dam_tx_llipool, ILI9341_DMA_LLI_NUM, dma_tx_transfers, 1);
bflb_dma_channel_start(ili9341_dma_spi_tx);
/* Wait to finish, and cs high */
while (ili9341_spi_draw_is_busy()) {
__ASM volatile("nop");
};
/* enable src_addr_inc */
bflb_dma_feature_control(ili9341_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, true);
lcd_spi_transmit_cmd_pixel_fill_sync(0x2C, (uint32_t)color, pixel_cnt);
}
/**
@ -494,31 +270,12 @@ void ili9341_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, i
*/
void ili9341_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_spi_color_t *picture)
{
size_t picture_size = (x2 - x1 + 1) * (y2 - y1 + 1);
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9341_spi_set_draw_window(x1, y1, x2, y2);
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
lcd_swap_color_data16(picture, picture, picture_size);
#endif
/* clean dcache */
bflb_l1c_dcache_clean_range((void *)(picture), (picture_size * 2));
/* spi 16-bit data mode */
bflb_spi_feature_control(ili9341_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* spi dma mode enable */
bflb_spi_link_txdma(ili9341_spi, true);
ILI9341_SPI_CS_LOW;
/* dma cfg and start */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)picture;
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
dma_tx_transfers[0].nbytes = picture_size * 2;
bflb_dma_channel_lli_reload(ili9341_dma_spi_tx, dam_tx_llipool, sizeof(dam_tx_llipool) / sizeof(dam_tx_llipool[0]), dma_tx_transfers, 1);
bflb_dma_channel_start(ili9341_dma_spi_tx);
lcd_spi_transmit_cmd_pixel_async(0x2C, (void *)picture, pixel_cnt);
}
/**
@ -532,13 +289,12 @@ void ili9341_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2,
*/
void ili9341_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_spi_color_t *picture)
{
/* sync mode, temporary shutdown interrupt */
ili9341_spi_sync_flush_flag = true;
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
ili9341_spi_draw_picture_nonblocking(x1, y1, x2, y2, picture);
while (ili9341_spi_draw_is_busy()) {
__ASM volatile("nop");
};
/* set window */
ili9341_spi_set_draw_window(x1, y1, x2, y2);
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)picture, pixel_cnt);
}
#endif

View file

@ -24,21 +24,11 @@
#ifndef _ILI9341_SPI_H_
#define _ILI9341_SPI_H_
#include "bflb_core.h"
#include "../lcd_conf.h"
#define ILI9341_SPI_CS_PIN GPIO_PIN_16
#define ILI9341_SPI_DC_PIN GPIO_PIN_18
#if defined LCD_SPI_ILI9341
#define ILI9341_SPI_CS_HIGH bflb_gpio_set(ili9341_gpio, ILI9341_SPI_CS_PIN)
#define ILI9341_SPI_CS_LOW bflb_gpio_reset(ili9341_gpio, ILI9341_SPI_CS_PIN)
#define ILI9341_SPI_DC_HIGH bflb_gpio_set(ili9341_gpio, ILI9341_SPI_DC_PIN)
#define ILI9341_SPI_DC_LOW bflb_gpio_reset(ili9341_gpio, ILI9341_SPI_DC_PIN)
#define ILI9341_SPI_W 240 /* ILI9341 LCD width */
#define ILI9341_SPI_H 320 /* ILI9341 LCD height */
#define ILI9341_SPI_OFFSET_X 0
#define ILI9341_SPI_OFFSET_Y 0
/* Do not modify the following */
#define ILI9341_SPI_COLOR_DEPTH 16
@ -51,9 +41,10 @@ typedef struct {
typedef uint16_t ili9341_spi_color_t;
int ili9341_spi_init();
void ili9341_spi_async_callback_enable(bool enable);
void ili9341_spi_async_callback_register(void (*callback)(void));
int ili9341_spi_set_dir(uint8_t dir, uint8_t mir_flag);
void ili9341_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2);
void ili9341_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void ili9341_spi_draw_point(uint16_t x, uint16_t y, ili9341_spi_color_t color);
void ili9341_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_spi_color_t color);
void ili9341_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9341_spi_color_t *picture);
@ -61,3 +52,4 @@ void ili9341_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, ui
int ili9341_spi_draw_is_busy(void);
#endif
#endif

View file

@ -25,37 +25,35 @@
#if defined(LCD_SPI_ILI9488)
#include "bflb_mtimer.h"
#include "bflb_spi.h"
#include "bflb_dma.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#include "ili9488_spi.h"
#if (LCD_SPI_INTERFACE_TYPE == 1)
#include "bl_spi_hard_4.h"
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
#define ILI9488_SPI_ID 1
#define ILI9488_SPI_NAME "spi1"
#define ILI9488_SPI_DMA_NAME "dma2_ch0"
#else
#define ILI9488_SPI_ID 0
#define ILI9488_SPI_NAME "spi0"
#define ILI9488_SPI_DMA_NAME "dma0_ch3"
#define lcd_spi_init lcd_spi_hard_4_init
#define lcd_spi_isbusy lcd_spi_hard_4_is_busy
#define lcd_spi_transmit_cmd_para lcd_spi_hard_4_transmit_cmd_para
#define lcd_spi_transmit_cmd_pixel_sync lcd_spi_hard_4_transmit_cmd_pixel_sync
#define lcd_spi_transmit_cmd_pixel_fill_sync lcd_spi_hard_4_transmit_cmd_pixel_fill_sync
#define lcd_spi_sync_callback_enable lcd_spi_hard_4_async_callback_enable
#define lcd_spi_async_callback_register lcd_spi_hard_4_async_callback_register
#define lcd_spi_transmit_cmd_pixel_async lcd_spi_hard_4_transmit_cmd_pixel_async
#define lcd_spi_transmit_cmd_pixel_fill_async lcd_spi_hard_4_transmit_cmd_pixel_fill_async
static lcd_spi_hard_4_init_t spi_para = {
.clock_freq = 40 * 1000 * 1000,
#if (ILI9488_SPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_RGB565,
#elif (ILI9488_SPI_PIXEL_FORMAT == 2)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#define ILI9488_DMA_LLI_NUM (ILI9488_SPI_W * ILI9488_SPI_H / 4064 + 1)
#else
/* asynchronous flush interrupt callback */
typedef void (*ili9488_spi_callback)(void);
static volatile ili9488_spi_callback ili9488_spi_async_callback = NULL;
static volatile bool ili9488_spi_sync_flush_flag = 0;
#error "Configuration error"
static struct bflb_device_s *ili9488_gpio;
static struct bflb_device_s *ili9488_spi;
static struct bflb_device_s *ili9488_dma_spi_tx;
/* The memory space of DMA */
static struct bflb_dma_channel_lli_pool_s dam_tx_llipool[ILI9488_DMA_LLI_NUM];
static struct bflb_dma_channel_lli_transfer_s dma_tx_transfers[1];
#endif
const ili9488_spi_init_cmd_t ili9488_spi_init_cmds[] = {
{ 0x01, NULL, 0 }, /* software reset */
@ -83,29 +81,22 @@ const ili9488_spi_init_cmd_t ili9488_spi_init_cmds[] = {
{ 0xF7, "\xA9\x51\x2C\x82", 4 }, /* Adjust Control 3 */
#if ILI9488_SPI_COLOR_REVERSAL
{ 0x21, NULL, 0 }, /* Color reversal */
#endif
{ 0x29, NULL, 0 }, /* Display On */
{ 0xFF, NULL, 10 },
};
/**
* @brief ili9488_spi_dma_flush_callback
* @brief ili9488_spi_async_callback_enable
*
* @return
*/
void ili9488_spi_dma_flush_callback(void *args)
void ili9488_spi_async_callback_enable(bool enable)
{
if (ili9488_spi_sync_flush_flag == true) {
ili9488_spi_sync_flush_flag = false;
return;
}
while (ili9488_spi_draw_is_busy()) {
__ASM volatile("nop");
};
if (ili9488_spi_async_callback != NULL) {
ili9488_spi_async_callback();
}
lcd_spi_sync_callback_enable(enable);
}
/**
@ -115,123 +106,7 @@ void ili9488_spi_dma_flush_callback(void *args)
*/
void ili9488_spi_async_callback_register(void (*callback)(void))
{
ili9488_spi_async_callback = callback;
}
/**
* @brief ili9488_spi_init
*
* @return int 0:succes 1:error
*/
static int ili9488_spi_peripheral_init(void)
{
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = 40 * 1000 * 1000,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* dma */
struct bflb_dma_channel_config_s dma_spi_tx_cfg = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_SPI0_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR1,
.dst_burst_count = DMA_BURST_INCR1,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT,
};
/* CS and DC pin init */
ili9488_gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(ili9488_gpio, ILI9488_SPI_CS_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(ili9488_gpio, ILI9488_SPI_DC_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
ILI9488_SPI_CS_HIGH;
ILI9488_SPI_DC_HIGH;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 2 * 4 - 1;
spi_cfg.rx_fifo_threshold = 2 * 4 - 1;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 4 - 1;
spi_cfg.rx_fifo_threshold = 4 - 1;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
spi_cfg.byte_order = SPI_BYTE_MSB;
#endif
/* spi init */
ili9488_spi = bflb_device_get_by_name(ILI9488_SPI_NAME);
bflb_spi_init(ili9488_spi, &spi_cfg);
/* spi enabled continuous mode */
bflb_spi_feature_control(ili9488_spi, SPI_CMD_SET_CS_INTERVAL, true);
#if (ILI9488_SPI_ID == 0)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI0_TX;
#elif (ILI9488_SPI_ID == 1)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI1_TX;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#endif
/* dma init */
ili9488_dma_spi_tx = bflb_device_get_by_name(ILI9488_SPI_DMA_NAME);
bflb_dma_channel_init(ili9488_dma_spi_tx, &dma_spi_tx_cfg);
/* dma int cfg */
bflb_dma_channel_irq_attach(ili9488_dma_spi_tx, ili9488_spi_dma_flush_callback, NULL);
return 0;
}
/**
* @brief ili9488_spi_write_cmd
*
* @param cmd
* @return int 0:succes 1:error
*/
static int ili9488_spi_write_cmd(uint8_t cmd)
{
ILI9488_SPI_DC_LOW;
ILI9488_SPI_CS_LOW;
bflb_spi_poll_send(ili9488_spi, cmd);
ILI9488_SPI_CS_HIGH;
ILI9488_SPI_DC_HIGH;
return 0;
}
/**
* @brief ili9488_spi_write_data_byte
*
* @param data
* @return int 0:succes 1:error
*/
static int ili9488_spi_write_data_byte(uint8_t data)
{
ILI9488_SPI_CS_LOW;
bflb_spi_poll_send(ili9488_spi, data);
ILI9488_SPI_CS_HIGH;
return 0;
lcd_spi_async_callback_register(callback);
}
/**
@ -243,23 +118,7 @@ static int ili9488_spi_write_data_byte(uint8_t data)
*/
int ili9488_spi_draw_is_busy(void)
{
if (bflb_dma_channel_isbusy(ili9488_dma_spi_tx)) {
return 1;
} else {
/* Wait for the SPI bus to be idle */
while (bflb_spi_isbusy(ili9488_spi)) {
__ASM volatile("nop");
};
/* Switch the SPI to non-DMA mode */
bflb_spi_link_txdma(ili9488_spi, false);
/* clear rx fifo */
bflb_spi_feature_control(ili9488_spi, SPI_CMD_CLEAR_RX_FIFO, 0);
/* */
ILI9488_SPI_CS_HIGH;
/* 8-bit data */
bflb_spi_feature_control(ili9488_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_8BIT);
return 0;
}
return lcd_spi_isbusy();
}
/**
@ -269,48 +128,19 @@ int ili9488_spi_draw_is_busy(void)
*/
int ili9488_spi_init()
{
int res = ili9488_spi_peripheral_init();
if (res < 0) {
return res;
}
lcd_spi_init(&spi_para);
for (uint16_t i = 0; i < (sizeof(ili9488_spi_init_cmds) / sizeof(ili9488_spi_init_cmd_t)); i++) {
if (ili9488_spi_init_cmds[i].cmd == 0xFF && ili9488_spi_init_cmds[i].data == NULL) {
for (uint16_t i = 0; i < (sizeof(ili9488_spi_init_cmds) / sizeof(ili9488_spi_init_cmds[0])); i++) {
if (ili9488_spi_init_cmds[i].cmd == 0xFF && ili9488_spi_init_cmds[i].data == NULL && ili9488_spi_init_cmds[i].databytes) {
bflb_mtimer_delay_ms(ili9488_spi_init_cmds[i].databytes);
} else {
/* send register address */
ili9488_spi_write_cmd(ili9488_spi_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (ili9488_spi_init_cmds[i].databytes); j++) {
ili9488_spi_write_data_byte(ili9488_spi_init_cmds[i].data[j]);
lcd_spi_transmit_cmd_para(ili9488_spi_init_cmds[i].cmd, (void *)(ili9488_spi_init_cmds[i].data), ili9488_spi_init_cmds[i].databytes);
}
}
}
ili9488_spi_set_draw_window(0, 0, ILI9488_SPI_H, ILI9488_SPI_W);
return res;
}
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
/**
* @brief lcd_swap_color_data16
*
* @param dst destination
* @param src source
* @param color_num color num
* @return int
*/
static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_num)
{
for (size_t i = 0; i < color_num; i++) {
dst[i] = (src[i] << 8) | (src[i] >> 8);
}
return 0;
}
#endif
/**
* @brief
*
@ -320,6 +150,7 @@ static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_nu
int ili9488_spi_set_dir(uint8_t dir, uint8_t mir_flag)
{
uint8_t param;
switch (dir) {
case 0:
if (!mir_flag)
@ -350,8 +181,9 @@ int ili9488_spi_set_dir(uint8_t dir, uint8_t mir_flag)
return -1;
break;
}
ili9488_spi_write_cmd(0x36);
ili9488_spi_write_data_byte(param);
lcd_spi_transmit_cmd_para(0x36, (void *)&param, 1);
return dir;
}
@ -374,19 +206,21 @@ void ili9488_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t
y2 += ILI9488_SPI_OFFSET_Y;
#endif
ili9488_spi_write_cmd(0x2a);
ili9488_spi_write_data_byte(x1 >> 8);
ili9488_spi_write_data_byte(x1);
ili9488_spi_write_data_byte(x2 >> 8);
ili9488_spi_write_data_byte(x2);
int8_t param[4];
ili9488_spi_write_cmd(0x2b);
ili9488_spi_write_data_byte(y1 >> 8);
ili9488_spi_write_data_byte(y1);
ili9488_spi_write_data_byte(y2 >> 8);
ili9488_spi_write_data_byte(y2);
param[0] = (x1 >> 8) & 0xFF;
param[1] = x1 & 0xFF;
param[2] = (x2 >> 8) & 0xFF;
param[3] = x2 & 0xFF;
ili9488_spi_write_cmd(0x2c);
lcd_spi_transmit_cmd_para(0x2A, (void *)param, 4);
param[0] = (y1 >> 8) & 0xFF;
param[1] = y1 & 0xFF;
param[2] = (y2 >> 8) & 0xFF;
param[3] = y2 & 0xFF;
lcd_spi_transmit_cmd_para(0x2B, (void *)param, 4);
}
/**
@ -398,20 +232,14 @@ void ili9488_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t
*/
void ili9488_spi_draw_point(uint16_t x, uint16_t y, ili9488_spi_color_t color)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
color = ((color >> 8) & 0xFF) | color << 8;
#endif
/* set window */
ili9488_spi_set_draw_window(x, y, x, y);
ILI9488_SPI_DC_HIGH;
ILI9488_SPI_CS_LOW;
bflb_spi_poll_send(ili9488_spi, color & 0x00ff);
bflb_spi_poll_send(ili9488_spi, (color >> 8) & 0x00ff);
ILI9488_SPI_CS_HIGH;
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)&color, 1);
}
/**
* @brief ili9488_spi_draw_area
* @brief ili9488_draw_area
*
* @param x1
* @param y1
@ -421,62 +249,17 @@ void ili9488_spi_draw_point(uint16_t x, uint16_t y, ili9488_spi_color_t color)
*/
void ili9488_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_spi_color_t color)
{
uint32_t pixelDataSize, PixelCount = (x2 - x1 + 1) * (y2 - y1 + 1);
uint32_t __attribute__((aligned(64))) color_src;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
color_src = color;
#else
color_src = ((color >> 8) & 0xFF) | color << 8;
#endif
/* clean cache */
bflb_l1c_dcache_clean_range((void *)&color_src, sizeof(color_src));
uint32_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9488_spi_set_draw_window(x1, y1, x2, y2);
/* get pixel Data Size */
pixelDataSize = PixelCount * 2;
/* spi 16-bit mode */
bflb_spi_feature_control(ili9488_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* enable spi dma mode */
bflb_spi_link_txdma(ili9488_spi, true);
ILI9488_SPI_CS_LOW;
/* sync mode flag, temporary shutdown interrupt */
ili9488_spi_sync_flush_flag = true;
/* disable dma src_addr_inc */
bflb_dma_feature_control(ili9488_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, false);
/* cfg and start dma */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)&color_src;
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI1_TDR;
#else
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
#endif
dma_tx_transfers[0].nbytes = pixelDataSize;
bflb_dma_channel_lli_reload(ili9488_dma_spi_tx, dam_tx_llipool, ILI9488_DMA_LLI_NUM, dma_tx_transfers, 1);
bflb_dma_channel_start(ili9488_dma_spi_tx);
/* Wait to finish, and cs high */
while (ili9488_spi_draw_is_busy()) {
__ASM volatile("nop");
};
/* enable src_addr_inc */
bflb_dma_feature_control(ili9488_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, true);
lcd_spi_transmit_cmd_pixel_fill_sync(0x2C, (uint32_t)color, pixel_cnt);
}
/**
* @brief ili9488_spi_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
* After the call, No other operations are allowed until (ili9488_spi_draw_is_busy()==0)
* @brief ili9488_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
* After the call, No other operations are allowed until (ili9488_draw_is_busy()==0)
*
* @param x1
* @param y1
@ -484,38 +267,18 @@ void ili9488_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, i
* @param y2
* @param picture
*/
void ili9488_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_spi_color_t *picture)
{
size_t picture_size = (x2 - x1 + 1) * (y2 - y1 + 1);
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
ili9488_spi_set_draw_window(x1, y1, x2, y2);
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
lcd_swap_color_data16(picture, picture, picture_size);
#endif
/* clean dcache */
bflb_l1c_dcache_clean_range((void *)(picture), (picture_size * 2));
/* spi 16-bit data mode */
bflb_spi_feature_control(ili9488_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* spi dma mode enable */
bflb_spi_link_txdma(ili9488_spi, true);
ILI9488_SPI_CS_LOW;
/* dma cfg and start */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)picture;
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
dma_tx_transfers[0].nbytes = picture_size * 2;
bflb_dma_channel_lli_reload(ili9488_dma_spi_tx, dam_tx_llipool, sizeof(dam_tx_llipool) / sizeof(dam_tx_llipool[0]), dma_tx_transfers, 1);
bflb_dma_channel_start(ili9488_dma_spi_tx);
lcd_spi_transmit_cmd_pixel_async(0x2C, (void *)picture, pixel_cnt);
}
/**
* @brief ili9488_spi_draw_picture,BlockingUsing DMA acceleration,Waiting for the draw end
* @brief ili9488_draw_picture,Blocking,Using DMA acceleration,Waiting for the draw end
*
* @param x1
* @param y1
@ -525,12 +288,12 @@ void ili9488_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2,
*/
void ili9488_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, ili9488_spi_color_t *picture)
{
/* sync mode, temporary shutdown interrupt */
ili9488_spi_sync_flush_flag = true;
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
ili9488_spi_draw_picture_nonblocking(x1, y1, x2, y2, picture);
while (ili9488_spi_draw_is_busy()) {
};
/* set window */
ili9488_spi_set_draw_window(x1, y1, x2, y2);
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)picture, pixel_cnt);
}
#endif

View file

@ -24,24 +24,11 @@
#ifndef _ILI9488_SPI_H_
#define _ILI9488_SPI_H_
#include "bflb_core.h"
#include "../lcd_conf.h"
#define ILI9488_SPI_CS_PIN GPIO_PIN_16
#define ILI9488_SPI_DC_PIN GPIO_PIN_18
#if defined LCD_SPI_ILI9488
#define ILI9488_SPI_CS_HIGH bflb_gpio_set(ili9488_gpio, ILI9488_SPI_CS_PIN)
#define ILI9488_SPI_CS_LOW bflb_gpio_reset(ili9488_gpio, ILI9488_SPI_CS_PIN)
#define ILI9488_SPI_DC_HIGH bflb_gpio_set(ili9488_gpio, ILI9488_SPI_DC_PIN)
#define ILI9488_SPI_DC_LOW bflb_gpio_reset(ili9488_gpio, ILI9488_SPI_DC_PIN)
/* ILI9488 LCD width */
#define ILI9488_SPI_W 320
/* ILI9488 LCD height */
#define ILI9488_SPI_H 480
/* The offset of the area can be displayed */
#define ILI9488_SPI_OFFSET_X 0
#define ILI9488_SPI_OFFSET_Y 0
/* Do not modify the following */
#define ILI9488_SPI_COLOR_DEPTH 16
@ -54,6 +41,7 @@ typedef struct {
typedef uint16_t ili9488_spi_color_t;
int ili9488_spi_init();
void ili9488_spi_async_callback_enable(bool enable);
void ili9488_spi_async_callback_register(void (*callback)(void));
int ili9488_spi_set_dir(uint8_t dir, uint8_t mir_flag);
void ili9488_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
@ -64,3 +52,4 @@ void ili9488_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, ui
int ili9488_spi_draw_is_busy(void);
#endif
#endif

View file

@ -25,38 +25,35 @@
#if defined(LCD_SPI_ST7789V)
#include "bflb_mtimer.h"
#include "bflb_spi.h"
#include "bflb_dma.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#include "st7789v_spi.h"
#if (LCD_SPI_INTERFACE_TYPE == 1)
#include "bl_spi_hard_4.h"
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
#define ST7789V_SPI_ID 1
#define ST7789V_SPI_NAME "spi1"
#define ST7789V_SPI_DMA_NAME "dma2_ch0"
#else
#define ST7789V_SPI_ID 0
#define ST7789V_SPI_NAME "spi0"
#define ST7789V_SPI_DMA_NAME "dma0_ch3"
#define lcd_spi_init lcd_spi_hard_4_init
#define lcd_spi_isbusy lcd_spi_hard_4_is_busy
#define lcd_spi_transmit_cmd_para lcd_spi_hard_4_transmit_cmd_para
#define lcd_spi_transmit_cmd_pixel_sync lcd_spi_hard_4_transmit_cmd_pixel_sync
#define lcd_spi_transmit_cmd_pixel_fill_sync lcd_spi_hard_4_transmit_cmd_pixel_fill_sync
#define lcd_spi_sync_callback_enable lcd_spi_hard_4_async_callback_enable
#define lcd_spi_async_callback_register lcd_spi_hard_4_async_callback_register
#define lcd_spi_transmit_cmd_pixel_async lcd_spi_hard_4_transmit_cmd_pixel_async
#define lcd_spi_transmit_cmd_pixel_fill_async lcd_spi_hard_4_transmit_cmd_pixel_fill_async
static lcd_spi_hard_4_init_t spi_para = {
.clock_freq = 40 * 1000 * 1000,
#if (ST7789V_SPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_RGB565,
#elif (ST7789V_SPI_PIXEL_FORMAT == 2)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#define ST7789V_DMA_LLI_NUM (ST7789V_SPI_W * ST7789V_SPI_H / 4064 + 1)
#else
/* asynchronous flush interrupt callback */
typedef void (*st7789v_spi_callback)(void);
static volatile st7789v_spi_callback st7789v_spi_async_callback = NULL;
static volatile bool st7789v_spi_sync_flush_flag = 0;
static struct bflb_device_s *st7789v_gpio;
static struct bflb_device_s *st7789v_spi;
static struct bflb_device_s *st7789v_dma_spi_tx;
/* The memory space of DMA */
static struct bflb_dma_channel_lli_pool_s dam_tx_llipool[ST7789V_DMA_LLI_NUM];
static struct bflb_dma_channel_lli_transfer_s dma_tx_transfers[1];
#error "Configuration error"
#endif
const st7789v_spi_init_cmd_t st7789v_spi_init_cmds[] = {
{ 0x01, NULL, 0 },
{ 0xFF, NULL, 10 },
@ -71,23 +68,13 @@ const st7789v_spi_init_cmd_t st7789v_spi_init_cmds[] = {
};
/**
* @brief st7789v_spi_dma_flush_callback
* @brief st7789v_spi_async_callback_enable
*
* @return
*/
void st7789v_spi_dma_flush_callback(void *args)
void st7789v_spi_async_callback_enable(bool enable)
{
if (st7789v_spi_sync_flush_flag == true) {
st7789v_spi_sync_flush_flag = false;
return;
}
while (lcd_draw_is_busy()) {
};
if (st7789v_spi_async_callback != NULL) {
st7789v_spi_async_callback();
}
lcd_spi_sync_callback_enable(enable);
}
/**
@ -97,123 +84,7 @@ void st7789v_spi_dma_flush_callback(void *args)
*/
void st7789v_spi_async_callback_register(void (*callback)(void))
{
st7789v_spi_async_callback = callback;
}
/**
* @brief st7789v_spi_init
*
* @return int 0:succes 1:error
*/
static int st7789v_spi_peripheral_init(void)
{
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = 80 * 1000 * 1000,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* dma */
struct bflb_dma_channel_config_s dma_spi_tx_cfg = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_SPI0_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR1,
.dst_burst_count = DMA_BURST_INCR1,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT,
};
/* CS and DC pin init */
st7789v_gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(st7789v_gpio, ST7789V_SPI_CS_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(st7789v_gpio, ST7789V_SPI_DC_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
ST7789V_SPI_CS_HIGH;
ST7789V_SPI_DC_HIGH;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 2 * 4 - 1;
spi_cfg.rx_fifo_threshold = 2 * 4 - 1;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 4 - 1;
spi_cfg.rx_fifo_threshold = 4 - 1;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
spi_cfg.byte_order = SPI_BYTE_MSB;
#endif
/* spi init */
st7789v_spi = bflb_device_get_by_name(ST7789V_SPI_NAME);
bflb_spi_init(st7789v_spi, &spi_cfg);
/* spi enabled continuous mode */
bflb_spi_feature_control(st7789v_spi, SPI_CMD_SET_CS_INTERVAL, true);
#if (ST7789V_SPI_ID == 0)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI0_TX;
#elif (ST7789V_SPI_ID == 1)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI1_TX;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#endif
/* dma init */
st7789v_dma_spi_tx = bflb_device_get_by_name(ST7789V_SPI_DMA_NAME);
bflb_dma_channel_init(st7789v_dma_spi_tx, &dma_spi_tx_cfg);
/* dma int cfg */
bflb_dma_channel_irq_attach(st7789v_dma_spi_tx, st7789v_spi_dma_flush_callback, NULL);
return 0;
}
/**
* @brief st7789v_spi_write_cmd
*
* @param cmd
* @return int 0:succes 1:error
*/
static int st7789v_spi_write_cmd(uint8_t cmd)
{
ST7789V_SPI_DC_LOW;
ST7789V_SPI_CS_LOW;
bflb_spi_poll_send(st7789v_spi, cmd);
ST7789V_SPI_CS_HIGH;
ST7789V_SPI_DC_HIGH;
return 0;
}
/**
* @brief st7789v_spi_write_data_byte
*
* @param data
* @return int 0:succes 1:error
*/
static int st7789v_spi_write_data_byte(uint8_t data)
{
ST7789V_SPI_CS_LOW;
bflb_spi_poll_send(st7789v_spi, data);
ST7789V_SPI_CS_HIGH;
return 0;
lcd_spi_async_callback_register(callback);
}
/**
@ -225,23 +96,7 @@ static int st7789v_spi_write_data_byte(uint8_t data)
*/
int st7789v_spi_draw_is_busy(void)
{
if (bflb_dma_channel_isbusy(st7789v_dma_spi_tx)) {
return 1;
} else {
/* Wait for the SPI bus to be idle */
while (bflb_spi_isbusy(st7789v_spi)) {
__ASM volatile("nop");
};
/* Switch the SPI to non-DMA mode */
bflb_spi_link_txdma(st7789v_spi, false);
/* clear rx fifo */
bflb_spi_feature_control(st7789v_spi, SPI_CMD_CLEAR_RX_FIFO, 0);
/* */
ST7789V_SPI_CS_HIGH;
/* 8-bit data */
bflb_spi_feature_control(st7789v_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_8BIT);
return 0;
}
return lcd_spi_isbusy();
}
/**
@ -251,48 +106,19 @@ int st7789v_spi_draw_is_busy(void)
*/
int st7789v_spi_init()
{
int res = st7789v_spi_peripheral_init();
if (res < 0) {
return res;
}
lcd_spi_init(&spi_para);
for (uint16_t i = 0; i < (sizeof(st7789v_spi_init_cmds) / sizeof(st7789v_spi_init_cmd_t)); i++) {
if (st7789v_spi_init_cmds[i].cmd == 0xFF && st7789v_spi_init_cmds[i].data == NULL) {
for (uint16_t i = 0; i < (sizeof(st7789v_spi_init_cmds) / sizeof(st7789v_spi_init_cmds[0])); i++) {
if (st7789v_spi_init_cmds[i].cmd == 0xFF && st7789v_spi_init_cmds[i].data == NULL && st7789v_spi_init_cmds[i].databytes) {
bflb_mtimer_delay_ms(st7789v_spi_init_cmds[i].databytes);
} else {
/* send register address */
st7789v_spi_write_cmd(st7789v_spi_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (st7789v_spi_init_cmds[i].databytes); j++) {
st7789v_spi_write_data_byte(st7789v_spi_init_cmds[i].data[j]);
lcd_spi_transmit_cmd_para(st7789v_spi_init_cmds[i].cmd, (void *)(st7789v_spi_init_cmds[i].data), st7789v_spi_init_cmds[i].databytes);
}
}
}
st7789v_spi_set_draw_window(0, 0, ST7789V_SPI_H, ST7789V_SPI_W);
return res;
}
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
/**
* @brief lcd_swap_color_data16
*
* @param dst destination
* @param src source
* @param color_num color num
* @return int
*/
static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_num)
{
for (size_t i = 0; i < color_num; i++) {
dst[i] = (src[i] << 8) | (src[i] >> 8);
}
return 0;
}
#endif
/**
* @brief
*
@ -302,6 +128,7 @@ static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_nu
int st7789v_spi_set_dir(uint8_t dir, uint8_t mir_flag)
{
uint8_t param;
switch (dir) {
case 0:
if (!mir_flag)
@ -332,8 +159,9 @@ int st7789v_spi_set_dir(uint8_t dir, uint8_t mir_flag)
return -1;
break;
}
st7789v_spi_write_cmd(0x36);
st7789v_spi_write_data_byte(param);
lcd_spi_transmit_cmd_para(0x36, (void *)&param, 1);
return dir;
}
@ -345,7 +173,7 @@ int st7789v_spi_set_dir(uint8_t dir, uint8_t mir_flag)
* @param x2
* @param y2
*/
void st7789v_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
void st7789v_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
#if ST7789V_SPI_OFFSET_X
x1 += ST7789V_SPI_OFFSET_X;
@ -356,19 +184,21 @@ void st7789v_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t
y2 += ST7789V_SPI_OFFSET_Y;
#endif
st7789v_spi_write_cmd(0x2a);
st7789v_spi_write_data_byte(x1 >> 8);
st7789v_spi_write_data_byte(x1);
st7789v_spi_write_data_byte(x2 >> 8);
st7789v_spi_write_data_byte(x2);
int8_t param[4];
st7789v_spi_write_cmd(0x2b);
st7789v_spi_write_data_byte(y1 >> 8);
st7789v_spi_write_data_byte(y1);
st7789v_spi_write_data_byte(y2 >> 8);
st7789v_spi_write_data_byte(y2);
param[0] = (x1 >> 8) & 0xFF;
param[1] = x1 & 0xFF;
param[2] = (x2 >> 8) & 0xFF;
param[3] = x2 & 0xFF;
st7789v_spi_write_cmd(0x2c);
lcd_spi_transmit_cmd_para(0x2A, (void *)param, 4);
param[0] = (y1 >> 8) & 0xFF;
param[1] = y1 & 0xFF;
param[2] = (y2 >> 8) & 0xFF;
param[3] = y2 & 0xFF;
lcd_spi_transmit_cmd_para(0x2B, (void *)param, 4);
}
/**
@ -380,16 +210,10 @@ void st7789v_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t
*/
void st7789v_spi_draw_point(uint16_t x, uint16_t y, st7789v_spi_color_t color)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
color = ((color >> 8) & 0xFF) | color << 8;
#endif
/* set window */
st7789v_spi_set_draw_window(x, y, x, y);
ST7789V_SPI_DC_HIGH;
ST7789V_SPI_CS_LOW;
bflb_spi_poll_send(st7789v_spi, color & 0x00ff);
bflb_spi_poll_send(st7789v_spi, (color >> 8) & 0x00ff);
ST7789V_SPI_CS_HIGH;
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)&color, 1);
}
/**
@ -403,57 +227,12 @@ void st7789v_spi_draw_point(uint16_t x, uint16_t y, st7789v_spi_color_t color)
*/
void st7789v_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7789v_spi_color_t color)
{
uint32_t pixelDataSize, PixelCount = (x2 - x1 + 1) * (y2 - y1 + 1);
uint32_t __attribute__((aligned(64))) color_src;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
color_src = color;
#else
color_src = ((color >> 8) & 0xFF) | color << 8;
#endif
/* clean cache */
bflb_l1c_dcache_clean_range((void *)&color_src, sizeof(color_src));
uint32_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
st7789v_spi_set_draw_window(x1, y1, x2, y2);
/* get pixel Data Size */
pixelDataSize = PixelCount * 2;
/* spi 16-bit mode */
bflb_spi_feature_control(st7789v_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* enable spi dma mode */
bflb_spi_link_txdma(st7789v_spi, true);
ST7789V_SPI_CS_LOW;
/* sync mode flag, temporary shutdown interrupt */
st7789v_spi_sync_flush_flag = true;
/* disable dma src_addr_inc */
bflb_dma_feature_control(st7789v_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, false);
/* cfg and start dma */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)&color_src;
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI1_TDR;
#else
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
#endif
dma_tx_transfers[0].nbytes = pixelDataSize;
bflb_dma_channel_lli_reload(st7789v_dma_spi_tx, dam_tx_llipool, ST7789V_DMA_LLI_NUM, dma_tx_transfers, 1);
bflb_dma_channel_start(st7789v_dma_spi_tx);
/* Wait to finish, and cs high */
while (st7789v_spi_draw_is_busy()) {
__ASM volatile("nop");
};
/* enable src_addr_inc */
bflb_dma_feature_control(st7789v_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, true);
lcd_spi_transmit_cmd_pixel_fill_sync(0x2C, (uint32_t)color, pixel_cnt);
}
/**
@ -468,31 +247,12 @@ void st7789v_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, s
*/
void st7789v_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7789v_spi_color_t *picture)
{
size_t picture_size = (x2 - x1 + 1) * (y2 - y1 + 1);
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
st7789v_spi_set_draw_window(x1, y1, x2, y2);
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
lcd_swap_color_data16(picture, picture, picture_size);
#endif
/* clean dcache */
bflb_l1c_dcache_clean_range((void *)(picture), (picture_size * 2));
/* spi 16-bit data mode */
bflb_spi_feature_control(st7789v_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* spi dma mode enable */
bflb_spi_link_txdma(st7789v_spi, true);
ST7789V_SPI_CS_LOW;
/* dma cfg and start */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)picture;
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
dma_tx_transfers[0].nbytes = picture_size * 2;
bflb_dma_channel_lli_reload(st7789v_dma_spi_tx, dam_tx_llipool, sizeof(dam_tx_llipool) / sizeof(dam_tx_llipool[0]), dma_tx_transfers, 1);
bflb_dma_channel_start(st7789v_dma_spi_tx);
lcd_spi_transmit_cmd_pixel_async(0x2C, (void *)picture, pixel_cnt);
}
/**
@ -506,13 +266,12 @@ void st7789v_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2,
*/
void st7789v_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7789v_spi_color_t *picture)
{
/* sync mode, temporary shutdown interrupt */
st7789v_spi_sync_flush_flag = true;
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
st7789v_spi_draw_picture_nonblocking(x1, y1, x2, y2, picture);
while (st7789v_spi_draw_is_busy()) {
__ASM volatile("nop");
};
/* set window */
st7789v_spi_set_draw_window(x1, y1, x2, y2);
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)picture, pixel_cnt);
}
#endif

View file

@ -24,21 +24,11 @@
#ifndef _ST7789V_SPI_H_
#define _ST7789V_SPI_H_
#include "bflb_core.h"
#include "../lcd_conf.h"
#define ST7789V_SPI_CS_PIN GPIO_PIN_12
#define ST7789V_SPI_DC_PIN GPIO_PIN_13
#if defined LCD_SPI_ST7789V
#define ST7789V_SPI_CS_HIGH bflb_gpio_set(st7789v_gpio, ST7789V_SPI_CS_PIN)
#define ST7789V_SPI_CS_LOW bflb_gpio_reset(st7789v_gpio, ST7789V_SPI_CS_PIN)
#define ST7789V_SPI_DC_HIGH bflb_gpio_set(st7789v_gpio, ST7789V_SPI_DC_PIN)
#define ST7789V_SPI_DC_LOW bflb_gpio_reset(st7789v_gpio, ST7789V_SPI_DC_PIN)
#define ST7789V_SPI_W 240 /* ST7789V LCD width */
#define ST7789V_SPI_H 280 /* ST7789V LCD height */
#define ST7789V_SPI_OFFSET_X 0
#define ST7789V_SPI_OFFSET_Y 20
/* Do not modify the following */
#define ST7789V_SPI_COLOR_DEPTH 16
@ -51,9 +41,10 @@ typedef struct {
typedef uint16_t st7789v_spi_color_t;
int st7789v_spi_init();
void st7789v_spi_async_callback_enable(bool enable);
void st7789v_spi_async_callback_register(void (*callback)(void));
int st7789v_spi_set_dir(uint8_t dir, uint8_t mir_flag);
void st7789v_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2);
void st7789v_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void st7789v_spi_draw_point(uint16_t x, uint16_t y, st7789v_spi_color_t color);
void st7789v_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7789v_spi_color_t color);
void st7789v_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7789v_spi_color_t *picture);
@ -61,3 +52,4 @@ void st7789v_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, ui
int st7789v_spi_draw_is_busy(void);
#endif
#endif

View file

@ -25,38 +25,35 @@
#if defined(LCD_SPI_ST7796)
#include "bflb_mtimer.h"
#include "bflb_spi.h"
#include "bflb_dma.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#include "st7796_spi.h"
#if (LCD_SPI_INTERFACE_TYPE == 1)
#include "bl_spi_hard_4.h"
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
#define ST7796_SPI_ID 1
#define ST7796_SPI_NAME "spi1"
#define ST7796_SPI_DMA_NAME "dma2_ch0"
#else
#define ST7796_SPI_ID 0
#define ST7796_SPI_NAME "spi0"
#define ST7796_SPI_DMA_NAME "dma0_ch3"
#define lcd_spi_init lcd_spi_hard_4_init
#define lcd_spi_isbusy lcd_spi_hard_4_is_busy
#define lcd_spi_transmit_cmd_para lcd_spi_hard_4_transmit_cmd_para
#define lcd_spi_transmit_cmd_pixel_sync lcd_spi_hard_4_transmit_cmd_pixel_sync
#define lcd_spi_transmit_cmd_pixel_fill_sync lcd_spi_hard_4_transmit_cmd_pixel_fill_sync
#define lcd_spi_sync_callback_enable lcd_spi_hard_4_async_callback_enable
#define lcd_spi_async_callback_register lcd_spi_hard_4_async_callback_register
#define lcd_spi_transmit_cmd_pixel_async lcd_spi_hard_4_transmit_cmd_pixel_async
#define lcd_spi_transmit_cmd_pixel_fill_async lcd_spi_hard_4_transmit_cmd_pixel_fill_async
static lcd_spi_hard_4_init_t spi_para = {
.clock_freq = 40 * 1000 * 1000,
#if (ST7796_SPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_RGB565,
#elif (ST7796_SPI_PIXEL_FORMAT == 2)
.pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_NRGB8888,
#endif
};
#define ST7796_DMA_LLI_NUM (ST7796_SPI_W * ST7796_SPI_H / 4064 + 1)
#else
/* asynchronous flush interrupt callback */
typedef void (*st7796_spi_callback)(void);
static volatile st7796_spi_callback st7796_spi_async_callback = NULL;
static volatile bool st7796_spi_sync_flush_flag = 0;
static struct bflb_device_s *st7796_gpio;
static struct bflb_device_s *st7796_spi;
static struct bflb_device_s *st7796_dma_spi_tx;
/* The memory space of DMA */
static struct bflb_dma_channel_lli_pool_s dam_tx_llipool[ST7796_DMA_LLI_NUM];
static struct bflb_dma_channel_lli_transfer_s dma_tx_transfers[1];
#error "Configuration error"
#endif
const st7796_spi_init_cmd_t st7796_spi_init_cmds[] = {
{ 0x01, NULL, 0 },
{ 0xFF, NULL, 10 },
@ -72,8 +69,8 @@ const st7796_spi_init_cmd_t st7796_spi_init_cmds[] = {
{ 0xE6, "\x0F\xF2\x3F\x4F\x4F\x28\x0E\x00", 8 },
{ 0xC5, "\x2A", 1 },
/* Display Inversion */
#if 0
/* Color reversal */
#if ST7796_SPI_COLOR_REVERSAL
{ 0xB4, "\x01", 1 },
{ 0x21, NULL, 0 },
#endif
@ -89,23 +86,13 @@ const st7796_spi_init_cmd_t st7796_spi_init_cmds[] = {
};
/**
* @brief st7796_spi_dma_flush_callback
* @brief st7796_spi_async_callback_enable
*
* @return
*/
void st7796_spi_dma_flush_callback(void *args)
void st7796_spi_async_callback_enable(bool enable)
{
if (st7796_spi_sync_flush_flag == true) {
st7796_spi_sync_flush_flag = false;
return;
}
while (lcd_draw_is_busy()) {
};
if (st7796_spi_async_callback != NULL) {
st7796_spi_async_callback();
}
lcd_spi_sync_callback_enable(enable);
}
/**
@ -115,123 +102,7 @@ void st7796_spi_dma_flush_callback(void *args)
*/
void st7796_spi_async_callback_register(void (*callback)(void))
{
st7796_spi_async_callback = callback;
}
/**
* @brief st7796_spi_init
*
* @return int 0:succes 1:error
*/
static int st7796_spi_peripheral_init(void)
{
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = 40 * 1000 * 1000,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* dma */
struct bflb_dma_channel_config_s dma_spi_tx_cfg = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_SPI0_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR1,
.dst_burst_count = DMA_BURST_INCR1,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT,
};
/* CS and DC pin init */
st7796_gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(st7796_gpio, ST7796_SPI_CS_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(st7796_gpio, ST7796_SPI_DC_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
ST7796_SPI_CS_HIGH;
ST7796_SPI_DC_HIGH;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 2 * 4 - 1;
spi_cfg.rx_fifo_threshold = 2 * 4 - 1;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = 4 - 1;
spi_cfg.rx_fifo_threshold = 4 - 1;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
spi_cfg.byte_order = SPI_BYTE_MSB;
#endif
/* spi init */
st7796_spi = bflb_device_get_by_name(ST7796_SPI_NAME);
bflb_spi_init(st7796_spi, &spi_cfg);
/* spi enabled continuous mode */
bflb_spi_feature_control(st7796_spi, SPI_CMD_SET_CS_INTERVAL, true);
#if (ST7796_SPI_ID == 0)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI0_TX;
#elif (ST7796_SPI_ID == 1)
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI1_TX;
#endif
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_BYTE_NUM_MAX > (2 * 4))
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#elif (!SPI_FIFO_WIDTH_VARIABLE_SUPPORT) && (SPI_FIFO_WORD_NUM_MAX > 4)
/* DMA support burst*4 */
dma_spi_tx_cfg.src_burst_count = DMA_BURST_INCR4;
dma_spi_tx_cfg.dst_burst_count = DMA_BURST_INCR4;
#endif
/* dma init */
st7796_dma_spi_tx = bflb_device_get_by_name(ST7796_SPI_DMA_NAME);
bflb_dma_channel_init(st7796_dma_spi_tx, &dma_spi_tx_cfg);
/* dma int cfg */
bflb_dma_channel_irq_attach(st7796_dma_spi_tx, st7796_spi_dma_flush_callback, NULL);
return 0;
}
/**
* @brief st7796_spi_write_cmd
*
* @param cmd
* @return int 0:succes 1:error
*/
static int st7796_spi_write_cmd(uint8_t cmd)
{
ST7796_SPI_DC_LOW;
ST7796_SPI_CS_LOW;
bflb_spi_poll_send(st7796_spi, cmd);
ST7796_SPI_CS_HIGH;
ST7796_SPI_DC_HIGH;
return 0;
}
/**
* @brief st7796_spi_write_data_byte
*
* @param data
* @return int 0:succes 1:error
*/
static int st7796_spi_write_data_byte(uint8_t data)
{
ST7796_SPI_CS_LOW;
bflb_spi_poll_send(st7796_spi, data);
ST7796_SPI_CS_HIGH;
return 0;
lcd_spi_async_callback_register(callback);
}
/**
@ -243,23 +114,7 @@ static int st7796_spi_write_data_byte(uint8_t data)
*/
int st7796_spi_draw_is_busy(void)
{
if (bflb_dma_channel_isbusy(st7796_dma_spi_tx)) {
return 1;
} else {
/* Wait for the SPI bus to be idle */
while (bflb_spi_isbusy(st7796_spi)) {
__ASM volatile("nop");
};
/* Switch the SPI to non-DMA mode */
bflb_spi_link_txdma(st7796_spi, false);
/* clear rx fifo */
bflb_spi_feature_control(st7796_spi, SPI_CMD_CLEAR_RX_FIFO, 0);
/* */
ST7796_SPI_CS_HIGH;
/* 8-bit data */
bflb_spi_feature_control(st7796_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_8BIT);
return 0;
}
return lcd_spi_isbusy();
}
/**
@ -269,48 +124,19 @@ int st7796_spi_draw_is_busy(void)
*/
int st7796_spi_init()
{
int res = st7796_spi_peripheral_init();
if (res < 0) {
return res;
}
lcd_spi_init(&spi_para);
for (uint16_t i = 0; i < (sizeof(st7796_spi_init_cmds) / sizeof(st7796_spi_init_cmd_t)); i++) {
if (st7796_spi_init_cmds[i].cmd == 0xFF && st7796_spi_init_cmds[i].data == NULL) {
for (uint16_t i = 0; i < (sizeof(st7796_spi_init_cmds) / sizeof(st7796_spi_init_cmds[0])); i++) {
if (st7796_spi_init_cmds[i].cmd == 0xFF && st7796_spi_init_cmds[i].data == NULL && st7796_spi_init_cmds[i].databytes) {
bflb_mtimer_delay_ms(st7796_spi_init_cmds[i].databytes);
} else {
/* send register address */
st7796_spi_write_cmd(st7796_spi_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (st7796_spi_init_cmds[i].databytes); j++) {
st7796_spi_write_data_byte(st7796_spi_init_cmds[i].data[j]);
lcd_spi_transmit_cmd_para(st7796_spi_init_cmds[i].cmd, (void *)(st7796_spi_init_cmds[i].data), st7796_spi_init_cmds[i].databytes);
}
}
}
st7796_spi_set_draw_window(0, 0, ST7796_SPI_H, ST7796_SPI_W);
return res;
}
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
/**
* @brief lcd_swap_color_data16
*
* @param dst destination
* @param src source
* @param color_num color num
* @return int
*/
static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_num)
{
for (size_t i = 0; i < color_num; i++) {
dst[i] = (src[i] << 8) | (src[i] >> 8);
}
return 0;
}
#endif
/**
* @brief
*
@ -320,6 +146,7 @@ static int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, uint32_t color_nu
int st7796_spi_set_dir(uint8_t dir, uint8_t mir_flag)
{
uint8_t param;
switch (dir) {
case 0:
if (!mir_flag)
@ -350,8 +177,9 @@ int st7796_spi_set_dir(uint8_t dir, uint8_t mir_flag)
return -1;
break;
}
st7796_spi_write_cmd(0x36);
st7796_spi_write_data_byte(param);
lcd_spi_transmit_cmd_para(0x36, (void *)&param, 1);
return dir;
}
@ -363,7 +191,7 @@ int st7796_spi_set_dir(uint8_t dir, uint8_t mir_flag)
* @param x2
* @param y2
*/
void st7796_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
void st7796_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
#if ST7796_SPI_OFFSET_X
x1 += ST7796_SPI_OFFSET_X;
@ -374,19 +202,21 @@ void st7796_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t
y2 += ST7796_SPI_OFFSET_Y;
#endif
st7796_spi_write_cmd(0x2a);
st7796_spi_write_data_byte(x1 >> 8);
st7796_spi_write_data_byte(x1);
st7796_spi_write_data_byte(x2 >> 8);
st7796_spi_write_data_byte(x2);
int8_t param[4];
st7796_spi_write_cmd(0x2b);
st7796_spi_write_data_byte(y1 >> 8);
st7796_spi_write_data_byte(y1);
st7796_spi_write_data_byte(y2 >> 8);
st7796_spi_write_data_byte(y2);
param[0] = (x1 >> 8) & 0xFF;
param[1] = x1 & 0xFF;
param[2] = (x2 >> 8) & 0xFF;
param[3] = x2 & 0xFF;
st7796_spi_write_cmd(0x2c);
lcd_spi_transmit_cmd_para(0x2A, (void *)param, 4);
param[0] = (y1 >> 8) & 0xFF;
param[1] = y1 & 0xFF;
param[2] = (y2 >> 8) & 0xFF;
param[3] = y2 & 0xFF;
lcd_spi_transmit_cmd_para(0x2B, (void *)param, 4);
}
/**
@ -398,16 +228,10 @@ void st7796_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t
*/
void st7796_spi_draw_point(uint16_t x, uint16_t y, st7796_spi_color_t color)
{
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
color = ((color >> 8) & 0xFF) | color << 8;
#endif
/* set window */
st7796_spi_set_draw_window(x, y, x, y);
ST7796_SPI_DC_HIGH;
ST7796_SPI_CS_LOW;
bflb_spi_poll_send(st7796_spi, color & 0x00ff);
bflb_spi_poll_send(st7796_spi, (color >> 8) & 0x00ff);
ST7796_SPI_CS_HIGH;
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)&color, 1);
}
/**
@ -421,57 +245,12 @@ void st7796_spi_draw_point(uint16_t x, uint16_t y, st7796_spi_color_t color)
*/
void st7796_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7796_spi_color_t color)
{
uint32_t pixelDataSize, PixelCount = (x2 - x1 + 1) * (y2 - y1 + 1);
uint32_t __attribute__((aligned(64))) color_src;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
color_src = color;
#else
color_src = ((color >> 8) & 0xFF) | color << 8;
#endif
/* clean cache */
bflb_l1c_dcache_clean_range((void *)&color_src, sizeof(color_src));
uint32_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
st7796_spi_set_draw_window(x1, y1, x2, y2);
/* get pixel Data Size */
pixelDataSize = PixelCount * 2;
/* spi 16-bit mode */
bflb_spi_feature_control(st7796_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* enable spi dma mode */
bflb_spi_link_txdma(st7796_spi, true);
ST7796_SPI_CS_LOW;
/* sync mode flag, temporary shutdown interrupt */
st7796_spi_sync_flush_flag = true;
/* disable dma src_addr_inc */
bflb_dma_feature_control(st7796_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, false);
/* cfg and start dma */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)&color_src;
#if (defined(BL808) || defined(BL606P)) && defined(CPU_D0)
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI1_TDR;
#else
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
#endif
dma_tx_transfers[0].nbytes = pixelDataSize;
bflb_dma_channel_lli_reload(st7796_dma_spi_tx, dam_tx_llipool, ST7796_DMA_LLI_NUM, dma_tx_transfers, 1);
bflb_dma_channel_start(st7796_dma_spi_tx);
/* Wait to finish, and cs high */
while (st7796_spi_draw_is_busy()) {
__ASM volatile("nop");
};
/* enable src_addr_inc */
bflb_dma_feature_control(st7796_dma_spi_tx, DMA_CMD_SET_SRCADDR_INCREMENT, true);
lcd_spi_transmit_cmd_pixel_fill_sync(0x2C, (uint32_t)color, pixel_cnt);
}
/**
@ -486,31 +265,12 @@ void st7796_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st
*/
void st7796_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7796_spi_color_t *picture)
{
size_t picture_size = (x2 - x1 + 1) * (y2 - y1 + 1);
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
/* set window */
st7796_spi_set_draw_window(x1, y1, x2, y2);
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT == 0)
lcd_swap_color_data16(picture, picture, picture_size);
#endif
/* clean dcache */
bflb_l1c_dcache_clean_range((void *)(picture), (picture_size * 2));
/* spi 16-bit data mode */
bflb_spi_feature_control(st7796_spi, SPI_CMD_SET_DATA_WIDTH, SPI_DATA_WIDTH_16BIT);
/* spi dma mode enable */
bflb_spi_link_txdma(st7796_spi, true);
ST7796_SPI_CS_LOW;
/* dma cfg and start */
dma_tx_transfers[0].src_addr = (uint32_t)(uintptr_t)picture;
dma_tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_SPI0_TDR;
dma_tx_transfers[0].nbytes = picture_size * 2;
bflb_dma_channel_lli_reload(st7796_dma_spi_tx, dam_tx_llipool, sizeof(dam_tx_llipool) / sizeof(dam_tx_llipool[0]), dma_tx_transfers, 1);
bflb_dma_channel_start(st7796_dma_spi_tx);
lcd_spi_transmit_cmd_pixel_async(0x2C, (void *)picture, pixel_cnt);
}
/**
@ -524,13 +284,12 @@ void st7796_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2,
*/
void st7796_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7796_spi_color_t *picture)
{
/* sync mode, temporary shutdown interrupt */
st7796_spi_sync_flush_flag = true;
size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
st7796_spi_draw_picture_nonblocking(x1, y1, x2, y2, picture);
while (st7796_spi_draw_is_busy()) {
__ASM volatile("nop");
};
/* set window */
st7796_spi_set_draw_window(x1, y1, x2, y2);
lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)picture, pixel_cnt);
}
#endif

View file

@ -24,21 +24,11 @@
#ifndef _ST7796_SPI_H_
#define _ST7796_SPI_H_
#include "bflb_core.h"
#include "../lcd_conf.h"
#define ST7796_SPI_CS_PIN GPIO_PIN_16
#define ST7796_SPI_DC_PIN GPIO_PIN_18
#if defined LCD_SPI_ST7796
#define ST7796_SPI_CS_HIGH bflb_gpio_set(st7796_gpio, ST7796_SPI_CS_PIN)
#define ST7796_SPI_CS_LOW bflb_gpio_reset(st7796_gpio, ST7796_SPI_CS_PIN)
#define ST7796_SPI_DC_HIGH bflb_gpio_set(st7796_gpio, ST7796_SPI_DC_PIN)
#define ST7796_SPI_DC_LOW bflb_gpio_reset(st7796_gpio, ST7796_SPI_DC_PIN)
#define ST7796_SPI_W 320 /* ST7796 LCD width */
#define ST7796_SPI_H 480 /* ST7796 LCD height */
#define ST7796_SPI_OFFSET_X 0
#define ST7796_SPI_OFFSET_Y 0
/* Do not modify the following */
#define ST7796_SPI_COLOR_DEPTH 16
@ -51,9 +41,10 @@ typedef struct {
typedef uint16_t st7796_spi_color_t;
int st7796_spi_init();
void st7796_spi_async_callback_enable(bool enable);
void st7796_spi_async_callback_register(void (*callback)(void));
int st7796_spi_set_dir(uint8_t dir, uint8_t mir_flag);
void st7796_spi_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2);
void st7796_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void st7796_spi_draw_point(uint16_t x, uint16_t y, st7796_spi_color_t color);
void st7796_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7796_spi_color_t color);
void st7796_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7796_spi_color_t *picture);
@ -61,3 +52,4 @@ void st7796_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uin
int st7796_spi_draw_is_busy(void);
#endif
#endif

View file

@ -232,6 +232,11 @@ void SDH_CMDTransferFinished_CallBack(SDH_Handle_Cfg_Type *handle, SDH_Stat_Type
}
}
extern void SDH_MMC1_IRQHandler(void);
static void sdh_isr(int irq, void *arg)
{
SDH_MMC1_IRQHandler();
}
/****************************************************************************/ /**
* @brief SDH INT init
*
@ -242,6 +247,9 @@ void SDH_CMDTransferFinished_CallBack(SDH_Handle_Cfg_Type *handle, SDH_Stat_Type
*******************************************************************************/
static void SDH_INT_Init(void)
{
bflb_irq_attach(33, sdh_isr, NULL);
bflb_irq_enable(33);
SDH_EnableIntStatus(SDH_INT_ALL);
SDH_DisableIntSource(SDH_INT_ALL);
SDH_Trans_Callback_Cfg_TypeInstance.SDH_CallBack_TransferFinished = SDH_DataTransferFinished_CallBack;

View file

@ -24,6 +24,7 @@ function(sdk_library_add_sources)
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
endif()
target_sources(${CURRENT_STATIC_LIBRARY} PRIVATE ${path})
endforeach()
endfunction()
@ -41,6 +42,7 @@ function(sdk_add_include_directories)
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
endif()
target_include_directories(sdk_intf_lib INTERFACE ${path})
endforeach()
endfunction()
@ -52,10 +54,23 @@ function(sdk_add_private_include_directories)
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
endif()
target_include_directories(${CURRENT_STATIC_LIBRARY} PRIVATE ${path})
endforeach()
endfunction()
function(sdk_add_system_include_directories)
foreach(arg ${ARGV})
if(IS_ABSOLUTE ${arg})
set(path ${arg})
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
endif()
target_include_directories(sdk_intf_lib SYSTEM INTERFACE ${path})
endforeach()
endfunction()
function(sdk_add_include_directories_ifdef feature)
if(${${feature}})
sdk_add_include_directories(${ARGN})
@ -68,6 +83,12 @@ function(sdk_add_private_include_directories_ifdef feature)
endif()
endfunction()
function(sdk_add_system_include_directories_ifdef feature)
if(${${feature}})
sdk_add_system_include_directories(${ARGN})
endif()
endfunction()
function(sdk_add_compile_definitions)
target_compile_definitions(sdk_intf_lib INTERFACE ${ARGV})
endfunction()
@ -155,6 +176,7 @@ function(sdk_add_static_library)
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
endif()
get_filename_component(library_name ${path} NAME_WE)
message(STATUS "[register extern library : ${library_name}], path:${CMAKE_CURRENT_LIST_DIR}")
set_property(GLOBAL APPEND PROPERTY SDK_LIBS ${path})
@ -179,6 +201,7 @@ function(sdk_set_linker_script ld)
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${ld})
endif()
set_property(GLOBAL PROPERTY LINKER_SCRIPT ${path})
endfunction()
@ -196,11 +219,11 @@ macro(sdk_set_main_file)
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${ARGV0})
endif()
set(CURRENT_MAIN_FILE ${path})
endmacro()
macro(project name)
if(CPU_ID)
set(proj_name ${name}_${CHIP}_${CPU_ID})
else()
@ -217,18 +240,20 @@ macro(project name)
add_executable(${proj_name}.elf ${CURRENT_MAIN_FILE})
target_link_libraries(${proj_name}.elf sdk_intf_lib)
get_property(LINKER_SCRIPT_PROPERTY GLOBAL PROPERTY LINKER_SCRIPT)
if(EXISTS ${LINKER_SCRIPT_PROPERTY})
set_target_properties(${proj_name}.elf PROPERTIES LINK_FLAGS "-T${LINKER_SCRIPT_PROPERTY} -Wl,-Map=${MAP_FILE}")
set_target_properties(${proj_name}.elf PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT_PROPERTY})
endif()
get_property(SDK_LIBS_PROPERTY GLOBAL PROPERTY SDK_LIBS)
target_link_libraries(${proj_name}.elf -Wl,--start-group ${SDK_LIBS_PROPERTY} app -Wl,--end-group)
target_link_libraries(${proj_name}.elf -Wl,--whole-archive ${SDK_LIBS_PROPERTY} app -Wl,--no-whole-archive)
if(OUTPUT_DIR)
add_custom_command(TARGET ${proj_name}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${proj_name}.elf> ${BIN_FILE}
COMMAND ${CMAKE_OBJDUMP} -d -S $<TARGET_FILE:${proj_name}.elf> >${ASM_FILE}
# COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${proj_name}.elf> ${HEX_FILE}
# COMMAND ${SIZE} $<TARGET_FILE:${proj_name}.elf>
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${proj_name}.elf> ${OUTPUT_DIR}/${name}/${proj_name}.elf
@ -243,12 +268,13 @@ macro(project name)
add_custom_command(TARGET ${proj_name}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${proj_name}.elf> ${BIN_FILE}
COMMAND ${CMAKE_OBJDUMP} -d -S $<TARGET_FILE:${proj_name}.elf> >${ASM_FILE}
# COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${proj_name}.elf> ${HEX_FILE}
# COMMAND ${SIZE} $<TARGET_FILE:${proj_name}.elf>
COMMENT "Generate ${BIN_FILE}\r\n"
)
endif()
# include(${BL_SDK_BASE}/cmake/bflb_flash.cmake)
# include(${BL_SDK_BASE}/cmake/gen_c_cpp_properties_json.cmake)
include(${BL_SDK_BASE}/cmake/bflb_flash.cmake)
include(${BL_SDK_BASE}/cmake/gen_c_cpp_properties_json.cmake)
endmacro()

View file

@ -1,4 +1,3 @@
add_subdirectory(ai)
sdk_add_subdirectory_ifdef(CONFIG_BFLOG bflog)
add_subdirectory(crypto)
add_subdirectory(fs)
@ -13,3 +12,4 @@ sdk_add_subdirectory_ifdef(CONFIG_SHELL shell)
add_subdirectory(usb)
add_subdirectory(utils)
add_subdirectory(wireless)
sdk_add_subdirectory_ifdef(CONFIG_HIBOOSTER hibooster)

View file

@ -150,13 +150,13 @@
#else
#define BFLOG_SIMPLE_LAYOUT_STRING(_color, _level, _tag, _tm, _msg) \
"%s" \
"[%c][%10lu]" \
"[%s:%s:%d]" \
"<%s> %s", \
"[%c:%10lu]" \
"[%s:%d]" \
"%10s> %s", \
(_color), \
(_level[0]), \
((_msg)->clkl), \
((_msg)->file), ((_msg)->func), ((_msg)->line), \
((_msg)->file), ((_msg)->line), \
(_tag), \
((_msg)->string)
#endif

View file

@ -1,18 +1,19 @@
sdk_generate_library()
sdk_generate_library()
sdk_library_add_sources(diskio.c)
sdk_library_add_sources(ff.c)
sdk_library_add_sources(ffsystem.c)
sdk_library_add_sources(ffunicode.c)
sdk_library_add_sources(diskio.c)
sdk_add_include_directories(.)
sdk_add_include_directories(port/.)
sdk_add_compile_definitions(-DCONFIG_FATFS)
if(CONFIG_FF_FS_REENTRANT)
sdk_add_compile_definitions(-DFF_FS_REENTRANT=${CONFIG_FF_FS_REENTRANT})
endif()
# fatfs use sdcard over sdio
if(CONFIG_FATFS_SDH_SDCARD)
sdk_add_compile_definitions(-DCONFIG_FATFS_SDH_SDCARD)
sdk_library_add_sources(port/fatfs_sdh_sdcard.c)
endif()
if(CONFIG_FATFS_FFCONF_USER)
sdk_add_compile_definitions(-DCONFIG_FATFS_FFCONF_USER)
endif()

View file

@ -11,78 +11,16 @@
#include "diskio.h" /* Declarations of disk functions */
#include "stddef.h"
/* Definitions of physical drive number for each drive */
#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_FLASH 2 /* Example: Map USB MSD to physical drive 2 */
#define DEV_USB 3 /* Example: Map USB MSD to physical drive 2 */
FATFS_DiskioDriverTypeDef pDiskioDriver = {
.RAM_disk_status = NULL,
.MMC_disk_status = NULL,
.USB_disk_status = NULL,
.RAM_disk_initialize = NULL,
.MMC_disk_initialize = NULL,
.USB_disk_initialize = NULL,
.RAM_disk_read = NULL,
.MMC_disk_read = NULL,
.USB_disk_read = NULL,
.RAM_disk_write = NULL,
.MMC_disk_write = NULL,
.USB_disk_write = NULL,
.RAM_disk_ioctl = NULL,
.MMC_disk_ioctl = NULL,
.USB_disk_ioctl = NULL,
.Translate_Result_Code = NULL,
};
FATFS_DiskioDriverTypeDef pDiskioDriver[DEV_NUM_MAX] = { NULL };
/*-----------------------------------------------------------------------*/
/* init driver callback */
/*-----------------------------------------------------------------------*/
void disk_driver_callback_init(FATFS_DiskioDriverTypeDef *pNewDriver)
void disk_driver_callback_init(uint8_t pdrv, FATFS_DiskioDriverTypeDef *pNewDriver)
{
if (pNewDriver->RAM_disk_status)
pDiskioDriver.RAM_disk_status = pNewDriver->RAM_disk_status;
if (pNewDriver->MMC_disk_status)
pDiskioDriver.MMC_disk_status = pNewDriver->MMC_disk_status;
if (pNewDriver->FLASH_disk_status)
pDiskioDriver.FLASH_disk_status = pNewDriver->FLASH_disk_status;
if (pNewDriver->USB_disk_status)
pDiskioDriver.USB_disk_status = pNewDriver->USB_disk_status;
if (pNewDriver->RAM_disk_initialize)
pDiskioDriver.RAM_disk_initialize = pNewDriver->RAM_disk_initialize;
if (pNewDriver->MMC_disk_initialize)
pDiskioDriver.MMC_disk_initialize = pNewDriver->MMC_disk_initialize;
if (pNewDriver->FLASH_disk_initialize)
pDiskioDriver.FLASH_disk_initialize = pNewDriver->FLASH_disk_initialize;
if (pNewDriver->USB_disk_initialize)
pDiskioDriver.USB_disk_initialize = pNewDriver->USB_disk_initialize;
if (pNewDriver->RAM_disk_read)
pDiskioDriver.RAM_disk_read = pNewDriver->RAM_disk_read;
if (pNewDriver->MMC_disk_read)
pDiskioDriver.MMC_disk_read = pNewDriver->MMC_disk_read;
if (pNewDriver->FLASH_disk_read)
pDiskioDriver.FLASH_disk_read = pNewDriver->FLASH_disk_read;
if (pNewDriver->USB_disk_read)
pDiskioDriver.USB_disk_read = pNewDriver->USB_disk_read;
if (pNewDriver->RAM_disk_write)
pDiskioDriver.RAM_disk_write = pNewDriver->RAM_disk_write;
if (pNewDriver->MMC_disk_write)
pDiskioDriver.MMC_disk_write = pNewDriver->MMC_disk_write;
if (pNewDriver->FLASH_disk_write)
pDiskioDriver.FLASH_disk_write = pNewDriver->FLASH_disk_write;
if (pNewDriver->USB_disk_write)
pDiskioDriver.USB_disk_write = pNewDriver->USB_disk_write;
if (pNewDriver->RAM_disk_ioctl)
pDiskioDriver.RAM_disk_ioctl = pNewDriver->RAM_disk_ioctl;
if (pNewDriver->MMC_disk_ioctl)
pDiskioDriver.MMC_disk_ioctl = pNewDriver->MMC_disk_ioctl;
if (pNewDriver->FLASH_disk_ioctl)
pDiskioDriver.FLASH_disk_ioctl = pNewDriver->FLASH_disk_ioctl;
if (pNewDriver->USB_disk_ioctl)
pDiskioDriver.USB_disk_ioctl = pNewDriver->USB_disk_ioctl;
if (pNewDriver->Translate_Result_Code)
pDiskioDriver.Translate_Result_Code = pNewDriver->Translate_Result_Code;
if (pdrv < DEV_NUM_MAX) {
pDiskioDriver[pdrv] = *pNewDriver;
}
}
/*-----------------------------------------------------------------------*/
@ -96,41 +34,19 @@ DSTATUS disk_status(
DSTATUS stat = STA_NOINIT;
int result = 0;
switch (pdrv) {
case DEV_RAM:
if (pDiskioDriver.RAM_disk_status) {
result = pDiskioDriver.RAM_disk_status();
}
break;
case DEV_MMC:
if (pDiskioDriver.MMC_disk_status) {
result = pDiskioDriver.MMC_disk_status();
}
break;
case DEV_FLASH:
if (pDiskioDriver.FLASH_disk_status) {
result = pDiskioDriver.FLASH_disk_status();
}
break;
case DEV_USB:
if (pDiskioDriver.USB_disk_status) {
result = pDiskioDriver.USB_disk_status();
}
break;
default:
if (pdrv > DEV_NUM_MAX) {
return STA_NOINIT;
}
if (pDiskioDriver[pdrv].disk_status) {
result = pDiskioDriver[pdrv].disk_status();
}
/* translate the reslut code here */
if (pDiskioDriver.Translate_Result_Code) {
stat = pDiskioDriver.Translate_Result_Code(result);
if (pDiskioDriver[pdrv].error_code_parsing) {
stat = pDiskioDriver[pdrv].error_code_parsing(result);
} else {
stat = result;
}
return stat;
@ -147,41 +63,19 @@ DSTATUS disk_initialize(
DSTATUS stat = STA_NOINIT;
int result = 0;
switch (pdrv) {
case DEV_RAM:
if (pDiskioDriver.RAM_disk_initialize) {
result = pDiskioDriver.RAM_disk_initialize();
}
break;
case DEV_MMC:
if (pDiskioDriver.MMC_disk_initialize) {
result = pDiskioDriver.MMC_disk_initialize();
}
break;
case DEV_FLASH:
if (pDiskioDriver.FLASH_disk_initialize) {
result = pDiskioDriver.FLASH_disk_initialize();
}
break;
case DEV_USB:
if (pDiskioDriver.USB_disk_initialize) {
result = pDiskioDriver.USB_disk_initialize();
}
break;
default:
if (pdrv > DEV_NUM_MAX) {
return STA_NOINIT;
}
if (pDiskioDriver[pdrv].disk_initialize) {
result = pDiskioDriver[pdrv].disk_initialize();
}
/* translate the reslut code here */
if (pDiskioDriver.Translate_Result_Code) {
stat = pDiskioDriver.Translate_Result_Code(result);
if (pDiskioDriver[pdrv].error_code_parsing) {
stat = pDiskioDriver[pdrv].error_code_parsing(result);
} else {
stat = result;
}
return stat;
@ -201,41 +95,19 @@ DRESULT disk_read(
DSTATUS stat = STA_NOINIT;
int result = 0;
switch (pdrv) {
case DEV_RAM:
if (pDiskioDriver.RAM_disk_read) {
result = pDiskioDriver.RAM_disk_read(buff, sector, count);
if (pdrv > DEV_NUM_MAX) {
return STA_NOINIT;
}
break;
case DEV_MMC:
if (pDiskioDriver.MMC_disk_read) {
result = pDiskioDriver.MMC_disk_read(buff, sector, count);
}
break;
case DEV_FLASH:
if (pDiskioDriver.FLASH_disk_read) {
result = pDiskioDriver.FLASH_disk_read(buff, sector, count);
}
break;
case DEV_USB:
if (pDiskioDriver.USB_disk_read) {
result = pDiskioDriver.USB_disk_read(buff, sector, count);
}
break;
default:
return RES_PARERR;
if (pDiskioDriver[pdrv].disk_read) {
result = pDiskioDriver[pdrv].disk_read(buff, sector, count);
}
/* translate the reslut code here */
if (pDiskioDriver.Translate_Result_Code) {
stat = pDiskioDriver.Translate_Result_Code(result);
if (pDiskioDriver[pdrv].error_code_parsing) {
stat = pDiskioDriver[pdrv].error_code_parsing(result);
} else {
stat = result;
}
return stat;
@ -257,41 +129,19 @@ DRESULT disk_write(
DSTATUS stat = STA_NOINIT;
int result = 0;
switch (pdrv) {
case DEV_RAM:
if (pDiskioDriver.RAM_disk_write) {
result = pDiskioDriver.RAM_disk_write(buff, sector, count);
if (pdrv > DEV_NUM_MAX) {
return STA_NOINIT;
}
break;
case DEV_MMC:
if (pDiskioDriver.MMC_disk_write) {
result = pDiskioDriver.MMC_disk_write(buff, sector, count);
}
break;
case DEV_FLASH:
if (pDiskioDriver.FLASH_disk_write) {
result = pDiskioDriver.FLASH_disk_write(buff, sector, count);
}
break;
case DEV_USB:
if (pDiskioDriver.USB_disk_write) {
result = pDiskioDriver.USB_disk_write(buff, sector, count);
}
break;
default:
return RES_PARERR;
if (pDiskioDriver[pdrv].disk_write) {
result = pDiskioDriver[pdrv].disk_write(buff, sector, count);
}
/* translate the reslut code here */
if (pDiskioDriver.Translate_Result_Code) {
stat = pDiskioDriver.Translate_Result_Code(result);
if (pDiskioDriver[pdrv].error_code_parsing) {
stat = pDiskioDriver[pdrv].error_code_parsing(result);
} else {
stat = result;
}
return stat;
@ -312,41 +162,19 @@ DRESULT disk_ioctl(
DSTATUS stat = STA_NOINIT;
int result = 0;
switch (pdrv) {
case DEV_RAM:
if (pDiskioDriver.RAM_disk_ioctl) {
result = pDiskioDriver.RAM_disk_ioctl(cmd, buff);
if (pdrv > DEV_NUM_MAX) {
return STA_NOINIT;
}
break;
case DEV_MMC:
if (pDiskioDriver.MMC_disk_ioctl) {
result = pDiskioDriver.MMC_disk_ioctl(cmd, buff);
}
break;
case DEV_FLASH:
if (pDiskioDriver.FLASH_disk_ioctl) {
result = pDiskioDriver.FLASH_disk_ioctl(cmd, buff);
}
break;
case DEV_USB:
if (pDiskioDriver.USB_disk_ioctl) {
result = pDiskioDriver.USB_disk_ioctl(cmd, buff);
}
break;
default:
return RES_PARERR;
if (pDiskioDriver[pdrv].disk_ioctl) {
result = pDiskioDriver[pdrv].disk_ioctl(cmd, buff);
}
/* translate the reslut code here */
if (pDiskioDriver.Translate_Result_Code) {
stat = pDiskioDriver.Translate_Result_Code(result);
if (pDiskioDriver[pdrv].error_code_parsing) {
stat = pDiskioDriver[pdrv].error_code_parsing(result);
} else {
stat = result;
}
return stat;

View file

@ -25,46 +25,31 @@ typedef enum {
} DRESULT;
/******************user code****************************/
/* Definitions of physical drive number for each drive
It must be in the same order as FF_VOLUME_STRS in ffconf.h */
#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_FLASH 1 /* Example: Map Flash to physical drive 1 */
#define DEV_SD 2 /* Example: Map MMC/SD card to physical drive 2 */
#define DEV_SD2 3
#define DEV_USB 4
#define DEV_NUM_MAX 5
typedef struct
{
/* get status */
int (*RAM_disk_status)(void);
int (*MMC_disk_status)(void);
int (*FLASH_disk_status)(void);
int (*USB_disk_status)(void);
/* init */
int (*RAM_disk_initialize)(void);
int (*MMC_disk_initialize)(void);
int (*FLASH_disk_initialize)(void);
int (*USB_disk_initialize)(void);
/* read */
int (*RAM_disk_read)(BYTE *buff, LBA_t sector, UINT count);
int (*MMC_disk_read)(BYTE *buff, LBA_t sector, UINT count);
int (*FLASH_disk_read)(BYTE *buff, LBA_t sector, UINT count);
int (*USB_disk_read)(BYTE *buff, LBA_t sector, UINT count);
/* write */
int (*RAM_disk_write)(const BYTE *buff, LBA_t sector, UINT count);
int (*MMC_disk_write)(const BYTE *buff, LBA_t sector, UINT count);
int (*FLASH_disk_write)(const BYTE *buff, LBA_t sector, UINT count);
int (*USB_disk_write)(const BYTE *buff, LBA_t sector, UINT count);
/* ioctl */
int (*RAM_disk_ioctl)(BYTE cmd, void *buff);
int (*MMC_disk_ioctl)(BYTE cmd, void *buff);
int (*FLASH_disk_ioctl)(BYTE cmd, void *buff);
int (*USB_disk_ioctl)(BYTE cmd, void *buff);
/* translate reslut code */
DSTATUS(*Translate_Result_Code)
int (*disk_status)(void);
int (*disk_initialize)(void);
int (*disk_read)(BYTE *buff, LBA_t sector, UINT count);
int (*disk_write)(const BYTE *buff, LBA_t sector, UINT count);
int (*disk_ioctl)(BYTE cmd, void *buff);
DSTATUS(*error_code_parsing)
(int result);
} FATFS_DiskioDriverTypeDef;
extern FATFS_DiskioDriverTypeDef pDiskioDriver;
extern FATFS_DiskioDriverTypeDef pDiskioDriver[];
void disk_driver_callback_init(FATFS_DiskioDriverTypeDef *pNewDriver);
void disk_driver_callback_init(uint8_t pdrv, FATFS_DiskioDriverTypeDef *pNewDriver);
/******************user code****************************/
/*---------------------------------------*/

View file

@ -1,22 +0,0 @@
const char *FR_Table[] = {
"FR_OK成功", /* (0) Succeeded */
"FR_DISK_ERR底层硬件错误", /* (1) A hard error occurred in the low level disk I/O layer */
"FR_INT_ERR断言失败", /* (2) Assertion failed */
"FR_NOT_READY物理驱动没有工作", /* (3) The physical drive cannot work */
"FR_NO_FILE文件不存在", /* (4) Could not find the file */
"FR_NO_PATH路径不存在", /* (5) Could not find the path */
"FR_INVALID_NAME无效文件名", /* (6) The path name format is invalid */
"FR_DENIED由于禁止访问或者目录已满访问被拒绝", /* (7) Access denied due to prohibited access or directory full */
"FR_EXIST文件已经存在", /* (8) Access denied due to prohibited access */
"FR_INVALID_OBJECT文件或者目录对象无效", /* (9) The file/directory object is invalid */
"FR_WRITE_PROTECTED物理驱动被写保护", /* (10) The physical drive is write protected */
"FR_INVALID_DRIVE逻辑驱动号无效", /* (11) The logical drive number is invalid */
"FR_NOT_ENABLED卷中无工作区", /* (12) The volume has no work area */
"FR_NO_FILESYSTEM没有有效的FAT卷", /* (13) There is no valid FAT volume */
"FR_MKFS_ABORTED由于参数错误f_mkfs()被终止", /* (14) The f_mkfs() aborted due to any parameter error */
"FR_TIMEOUT在规定的时间内无法获得访问卷的许可", /* (15) Could not get a grant to access the volume within defined period */
"FR_LOCKED由于文件共享策略操作被拒绝", /* (16) The operation is rejected according to the file sharing policy */
"FR_NOT_ENOUGH_CORE无法分配长文件名工作区", /* (17) LFN working buffer could not be allocated */
"FR_TOO_MANY_OPEN_FILES当前打开的文件数大于_FS_SHARE", /* (18) Number of open files > _FS_SHARE */
"FR_INVALID_PARAMETER参数无效" /* (19) Given parameter is invalid */
};

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.14 /
/ FatFs - Generic FAT Filesystem module R0.15 /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/ Copyright (C) 2022, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -19,7 +19,7 @@
/----------------------------------------------------------------------------*/
#ifndef FF_DEFINED
#define FF_DEFINED 86606 /* Revision ID */
#define FF_DEFINED 80286 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@ -33,10 +33,14 @@ extern "C" {
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Main development platform */
#if defined(_WIN32) /* Windows VC++ (for development only) */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#include <float.h>
#define isnan(v) _isnan(v)
#define isinf(v) (!_finite(v))
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
@ -46,6 +50,7 @@ typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
@ -55,50 +60,6 @@ typedef unsigned long DWORD; /* 32-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct
{
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char *VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L##x
#define _TEXT(x) L##x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8##x
#define _TEXT(x) u8##x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U##x
#define _TEXT(x) U##x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size and LBA variables */
#if FF_FS_EXFAT
@ -119,15 +80,53 @@ typedef DWORD FSIZE_t;
typedef DWORD LBA_t;
#endif
/* Type of path name strings on FatFs API (TCHAR) */
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L##x
#define _TEXT(x) L##x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8##x
#define _TEXT(x) u8##x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U##x
#define _TEXT(x) U##x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char *VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Filesystem object structure (FATFS) */
typedef struct
{
typedef struct {
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Associated physical drive */
BYTE pdrv; /* Volume hosting physical drive */
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
BYTE wflag; /* win[] status (b0:dirty) */
BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
@ -140,9 +139,6 @@ typedef struct
#if FF_FS_EXFAT
BYTE *dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
@ -156,24 +152,23 @@ typedef struct
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD fsize; /* Number of sectors per FAT */
LBA_t volbase; /* Volume base sector */
LBA_t fatbase; /* FAT base sector */
LBA_t dirbase; /* Root directory base sector/cluster */
LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
LBA_t database; /* Data base sector */
#if FF_FS_EXFAT
LBA_t bitbase; /* Allocation bitmap base sector */
#endif
LBA_t winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS] __attribute__((aligned(8))); /* Disk access window for Directory, FAT (and file data at tiny cfg) */
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (FFOBJID) */
typedef struct
{
typedef struct {
FATFS *fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
WORD id; /* Hosting volume's mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
@ -192,8 +187,7 @@ typedef struct
/* File object structure (FIL) */
typedef struct
{
typedef struct {
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
@ -208,14 +202,13 @@ typedef struct
DWORD *cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window */
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct
{
typedef struct {
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
@ -232,14 +225,13 @@ typedef struct
/* File information structure (FILINFO) */
typedef struct
{
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1]; /* Altenative file name */
TCHAR altname[FF_SFN_BUF + 1]; /* Alternative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
@ -248,8 +240,7 @@ typedef struct
/* Format parameter structure (MKFS_PARM) */
typedef struct
{
typedef struct {
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
BYTE n_fat; /* Number of FATs */
UINT align; /* Data area alignment (sector) */
@ -283,7 +274,8 @@ typedef enum {
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
/* FatFs Module Application Interface */
/*--------------------------------------------------------------*/
FRESULT f_open(FIL *fp, const TCHAR *path, BYTE mode); /* Open or create a file */
FRESULT f_close(FIL *fp); /* Close an open file object */
@ -320,6 +312,8 @@ int f_puts(const TCHAR *str, FIL *cp);
int f_printf(FIL *fp, const TCHAR *str, ...); /* Put a formatted string to the file */
TCHAR *f_gets(TCHAR *buff, int len, FIL *fp); /* Get a string from the file */
/* Some API fucntions are implemented as macro */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
@ -329,39 +323,39 @@ TCHAR *f_gets(TCHAR *buff, int len, FIL *fp);
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* Additional Functions */
/*--------------------------------------------------------------*/
/* RTC function */
/* RTC function (provided by user) */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime(void);
DWORD get_fattime(void); /* Get current time */
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
/* LFN support functions (defined in ffunicode.c) */
#if FF_USE_LFN >= 1
WCHAR ff_oem2uni(WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem(DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper(DWORD uni); /* Unicode upper-case conversion */
#endif
/* O/S dependent functions (samples available in ffsystem.c) */
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void *ff_memalloc(UINT msize); /* Allocate memory block */
void ff_memfree(void *mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj(BYTE vol, FF_SYNC_t *sobj); /* Create a sync object */
int ff_req_grant(FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant(FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj(FF_SYNC_t sobj); /* Delete a sync object */
#if FF_FS_REENTRANT /* Sync functions */
int ff_mutex_create(int vol); /* Create a sync object */
void ff_mutex_delete(int vol); /* Delete a sync object */
int ff_mutex_take(int vol); /* Lock sync object */
void ff_mutex_give(int vol); /* Unlock sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* Flags and Offset Address */
/*--------------------------------------------------------------*/
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01

View file

@ -1,12 +1,18 @@
/*---------------------------------------------------------------------------/
/ FatFs Functional Configurations
/ Configurations of FatFs Module
/---------------------------------------------------------------------------*/
#if defined(CONFIG_FFCONF_USER) && (CONFIG_FFCONF_USER)
#include "ffconf_user.h"
#endif
#define FFCONF_DEF 80286 /* Revision ID */
#define FFCONF_DEF 86606 /* Revision ID */
#if defined(CONFIG_FATFS_FFCONF_USER) && (CONFIG_FATFS_FFCONF_USER)
/* User external configuration, User need to use this file as a template.
All configuration items must be included in the file */
#include "ffconf_user.h"
#else
// #warning "There is no user FatFs conf file and the default conf will be used"
/*---------------------------------------------------------------------------/
/ Function Configurations
@ -36,17 +42,8 @@
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#ifndef FF_USE_STRFUNC
#define FF_USE_STRFUNC 2
#endif
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#ifndef FF_USE_FIND
#define FF_USE_FIND 0
#define FF_USE_FIND 1
#endif
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
@ -67,7 +64,7 @@
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#ifndef FF_USE_CHMOD
#define FF_USE_CHMOD 0
#define FF_USE_CHMOD 1
#endif
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
@ -83,6 +80,40 @@
#endif
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
#ifndef FF_USE_STRFUNC
#define FF_USE_STRFUNC 0
#endif
#ifndef FF_PRINT_LLI
#define FF_PRINT_LLI 1
#endif
#ifndef FF_PRINT_FLOAT
#define FF_PRINT_FLOAT 1
#endif
#ifndef FF_STRF_ENCODE
#define FF_STRF_ENCODE 3
#endif
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion.
/
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
/ makes f_printf() support floating point argument. These features want C99 or later.
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
/ to be read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
@ -117,7 +148,9 @@
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 3
#ifndef FF_USE_LFN
#define FF_USE_LFN 2
#endif
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
@ -149,34 +182,15 @@
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#ifndef FF_LFN_BUF
#define FF_LFN_BUF 255
#endif
#ifndef FF_SFN_BUF
#define FF_SFN_BUF 12
#endif
/* This set of options defines size of file name members in the FILINFO structure
/ which is used to read out directory items. These values should be suffcient for
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#ifndef FF_STRF_ENCODE
#define FF_STRF_ENCODE 3
#endif
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#ifndef FF_FS_RPATH
#define FF_FS_RPATH 2
#define FF_FS_RPATH 1
#endif
/* This option configures support for relative path.
/
@ -189,18 +203,18 @@
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 6
#define FF_VOLUMES 5
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 1
#define FF_VOLUME_STRS "ram", "sd", "flash", "usb", "cg", "sd2",
#define FF_STR_VOLUME_ID 2
#define FF_VOLUME_STRS "ram", "flash", "sd", "sd2", "usb"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/ not defined, a user defined volume string table needs to be defined as:
/ not defined, a user defined volume string table is needed as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/
@ -213,32 +227,23 @@
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
/ function will be available. */
#ifndef FF_MIN_SS
#define FF_MIN_SS 512
#endif
#ifndef FF_MAX_SS
#define FF_MAX_SS 512
#endif
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ harddisk, but a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#ifndef FF_LBA64
#define FF_LBA64 0
#endif
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
#ifndef FF_MIN_GPT
#define FF_MIN_GPT 0x100000000
#endif
/* Minimum number of sectors to switch GPT format to create partition in f_mkfs and
#define FF_MIN_GPT 0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
#ifndef FF_USE_TRIM
@ -251,7 +256,6 @@
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#ifndef FF_FS_TINY
#define FF_FS_TINY 0
#endif
@ -270,21 +274,12 @@
#ifndef FF_FS_NORTC
#define FF_FS_NORTC 1
#endif
#ifndef FF_NORTC_MON
#define FF_NORTC_MON 1
#endif
#ifndef FF_NORTC_MDAY
#define FF_NORTC_MDAY 1
#endif
#ifndef FF_NORTC_YEAR
#define FF_NORTC_YEAR 2022
#endif
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
@ -295,7 +290,7 @@
#define FF_FS_NOFSINFO 0
#endif
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ option, and f_getfree() function at the first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
@ -317,33 +312,25 @@
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
/* #include <somertos.h> // O/S definitions */
#ifndef FF_FS_REENTRANT
#define FF_FS_REENTRANT 0
#endif
#if (FF_FS_REENTRANT)
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t SemaphoreHandle_t
#endif
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/ to the same volume is under control of this featuer.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
/ function, must be added to the project. Samples are available in ffsystem.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
*/
#endif
/*--- End of configuration options ---*/

View file

@ -1,163 +1,194 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2018 */
/* A Sample Code of User Provided OS Dependent Functions for FatFs */
/*------------------------------------------------------------------------*/
#include "ff.h"
#include "malloc.h"
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
#if FF_USE_LFN == 3 /* Use dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/* Allocate/Free a Memory Block */
/*------------------------------------------------------------------------*/
#include <stdlib.h> /* with POSIX API */
void *ff_memalloc( /* Returns pointer to the allocated memory block (null if not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
return malloc((size_t)msize); /* Allocate a new memory block */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree(
void *mblock /* Pointer to the memory block to free (nothing to do if null) */
void *mblock /* Pointer to the memory block to free (no effect if null) */
)
{
free(mblock); /* Free the memory block with POSIX API */
free(mblock); /* Free the memory block */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Definitions of Mutex */
/*------------------------------------------------------------------------*/
#define OS_TYPE 3 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */
#if OS_TYPE == 0 /* Win32 */
#include <windows.h>
static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
#elif OS_TYPE == 1 /* uITRON */
#include "itron.h"
#include "kernel.h"
static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#elif OS_TYPE == 2 /* uc/OS-II */
#include "includes.h"
static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */
#elif OS_TYPE == 3 /* FreeRTOS */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
#elif OS_TYPE == 4 /* CMSIS-RTOS */
#include "cmsis_os.h"
static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#endif
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/* Create a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
/* This function is called in f_mount function to create a new mutex
/ or semaphore for the volume. When a 0 is returned, the f_mount function
/ fails with FR_INT_ERR.
*/
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
int ff_cre_syncobj( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t *sobj /* Pointer to return the created sync object */
int ff_mutex_create( /* Returns 1:Function succeeded or 0:Could not create the mutex */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
/* Win32 */
// *sobj = CreateMutex(NULL, FALSE, NULL);
// return (int)(*sobj != INVALID_HANDLE_VALUE);
#if OS_TYPE == 0 /* Win32 */
Mutex[vol] = CreateMutex(NULL, FALSE, NULL);
return (int)(Mutex[vol] != INVALID_HANDLE_VALUE);
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
#elif OS_TYPE == 1 /* uITRON */
T_CMTX cmtx = { TA_TPRI, 1 };
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
Mutex[vol] = acre_mtx(&cmtx);
return (int)(Mutex[vol] > 0);
/* FreeRTOS */
*sobj = xSemaphoreCreateMutex();
return (int)(*sobj != NULL);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
/* CMSIS-RTOS */
// *sobj = osMutexCreate(&Mutex[vol]);
// return (int)(*sobj != NULL);
Mutex[vol] = OSMutexCreate(0, &err);
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
Mutex[vol] = xSemaphoreCreateMutex();
return (int)(Mutex[vol] != NULL);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDef(cmsis_os_mutex);
Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex));
return (int)(Mutex[vol] != NULL);
#endif
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/* Delete a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
/* This function is called in f_mount function to delete a mutex or
/ semaphore of the volume created with ff_mutex_create function.
*/
int ff_del_syncobj( /* 1:Function succeeded, 0:Could not delete due to an error */
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
void ff_mutex_delete( /* Returns 1:Function succeeded or 0:Could not delete due to an error */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
/* Win32 */
// return (int)CloseHandle(sobj);
#if OS_TYPE == 0 /* Win32 */
CloseHandle(Mutex[vol]);
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
#elif OS_TYPE == 1 /* uITRON */
del_mtx(Mutex[vol]);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
/* FreeRTOS */
vSemaphoreDelete(sobj);
return 1;
OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err);
/* CMSIS-RTOS */
// return (int)(osMutexDelete(sobj) == osOK);
#elif OS_TYPE == 3 /* FreeRTOS */
vSemaphoreDelete(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDelete(Mutex[vol]);
#endif
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/* Request a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/* This function is called on enter file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant( /* 1:Got a grant to access the volume, 0:Could not get a grant */
FF_SYNC_t sobj /* Sync object to wait */
int ff_mutex_take( /* Returns 1:Succeeded or 0:Timeout */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
/* Win32 */
// return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
#if OS_TYPE == 0 /* Win32 */
return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0);
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
#elif OS_TYPE == 1 /* uITRON */
return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
/* FreeRTOS */
return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err));
return (int)(err == OS_NO_ERR);
/* CMSIS-RTOS */
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
}
#elif OS_TYPE == 3 /* FreeRTOS */
return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE);
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant(
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* Win32 */
// ReleaseMutex(sobj);
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
/* FreeRTOS */
xSemaphoreGive(sobj);
/* CMSIS-RTOS */
// osMutexRelease(sobj);
}
#elif OS_TYPE == 4 /* CMSIS-RTOS */
return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK);
#endif
}
/*------------------------------------------------------------------------*/
/* Release a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leave file functions to unlock the volume.
*/
void ff_mutex_give(
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
ReleaseMutex(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
unl_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OSMutexPost(Mutex[vol]);
#elif OS_TYPE == 3 /* FreeRTOS */
xSemaphoreGive(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexRelease(Mutex[vol]);
#endif
}
#endif /* FF_FS_REENTRANT */

View file

@ -1,13 +1,13 @@
/*------------------------------------------------------------------------*/
/* Unicode handling functions for FatFs R0.13+ */
/* Unicode Handling Functions for FatFs R0.13 and Later */
/*------------------------------------------------------------------------*/
/* This module will occupy a huge memory in the .rodata section when the */
/* FatFs is configured for LFN with DBCS. If the system has a Unicode */
/* library for the code conversion, this module should be modified to use */
/* it to avoid silly memory consumption. */
/*------------------------------------------------------------------------*/
/* This module will occupy a huge memory in the .const section when the /
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
/ utilitiy for the code conversion, this module should be modified to use /
/ that function to avoid silly memory consumption. /
/-------------------------------------------------------------------------*/
/*
/ Copyright (C) 2014, ChaN, all right reserved.
/ Copyright (C) 2022, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -22,20 +22,21 @@
/ by use of this software.
*/
#include "ff.h"
#if FF_USE_LFN /* This module will be blanked if non-LFN configuration */
#if FF_USE_LFN != 0 /* This module will be blanked if in non-LFN configuration */
#define MERGE2(a, b) a ## b
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
/*------------------------------------------------------------------------*/
/* Code Conversion Tables */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */
static const WCHAR uni2oem932[] = /* Unicode --> Shift_JIS pairs */
{
static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180,
0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6,
0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE,
@ -962,8 +963,7 @@ static const WCHAR uni2oem932[] = /* Unicode --> Shift_JIS pairs */
0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0
};
static const WCHAR oem2uni932[] = /* Shift_JIS --> Unicode pairs */
{
static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68,
0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70,
0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78,
@ -1892,8 +1892,7 @@ static const WCHAR oem2uni932[] = /* Shift_JIS --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */
static const WCHAR uni2oem936[] = /* Unicode --> GBK pairs */
{
static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4,
0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE,
0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9,
@ -4621,8 +4620,7 @@ static const WCHAR uni2oem936[] = /* Unicode --> GBK pairs */
0, 0
};
static const WCHAR oem2uni936[] = /* GBK --> Unicode pairs */
{
static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17,
0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F,
0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42,
@ -7352,8 +7350,7 @@ static const WCHAR oem2uni936[] = /* GBK --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */
static const WCHAR uni2oem949[] = /* Unicode --> Korean pairs */
{
static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6,
0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6,
0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF,
@ -9488,8 +9485,7 @@ static const WCHAR uni2oem949[] = /* Unicode --> Korean pairs */
0, 0
};
static const WCHAR oem2uni949[] = /* Korean --> Unicode pairs */
{
static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E,
0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25,
0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32,
@ -11626,8 +11622,7 @@ static const WCHAR oem2uni949[] = /* Korean --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */
static const WCHAR uni2oem950[] = /* Unicode --> Big5 pairs */
{
static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE,
0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346,
0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E,
@ -13318,8 +13313,7 @@ static const WCHAR uni2oem950[] = /* Unicode --> Big5 pairs */
0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0
};
static const WCHAR oem2uni950[] = /* Big5 --> Unicode pairs */
{
static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A,
0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52,
0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31,
@ -15012,8 +15006,7 @@ static const WCHAR oem2uni950[] = /* Big5 --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
static const WCHAR uc437[] = /* CP437(U.S.) to Unicode conversion table */
{
static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15025,8 +15018,7 @@ static const WCHAR uc437[] = /* CP437(U.S.) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
static const WCHAR uc720[] = /* CP720(Arabic) to Unicode conversion table */
{
static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
@ -15038,8 +15030,7 @@ static const WCHAR uc720[] = /* CP720(Arabic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
static const WCHAR uc737[] = /* CP737(Greek) to Unicode conversion table */
{
static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
@ -15051,8 +15042,7 @@ static const WCHAR uc737[] = /* CP737(Greek) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
static const WCHAR uc771[] = /* CP771(KBL) to Unicode conversion table */
{
static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
@ -15064,8 +15054,7 @@ static const WCHAR uc771[] = /* CP771(KBL) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
static const WCHAR uc775[] = /* CP775(Baltic) to Unicode conversion table */
{
static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
@ -15077,8 +15066,7 @@ static const WCHAR uc775[] = /* CP775(Baltic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
static const WCHAR uc850[] = /* CP850(Latin 1) to Unicode conversion table */
{
static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15090,8 +15078,7 @@ static const WCHAR uc850[] = /* CP850(Latin 1) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
static const WCHAR uc852[] = /* CP852(Latin 2) to Unicode conversion table */
{
static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
@ -15103,8 +15090,7 @@ static const WCHAR uc852[] = /* CP852(Latin 2) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
static const WCHAR uc855[] = /* CP855(Cyrillic) to Unicode conversion table */
{
static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
@ -15116,8 +15102,7 @@ static const WCHAR uc855[] = /* CP855(Cyrillic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
static const WCHAR uc857[] = /* CP857(Turkish) to Unicode conversion table */
{
static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15129,8 +15114,7 @@ static const WCHAR uc857[] = /* CP857(Turkish) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
static const WCHAR uc860[] = /* CP860(Portuguese) to Unicode conversion table */
{
static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15142,8 +15126,7 @@ static const WCHAR uc860[] = /* CP860(Portuguese) to Unicode conversion table *
};
#endif
#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
static const WCHAR uc861[] = /* CP861(Icelandic) to Unicode conversion table */
{
static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15155,8 +15138,7 @@ static const WCHAR uc861[] = /* CP861(Icelandic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
static const WCHAR uc862[] = /* CP862(Hebrew) to Unicode conversion table */
{
static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15168,8 +15150,7 @@ static const WCHAR uc862[] = /* CP862(Hebrew) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
static const WCHAR uc863[] = /* CP863(Canadian French) to Unicode conversion table */
{
static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
@ -15181,8 +15162,7 @@ static const WCHAR uc863[] = /* CP863(Canadian French) to Unicode conversion ta
};
#endif
#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
static const WCHAR uc864[] = /* CP864(Arabic) to Unicode conversion table */
{
static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
@ -15194,8 +15174,7 @@ static const WCHAR uc864[] = /* CP864(Arabic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
static const WCHAR uc865[] = /* CP865(Nordic) to Unicode conversion table */
{
static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
@ -15207,8 +15186,7 @@ static const WCHAR uc865[] = /* CP865(Nordic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
static const WCHAR uc866[] = /* CP866(Russian) to Unicode conversion table */
{
static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
@ -15220,8 +15198,7 @@ static const WCHAR uc866[] = /* CP866(Russian) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
static const WCHAR uc869[] = /* CP869(Greek 2) to Unicode conversion table */
{
static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
@ -15233,9 +15210,12 @@ static const WCHAR uc869[] = /* CP869(Greek 2) to Unicode conversion table */
};
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* SBCS fixed code page */
/* OEM <==> Unicode Conversions for Static Code Page Configuration with */
/* SBCS Fixed Code Page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
@ -15247,17 +15227,13 @@ WCHAR ff_uni2oem( /* Returns OEM code character, zero on error */
WCHAR c = 0;
const WCHAR* p = CVTBL(uc, FF_CODE_PAGE);
if (uni < 0x80) /* ASCII? */
{
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else /* Non-ASCII */
{
if (uni < 0x10000 && cp == FF_CODE_PAGE) /* Is it in BMP and valid code page? */
{
for (c = 0; c < 0x80 && uni != p[c]; c++)
;
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
for (c = 0; c < 0x80 && uni != p[c]; c++) ;
c = (c + 0x80) & 0xFF;
}
}
@ -15273,17 +15249,13 @@ WCHAR ff_oem2uni( /* Returns Unicode character in UTF-16, zero on erro
WCHAR c = 0;
const WCHAR* p = CVTBL(uc, FF_CODE_PAGE);
if (oem < 0x80) /* ASCII? */
{
if (oem < 0x80) { /* ASCII? */
c = oem;
} else /* Extended char */
{
if (cp == FF_CODE_PAGE) /* Is it a valid code page? */
{
if (oem < 0x100) {
c = p[oem - 0x80];
}
} else { /* Extended char */
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
if (oem < 0x100) c = p[oem - 0x80];
}
}
@ -15292,9 +15264,11 @@ WCHAR ff_oem2uni( /* Returns Unicode character in UTF-16, zero on erro
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* DBCS fixed code page */
/* OEM <==> Unicode Conversions for Static Code Page Configuration with */
/* DBCS Fixed Code Page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE >= 900
@ -15307,42 +15281,33 @@ WCHAR ff_uni2oem( /* Returns OEM code character, zero on error */
WCHAR c = 0, uc;
UINT i = 0, n, li, hi;
if (uni < 0x80) /* ASCII? */
{
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else /* Non-ASCII */
{
if (uni < 0x10000 && cp == FF_CODE_PAGE) /* Is it in BMP and valid code page? */
{
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
uc = (WCHAR)uni;
p = CVTBL(uni2oem, FF_CODE_PAGE);
hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1;
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (uc == p[i * 2]) {
break;
}
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) {
c = p[i * 2 + 1];
}
if (n != 0) c = p[i * 2 + 1];
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
WCHAR oem, /* OEM code to be converted */
WORD cp /* Code page for the conversion */
@ -15352,35 +15317,25 @@ WCHAR ff_oem2uni( /* Returns Unicode character in UTF-16, zero on erro
WCHAR c = 0;
UINT i = 0, n, li, hi;
if (oem < 0x80) /* ASCII? */
{
if (oem < 0x80) { /* ASCII? */
c = oem;
} else /* Extended char */
{
if (cp == FF_CODE_PAGE) /* Is it valid code page? */
{
} else { /* Extended char */
if (cp == FF_CODE_PAGE) { /* Is it valid code page? */
p = CVTBL(oem2uni, FF_CODE_PAGE);
hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1;
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (oem == p[i * 2]) {
break;
}
if (oem == p[i * 2]) break;
if (oem > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) {
c = p[i * 2 + 1];
}
if (n != 0) c = p[i * 2 + 1];
}
}
@ -15388,8 +15343,10 @@ WCHAR ff_oem2uni( /* Returns Unicode character in UTF-16, zero on erro
}
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for dynamic code page configuration */
/* OEM <==> Unicode Conversions for Dynamic Code Page Configuration */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 0
@ -15397,6 +15354,7 @@ WCHAR ff_oem2uni( /* Returns Unicode character in UTF-16, zero on erro
static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0};
static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
@ -15406,78 +15364,40 @@ WCHAR ff_uni2oem( /* Returns OEM code character, zero on error */
WCHAR c = 0, uc;
UINT i, n, li, hi;
if (uni < 0x80) /* ASCII? */
{
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else /* Non-ASCII */
{
if (uni < 0x10000) /* Is it in BMP? */
{
} else { /* Non-ASCII */
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WCHAR)uni;
p = 0;
if (cp < 900) /* SBCS */
{
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++)
; /* Get conversion table */
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */
p = cp_table[i];
if (p) /* Is it valid code page ? */
{
for (c = 0; c < 0x80 && uc != p[c]; c++)
; /* Find OEM code in the table */
if (p) { /* Is it valid code page ? */
for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */
c = (c + 0x80) & 0xFF;
}
} else /* DBCS */
{
switch (cp) /* Get conversion table */
{
case 932:
p = uni2oem932;
hi = sizeof uni2oem932 / 4 - 1;
break;
case 936:
p = uni2oem936;
hi = sizeof uni2oem936 / 4 - 1;
break;
case 949:
p = uni2oem949;
hi = sizeof uni2oem949 / 4 - 1;
break;
case 950:
p = uni2oem950;
hi = sizeof uni2oem950 / 4 - 1;
break;
} else { /* DBCS */
switch (cp) { /* Get conversion table */
case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
}
if (p) /* Is it valid code page? */
{
if (p) { /* Is it valid code page? */
li = 0;
for (n = 16; n; n--) /* Find OEM code */
{
for (n = 16; n; n--) { /* Find OEM code */
i = li + (hi - li) / 2;
if (uc == p[i * 2]) {
break;
}
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) {
c = p[i * 2 + 1];
}
if (n != 0) c = p[i * 2 + 1];
}
}
}
@ -15486,6 +15406,7 @@ WCHAR ff_uni2oem( /* Returns OEM code character, zero on error */
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */
WORD cp /* Code page for the conversion */
@ -15495,71 +15416,37 @@ WCHAR ff_oem2uni( /* Returns Unicode character in UTF-16, zero on erro
WCHAR c = 0;
UINT i, n, li, hi;
if (oem < 0x80) /* ASCII? */
{
if (oem < 0x80) { /* ASCII? */
c = oem;
} else /* Extended char */
{
} else { /* Extended char */
p = 0;
if (cp < 900) /* SBCS */
{
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++)
; /* Get table */
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */
p = cp_table[i];
if (p) /* Is it a valid CP ? */
{
if (oem < 0x100) {
c = p[oem - 0x80];
if (p) { /* Is it a valid CP ? */
if (oem < 0x100) c = p[oem - 0x80];
}
}
} else /* DBCS */
{
} else { /* DBCS */
switch (cp) {
case 932:
p = oem2uni932;
hi = sizeof oem2uni932 / 4 - 1;
break;
case 936:
p = oem2uni936;
hi = sizeof oem2uni936 / 4 - 1;
break;
case 949:
p = oem2uni949;
hi = sizeof oem2uni949 / 4 - 1;
break;
case 950:
p = oem2uni950;
hi = sizeof oem2uni950 / 4 - 1;
break;
case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break;
case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break;
case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break;
case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break;
}
if (p) {
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (oem == p[i * 2]) {
break;
}
if (oem == p[i * 2]) break;
if (oem > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) {
c = p[i * 2 + 1];
}
if (n != 0) c = p[i * 2 + 1];
}
}
}
@ -15568,8 +15455,10 @@ WCHAR ff_oem2uni( /* Returns Unicode character in UTF-16, zero on erro
}
#endif
/*------------------------------------------------------------------------*/
/* Unicode up-case conversion */
/* Unicode Up-case Conversion */
/*------------------------------------------------------------------------*/
DWORD ff_wtoupper ( /* Returns up-converted code point */
@ -15578,8 +15467,7 @@ DWORD ff_wtoupper( /* Returns up-converted code point */
{
const WORD* p;
WORD uc, bc, nc, cmd;
static const WORD cvt1[] = /* Compressed up conversion table for U+0000 - U+0FFF */
{
static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */
/* Basic Latin */
0x0061,0x031A,
/* Latin-1 Supplement */
@ -15626,8 +15514,7 @@ DWORD ff_wtoupper( /* Returns up-converted code point */
0x0000 /* EOT */
};
static const WORD cvt2[] = /* Compressed up conversion table for U+1000 - U+FFFF */
{
static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */
/* Phonetic Extensions */
0x1D7D,0x0001,0x2C63,
/* Latin Extended Additional */
@ -15672,78 +15559,35 @@ DWORD ff_wtoupper( /* Returns up-converted code point */
0x0000 /* EOT */
};
if (uni < 0x10000) /* Is it in BMP? */
{
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WORD)uni;
p = uc < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get the block base */
if (bc == 0 || uc < bc) {
break; /* Not matched? */
}
nc = *p++;
cmd = nc >> 8;
nc &= 0xFF; /* Get processing command and block size */
if (uc < bc + nc) /* In the block? */
{
if (bc == 0 || uc < bc) break; /* Not matched? */
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (uc < bc + nc) { /* In the block? */
switch (cmd) {
case 0:
uc = p[uc - bc];
break; /* Table conversion */
case 1:
uc -= (uc - bc) & 1;
break; /* Case pairs */
case 2:
uc -= 16;
break; /* Shift -16 */
case 3:
uc -= 32;
break; /* Shift -32 */
case 4:
uc -= 48;
break; /* Shift -48 */
case 5:
uc -= 26;
break; /* Shift -26 */
case 6:
uc += 8;
break; /* Shift +8 */
case 7:
uc -= 80;
break; /* Shift -80 */
case 8:
uc -= 0x1C60;
break; /* Shift -0x1C60 */
/* add this for make pass */
default:
case 0: uc = p[uc - bc]; break; /* Table conversion */
case 1: uc -= (uc - bc) & 1; break; /* Case pairs */
case 2: uc -= 16; break; /* Shift -16 */
case 3: uc -= 32; break; /* Shift -32 */
case 4: uc -= 48; break; /* Shift -48 */
case 5: uc -= 26; break; /* Shift -26 */
case 6: uc += 8; break; /* Shift +8 */
case 7: uc -= 80; break; /* Shift -80 */
case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */
}
break;
}
break;
if (cmd == 0) p += nc; /* Skip table if needed */
}
if (cmd == 0) {
p += nc; /* Skip table if needed */
}
}
uni = uc;
}
return uni;
}
#endif /* #if FF_USE_LFN */
#endif /* #if FF_USE_LFN != 0 */

View file

@ -0,0 +1,33 @@
/**
* @file sdh_sdcard.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef FATFS_DISKIO_REGISTER_H
#define FATFS_DISKIO_REGISTER_H
#if defined(BL616) || defined(BL808) || defined(BL628) || defined(BL606P)
void fatfs_sdh_driver_register(void);
#endif
#endif

View file

@ -21,15 +21,6 @@
*
*/
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2019 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#if defined(BL616) || defined(BL808) || defined(BL628) || defined(BL606P)
#include "ff.h" /* Obtains integer types */
@ -38,7 +29,6 @@
#include "bflb_irq.h"
static sd_card_t gSDCardInfo;
extern const char *FR_Table[];
int MMC_disk_status()
{
@ -108,33 +98,38 @@ int MMC_disk_ioctl(BYTE cmd, void *buff)
DSTATUS Translate_Result_Code(int result)
{
// MSG("%s\r\n",FR_Table[result]);
return result;
}
extern void SDH_MMC1_IRQHandler(void);
static void sdh_isr(int irq, void *arg)
{
SDH_MMC1_IRQHandler();
}
void fatfs_sdh_driver_register(void)
{
FATFS_DiskioDriverTypeDef pNewDiskioDriver;
FATFS_DiskioDriverTypeDef SDH_DiskioDriver = { NULL };
memset(&pNewDiskioDriver, 0, sizeof(FATFS_DiskioDriverTypeDef));
SDH_DiskioDriver.disk_status = MMC_disk_status;
SDH_DiskioDriver.disk_initialize = MMC_disk_initialize;
SDH_DiskioDriver.disk_write = MMC_disk_write;
SDH_DiskioDriver.disk_read = MMC_disk_read;
SDH_DiskioDriver.disk_ioctl = MMC_disk_ioctl;
SDH_DiskioDriver.error_code_parsing = Translate_Result_Code;
pNewDiskioDriver.MMC_disk_status = MMC_disk_status;
pNewDiskioDriver.MMC_disk_initialize = MMC_disk_initialize;
pNewDiskioDriver.MMC_disk_write = MMC_disk_write;
pNewDiskioDriver.MMC_disk_read = MMC_disk_read;
pNewDiskioDriver.MMC_disk_ioctl = MMC_disk_ioctl;
pNewDiskioDriver.Translate_Result_Code = Translate_Result_Code;
disk_driver_callback_init(&pNewDiskioDriver);
disk_driver_callback_init(DEV_SD, &SDH_DiskioDriver);
}
bflb_irq_attach(33, sdh_isr, NULL);
bflb_irq_enable(33);
uint32_t get_fattime(void)
{
uint16_t year = 2022;
uint8_t mon = 1;
uint8_t mday = 1;
uint8_t hour = 0;
uint8_t min = 0;
uint8_t sec = 0;
return ((uint32_t)(year - 1980) << 25 |
(uint32_t)mon << 21 |
(uint32_t)mday << 16 |
(uint32_t)hour << 11 |
(uint32_t)min << 5 |
(uint32_t)(sec / 2) << 0);
}
#endif

View file

@ -1,5 +1,9 @@
sdk_generate_library()
add_subdirectory(newlib)
# use newlib stdlib or nuttx stdlib
if(NOT CONFIG_NEWLIB_STANDARD)
sdk_library_add_sources(
nuttx/libc/stdlib/lib_abs.c
nuttx/libc/stdlib/lib_atof.c
@ -19,7 +23,10 @@ nuttx/libc/stdlib/lib_strtod.c
# nuttx/libc/stdlib/lib_strtoll.c
# nuttx/libc/stdlib/lib_strtoull.c
)
endif()
# use newlib string or nuttx string
if(NOT CONFIG_NEWLIB_STANDARD)
sdk_library_add_sources(
nuttx/libc/string/lib_ffs.c
nuttx/libc/string/lib_ffsl.c
@ -54,72 +61,51 @@ nuttx/libc/string/lib_strtokr.c
# nuttx/libc/string/lib_isbasedigit.c
# nuttx/libc/string/lib_skipspace.c
)
endif()
# is boot2
if(NOT CONFIG_BOOT2)
# use newlib memcpy or nuttx memcpy
if(NOT CONFIG_NEWLIB_STANDARD)
sdk_library_add_sources(
nuttx/libc/string/lib_vikmemcpy.c
)
endif()
else()
sdk_library_add_sources(
nuttx/libc/string/lib_memcpy.c
)
endif()
sdk_add_include_directories(.)
# libc or vlibc select
if(CONFIG_VLIBC)
# vsnprintf config
if(CONFIG_VSNPRINTF_FLOAT)
sdk_add_compile_definitions(-DCONFIG_VLIBC_FLOAT=${CONFIG_VSNPRINTF_FLOAT})
endif()
if(CONFIG_VSNPRINTF_FLOAT_EX)
sdk_add_compile_definitions(-DCONFIG_VLIBC_FLOAT_EX=${CONFIG_VSNPRINTF_FLOAT_EX})
endif()
if(CONFIG_VSNPRINTF_LONG_LONG)
sdk_add_compile_definitions(-DCONFIG_VLIBC_LONG_LONG=${CONFIG_VSNPRINTF_LONG_LONG})
endif()
if(CONFIG_VSNPRINTF_WRITEBACK)
sdk_add_compile_definitions(-DCONFIG_VLIBC_WRITEBACK=${CONFIG_VSNPRINTF_WRITEBACK})
endif()
sdk_add_compile_definitions(-DCONFIG_VLIBC)
# vlibc debug enable
if(CONFIG_VLIBC_DEBUG)
sdk_add_compile_definitions(-DCONFIG_VLIBC_DEBUG)
endif()
# vlibc fatfs port enable
if(CONFIG_VLIBC_FATFS)
sdk_add_compile_definitions(-DCONFIG_VLIBC_FATFS)
endif()
sdk_library_add_sources(vlibc/printf.c)
sdk_library_add_sources(vlibc/vlibc_stdio.c)
sdk_library_add_sources(vlibc/vlibc_vsnprintf.c)
sdk_add_include_directories(vlibc)
else()
# vsnprintf config
if(CONFIG_VSNPRINTF_FLOAT)
sdk_add_compile_definitions(-DCONFIG_LIBC_FLOAT=${CONFIG_VSNPRINTF_FLOAT})
endif()
if(CONFIG_VSNPRINTF_FLOAT_EX)
sdk_add_compile_definitions(-DCONFIG_LIBC_FLOAT_EX=${CONFIG_VSNPRINTF_FLOAT_EX})
endif()
if(CONFIG_VSNPRINTF_LONG_LONG)
sdk_add_compile_definitions(-DCONFIG_LIBC_LONG_LONG=${CONFIG_VSNPRINTF_LONG_LONG})
endif()
if(NOT CONFIG_NEWLIB_STANDARD)
if(CONFIG_VSNPRINTF_NANO)
sdk_library_add_sources(vsnprintf_nano.c)
else()
sdk_library_add_sources(vsnprintf.c)
endif()
endif()
if(NOT CONFIG_NEWLIB)
sdk_library_add_sources(snprintf.c)
sdk_library_add_sources(sprintf.c)
sdk_library_add_sources(vsprintf.c)
sdk_library_add_sources(printf.c)
endif()
sdk_library_add_sources(snprintf.c)
# vsnprintf %f %F
if(CONFIG_VSNPRINTF_FLOAT)
sdk_add_compile_definitions(-DCONFIG_LIBC_FLOAT=${CONFIG_VSNPRINTF_FLOAT})
endif()
# vsnprintf %g %G %e %E
if(CONFIG_VSNPRINTF_FLOAT_EX)
sdk_add_compile_definitions(-DCONFIG_LIBC_FLOAT_EX=${CONFIG_VSNPRINTF_FLOAT_EX})
endif()
# vsnprintf %lld %lli %llu %llx %llX %llo
if(CONFIG_VSNPRINTF_LONG_LONG)
sdk_add_compile_definitions(-DCONFIG_LIBC_LONG_LONG=${CONFIG_VSNPRINTF_LONG_LONG})
endif()
# use custom apis first, if not exist, then use builtin apis
sdk_add_compile_options(-fno-builtin)

View file

@ -0,0 +1,33 @@
sdk_add_include_directories(.)
if(CONFIG_NEWLIB_STANDARD)
sdk_add_compile_definitions(-DCONFIG_NEWLIB_STANDARD=1)
get_target_property(SDK_INTF_LIB_LINK_OPTIONS sdk_intf_lib INTERFACE_LINK_OPTIONS)
list(REMOVE_ITEM SDK_INTF_LIB_LINK_OPTIONS --specs=nano.specs)
set_target_properties(sdk_intf_lib PROPERTIES INTERFACE_LINK_OPTIONS "")
foreach(item ${SDK_INTF_LIB_LINK_OPTIONS})
sdk_add_link_options(${item})
endforeach()
endif()
# newlib syscalls and ports
if(CONFIG_NEWLIB)
sdk_add_compile_definitions(-DCONFIG_NEWLIB=1)
sdk_library_add_sources(syscalls.c)
sdk_library_add_sources(port_tty.c)
sdk_library_add_sources(port_time.c)
sdk_library_add_sources(port_memory.c)
sdk_library_add_sources(port_init_fini.c)
if(CONFIG_NEWLIB_FATFS)
sdk_add_compile_definitions(-DCONFIG_NEWLIB_FATFS=1)
sdk_library_add_sources(port_file_fatfs.c)
else()
sdk_library_add_sources(port_file_nosys.c)
endif()
else()
sdk_library_add_sources(syscalls_nosys.c)
endif()

View file

@ -0,0 +1,9 @@
# Newlib Syscalls
## Configurations
| CONFIG | Description |
|:----------------------:|:---------------------------:|
| CONFIG_NEWLIB | Enable newlib support |
| CONFIG_NEWLIB_STANDARD | Enable newlib full standart support (default nano) |
| CONFIG_NEWLIB_FATFS | Enable newlib filesystem port fatfs support |

View file

@ -0,0 +1,561 @@
#include <errno.h>
#include <reent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include "ff.h"
int fresult_table[20] = {
0, /* (0) Succeeded */
EIO, /* (1) A hard error occurred in the low level disk I/O layer */
EINVAL, /* (2) Assertion failed */
EIO, /* (3) The physical drive cannot work */
ENOENT, /* (4) Could not find the file */
ENOENT, /* (5) Could not find the path */
EBADF, /* (6) The path name format is invalid */
EACCES, /* (7) Access denied due to prohibited access or directory full */
EEXIST, /* (8) Access denied due to prohibited access */
ENOENT, /* (9) The file/directory object is invalid */
EROFS, /* (10) The physical drive is write protected */
ENODEV, /* (11) The logical drive number is invalid */
ENODEV, /* (12) The volume has no work area */
EPIPE, /* (13) There is no valid FAT volume */
EIO, /* (14) The f_mkfs() aborted due to any problem */
EBUSY, /* (15) Could not get a grant to access the volume within defined period */
EACCES, /* (16) The operation is rejected according to the file sharing policy */
ENOMEM, /* (17) LFN working buffer could not be allocated */
EMFILE, /* (18) Number of open files > FF_FS_LOCK */
EINVAL /* (19) Given parameter is invalid */
};
static void *fd_table[FOPEN_MAX] = { NULL };
/*****************************************************************************
* @brief c99 mode to fatfs mode
*
* @param[in] mode c99 mode
*
* @retval uint8_t fatfs mode
*****************************************************************************/
static uint8_t _open_r_helper_mode_to_fatfs(int mode)
{
uint8_t fatfs_mode;
switch (mode & O_ACCMODE) {
case O_RDONLY:
fatfs_mode = FA_READ;
break;
case O_WRONLY:
fatfs_mode = FA_WRITE;
break;
case O_RDWR:
fatfs_mode = (FA_READ | FA_WRITE);
break;
default:
fatfs_mode = FA_READ;
break;
}
if ((mode & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) {
fatfs_mode |= FA_CREATE_ALWAYS;
} else if (mode & O_APPEND) {
fatfs_mode |= FA_OPEN_APPEND;
} else if (mode & O_EXCL) {
fatfs_mode |= FA_CREATE_NEW;
} else if (mode & O_CREAT) {
fatfs_mode |= FA_OPEN_ALWAYS;
}
return fatfs_mode;
}
/*****************************************************************************
* @brief open
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path string pointer
* @param[in] flags open mode in fcntl.h
* @param[in] mode permission mode
*
* @retval int >=0:fd -1:Error
*****************************************************************************/
int _open_file_r(struct _reent *reent, const char *path, int flags, int mode)
{
FRESULT fresult;
FIL *fp;
int fd = -1;
for (int i = 0; i < FOPEN_MAX; i++) {
if (fd_table[i] == NULL) {
fd_table[i] = (void *)0xffffffff;
fd = i;
break;
}
}
if (fd == -1) {
reent->_errno = EMFILE;
return -1;
}
fp = (FIL *)malloc(sizeof(FIL));
if (fp == NULL) {
reent->_errno = ENOMEM;
return -1;
}
fresult = f_open(fp, path, _open_r_helper_mode_to_fatfs(flags));
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
free(fp);
return -1;
}
fd_table[fd] = fp;
return 0x4000 | fd;
}
/*****************************************************************************
* @brief close
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _close_file_r(struct _reent *reent, int fd)
{
FRESULT fresult;
FIL *fp;
fd &= ~0x4000;
if ((fd < 0) || (fd >= FOPEN_MAX) || (fd_table[fd] == NULL)) {
reent->_errno = EBADF;
return -1;
}
fp = fd_table[fd];
fresult = f_close(fp);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
free(fp);
fd_table[fd] = NULL;
return 0;
}
/*****************************************************************************
* @brief read
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes read
*
* @retval _ssize_t actual number of bytes read
*****************************************************************************/
_ssize_t _read_file_r(struct _reent *reent, int fd, void *ptr, size_t size)
{
size_t bytes = 0;
FRESULT fresult;
FIL *fp;
fd &= ~0x4000;
if ((fd < 0) || (fd >= FOPEN_MAX) || (fd_table[fd] == NULL)) {
reent->_errno = EBADF;
return -1;
}
fp = fd_table[fd];
fresult = f_read(fp, ptr, size, &bytes);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
}
return bytes;
}
/*****************************************************************************
* @brief write
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes write
*
* @retval _ssize_t actual number of bytes write
*****************************************************************************/
_ssize_t _write_file_r(struct _reent *reent, int fd, const void *ptr, size_t size)
{
size_t bytes = 0;
FRESULT fresult;
FIL *fp;
fd &= ~0x4000;
if ((fd < 0) || (fd >= FOPEN_MAX) || (fd_table[fd] == NULL)) {
reent->_errno = EBADF;
return -1;
}
fp = fd_table[fd];
fresult = f_write(fp, ptr, size, &bytes);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
} else {
f_sync(fp);
}
return bytes;
}
/*****************************************************************************
* @brief lseek
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] offset number of offset bytes
* @param[in] whence offset type
*
* @retval _off_t absolute offset of file pointer
*****************************************************************************/
_off_t _lseek_file_r(struct _reent *reent, int fd, _off_t offset, int whence)
{
FRESULT fresult;
FIL *fp;
fd &= ~0x4000;
if ((fd < 0) || (fd >= FOPEN_MAX) || (fd_table[fd] == NULL)) {
reent->_errno = EBADF;
return -1;
}
fp = fd_table[fd];
switch (whence) {
case SEEK_SET:
fresult = f_lseek(fp, offset);
break;
case SEEK_CUR:
fresult = f_lseek(fp, f_tell((FIL *)fp) + offset);
break;
case SEEK_END:
fresult = f_lseek(fp, f_size((FIL *)fp) + offset);
break;
default:
reent->_errno = EINVAL;
return -1;
}
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
errno = fresult_table[fresult];
}
return EOF;
}
return f_tell((FIL *)fp);
}
/*****************************************************************************
* @brief rename
*
* @param[in] reent pointer to reentrant struct
* @param[in] oldname old file path
* @param[in] newname new file path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _rename_file_r(struct _reent *reent, const char *oldname, const char *newname)
{
FRESULT fresult;
fresult = f_rename(oldname, newname);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
return 0;
}
/*****************************************************************************
* @brief unlink
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _unlink_file_r(struct _reent *reent, const char *path)
{
FRESULT fresult;
fresult = f_unlink(path);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
return 0;
}
/*****************************************************************************
* @brief fstat (not supported)
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _fstat_file_r(struct _reent *reent, int fd, struct stat *st)
{
FIL *fp;
fd &= ~0x4000;
if ((fd < 0) || (fd >= FOPEN_MAX) || (fd_table[fd] == NULL)) {
reent->_errno = EBADF;
return -1;
}
fp = fd_table[fd];
st->st_mode = 0444 | S_IFREG;
if (!(fp->obj.attr & AM_RDO)) {
st->st_mode |= 0222;
}
st->st_size = f_size(fp);
// st->st_atime = 0;
// st->st_mtime = 0;
// st->st_ctime = 0;
return 0;
}
/*****************************************************************************
* @brief stat
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _stat_file_r(struct _reent *reent, const char *path, struct stat *st)
{
FRESULT fresult;
FILINFO fno;
fresult = f_stat(path, &fno);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
st->st_mode = 0444;
if (!(fno.fattrib & AM_RDO)) {
st->st_mode |= 0222;
}
if (fno.fattrib & AM_DIR) {
st->st_mode |= S_IFDIR;
} else {
st->st_mode |= S_IFREG;
}
st->st_size = fno.fsize;
time_t ftime_sec = ((fno.ftime >> 0) & 0x1F) * 2 +
((fno.ftime >> 5) & 0x3F) * 60 +
((fno.ftime >> 11) & 0x1F) * 3600;
st->st_atime = ftime_sec;
st->st_mtime = ftime_sec;
st->st_ctime = ftime_sec;
return 0;
}
/*****************************************************************************
* @brief mkdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
* @param[in] mode mode
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _mkdir_file_r(struct _reent *reent, const char *path, int mode)
{
int fresult;
fresult = f_mkdir(path);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
return 0;
}
/*****************************************************************************
* @brief rmdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _rmdir_file_r(struct _reent *reent, const char *path)
{
int fresult;
fresult = f_rmdir(path);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
return 0;
}
/*****************************************************************************
* @brief chmod
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
* @param[in] mode mode
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chmod_file_r(struct _reent *reent, const char *path, mode_t mode)
{
FRESULT fresult;
if ((mode & S_IRWXU) == S_IRUSR) {
fresult = f_chmod(path, AM_RDO, AM_RDO);
} else {
fresult = f_chmod(path, 0, AM_RDO);
}
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
return 0;
}
/*****************************************************************************
* @brief chdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chdir_file_r(struct _reent *reent, const char *path)
{
FRESULT fresult;
fresult = f_chdir(path);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
return 0;
}
/*****************************************************************************
* @brief getcwd
*
* @param[in] reent pointer to reentrant struct
* @param[in] buf buf for path
* @param[in] size buf size
*
* @retval char* pointer to path string NULL:Error
*****************************************************************************/
char *_getcwd_file_r(struct _reent *reent, char *buf, size_t size)
{
FRESULT fresult;
fresult = f_getcwd(buf, size);
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return NULL;
}
return buf;
}
/*****************************************************************************
* @brief chroot
*
* @param[in] path path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chroot_file_r(struct _reent *reent, const char *path)
{
FRESULT fresult;
fresult = f_chdrive("sd:/");
if (fresult != FR_OK) {
if (fresult <= FR_INVALID_PARAMETER) {
reent->_errno = fresult_table[fresult];
}
return -1;
}
return 0;
}

View file

@ -0,0 +1,229 @@
#include <errno.h>
#include <reent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
/*****************************************************************************
* @brief open
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path string pointer
* @param[in] flags open mode in fcntl.h
* @param[in] mode permission mode
*
* @retval int >=0:fd -1:Error
*****************************************************************************/
int _open_file_r(struct _reent *reent, const char *path, int flags, int mode)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief close
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _close_file_r(struct _reent *reent, int fd)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief read
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes read
*
* @retval _ssize_t actual number of bytes read
*****************************************************************************/
_ssize_t _read_file_r(struct _reent *reent, int fd, void *ptr, size_t size)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief write
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes write
*
* @retval _ssize_t actual number of bytes write
*****************************************************************************/
_ssize_t _write_file_r(struct _reent *reent, int fd, const void *ptr, size_t size)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief lseek
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] offset number of offset bytes
* @param[in] whence offset type
*
* @retval _off_t absolute offset of file pointer
*****************************************************************************/
_off_t _lseek_file_r(struct _reent *reent, int fd, _off_t offset, int whence)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief rename
*
* @param[in] reent pointer to reentrant struct
* @param[in] oldname old file path
* @param[in] newname new file path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _rename_file_r(struct _reent *reent, const char *oldname, const char *newname)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief unlink
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _unlink_file_r(struct _reent *reent, const char *path)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief fstat (not supported)
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _fstat_file_r(struct _reent *reent, int fd, struct stat *st)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief stat
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _stat_file_r(struct _reent *reent, const char *path, struct stat *st)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief mkdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
* @param[in] mode mode
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _mkdir_file_r(struct _reent *reent, const char *path, int mode)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief rmdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _rmdir_file_r(struct _reent *reent, const char *path)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief chmod
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
* @param[in] mode mode
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chmod_file_r(struct _reent *reent, const char *path, mode_t mode)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief chdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chdir_file_r(struct _reent *reent, const char *path)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief getcwd
*
* @param[in] reent pointer to reentrant struct
* @param[in] buf buf for path
* @param[in] size buf size
*
* @retval char* pointer to path string NULL:Error
*****************************************************************************/
char *_getcwd_file_r(struct _reent *reent, char *buf, size_t size)
{
reent->_errno = ENOSYS;
return NULL;
}
/*****************************************************************************
* @brief chroot
*
* @param[in] path path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chroot_file_r(struct _reent *reent, const char *path)
{
reent->_errno = ENOSYS;
return -1;
}

View file

@ -0,0 +1,53 @@
#include <sys/types.h>
/* These magic symbols are provided by the linker. */
extern void (*__preinit_array_start[])(void) __attribute__((weak));
extern void (*__preinit_array_end[])(void) __attribute__((weak));
extern void (*__init_array_start[])(void) __attribute__((weak));
extern void (*__init_array_end[])(void) __attribute__((weak));
extern void (*__fini_array_start[])(void) __attribute__((weak));
extern void (*__fini_array_end[])(void) __attribute__((weak));
extern void _init(void);
extern void _fini(void);
__attribute__((weak)) void _init(void)
{
}
__attribute__((weak)) void _fini(void)
{
}
/* Iterate over all the init routines. */
void __libc_init_array(void)
{
size_t count;
size_t i;
count = __preinit_array_end - __preinit_array_start;
for (i = 0; i < count; i++) {
__preinit_array_start[i]();
}
_init();
count = __init_array_end - __init_array_start;
for (i = 0; i < count; i++) {
__init_array_start[i]();
}
}
/* Run all the cleanup routines. */
void __libc_fini_array(void)
{
size_t count;
size_t i;
count = __fini_array_end - __fini_array_start;
for (i = count; i > 0; i--) {
__fini_array_start[i - 1]();
}
_fini();
}

View file

@ -0,0 +1,122 @@
#include <errno.h>
#include <reent.h>
#include "mem.h"
/*****************************************************************************
* @brief allocates space (disable)
*
* @param[in] reent pointer to reentrant struct
* @param[in] incr bytes of increment
*
* @retval void* pointer to allocated memory
*****************************************************************************/
void *_sbrk_r(struct _reent *reent, ptrdiff_t incr)
{
reent->_errno = ENOSYS;
return NULL;
}
/*****************************************************************************
* @brief allocate memory
*
* @param[in] reent pointer to reentrant struct
* @param[in] size bytes of allocated memory
*
* @retval void* pointer to allocated memory
*****************************************************************************/
void *_malloc_r(struct _reent *reent, size_t size)
{
void *mem;
mem = bflb_malloc(KMEM_HEAP, size);
if (mem == NULL) {
reent->_errno = ENOMEM;
}
return mem;
}
/*****************************************************************************
* @brief reallocate memory
*
* @param[in] reent pointer to reentrant struct
* @param[in] old pointer to old allocated memory
* @param[in] newlen bytes of new allocated memory
*
* @retval void* pointer to new allocated memory
*****************************************************************************/
void *_realloc_r(struct _reent *reent, void *old, size_t newlen)
{
void *mem;
mem = bflb_realloc(KMEM_HEAP, old, newlen);
if (mem == NULL) {
reent->_errno = ENOMEM;
}
return mem;
}
/*****************************************************************************
* @brief allocate and zero memory
*
* @param[in] reent pointer to reentrant struct
* @param[in] nmenb
* @param[in] size
*
* @retval void* pointer to allocated memory
*****************************************************************************/
void *_calloc_r(struct _reent *reent, size_t nmenb, size_t size)
{
void *mem;
mem = bflb_calloc(KMEM_HEAP, nmenb, size);
if (mem == NULL) {
reent->_errno = ENOMEM;
}
return mem;
}
/*****************************************************************************
* @brief allocate aligned memory
*
* @param[in] reent pointer to reentrant struct
* @param[in] align align bytes
* @param[in] size bytes of allocated memory
*
* @retval void* pointer to new allocated memory
*****************************************************************************/
void *_memalign_r(struct _reent *reent, size_t align, size_t size)
{
void *mem;
mem = bflb_malloc_align(KMEM_HEAP, align, size);
if (mem == NULL) {
reent->_errno = ENOMEM;
}
return mem;
}
/*****************************************************************************
* @brief free memory
*
* @param[in] reent pointer to reentrant struct
* @param[in] addr pointer to allocated memory
*
*****************************************************************************/
void _free_r(struct _reent *reent, void *addr)
{
if (addr == NULL) {
reent->_errno = EINVAL;
return;
}
bflb_free(KMEM_HEAP, addr);
}

View file

@ -0,0 +1,106 @@
#include <errno.h>
#include <reent.h>
#include <sys/time.h>
#include "bflb_rtc.h"
static struct bflb_device_s *rtc = NULL;
static uint32_t timestamp_base = 0;
static struct timezone tz = {
.tz_dsttime = 0,
.tz_minuteswest = 0
};
struct tms {
clock_t tms_utime; /* user time */
clock_t tms_stime; /* system time */
clock_t tms_cutime; /* user time, children */
clock_t tms_cstime; /* system time, children */
};
/*****************************************************************************
* @brief get times
*
* @param[in] reent pointer to reentrant struct
* @param[out] ptms pointer to tms struct
*
* @retval clock_t timeval now
*****************************************************************************/
clock_t _times_r(struct _reent *reent, struct tms *ptms)
{
clock_t timeval = bflb_mtimer_get_time_us();
if (ptms) {
ptms->tms_utime = timeval; /* user time */
ptms->tms_stime = 0; /* system time */
ptms->tms_cutime = 0; /* user time, children */
ptms->tms_cstime = 0; /* system time, children */
}
return timeval;
}
/*****************************************************************************
* @brief
*
* @param[in] reent pointer to reentrant struct
* @param[out] tp pointer to timeval struct
* @param[out] tzvp pointer to timezone struct
*
* @retval int
*****************************************************************************/
int _gettimeofday_r(struct _reent *reent, struct timeval *tp, void *tzvp)
{
struct timezone *tzp = tzvp;
if (rtc == NULL) {
rtc = bflb_device_get_by_name("rtc");
}
if (tp) {
uint64_t ticks = bflb_rtc_get_time(rtc);
tp->tv_sec = ticks / 32768 + timestamp_base;
tp->tv_usec = (ticks & 0x7fff) * 31;
}
if (tzp) {
tzp->tz_minuteswest = tz.tz_minuteswest;
tzp->tz_dsttime = tz.tz_dsttime;
}
return 0;
}
/*****************************************************************************
* @brief
*
* @param[in] reent pointer to reentrant struct
* @param[in] tp pointer to timeval struct
* @param[in] tzp pointer to timezone struct
*
* @retval int
*****************************************************************************/
int _settimeofday_r(struct _reent *reent, const struct timeval *tp, const struct timezone *tzp)
{
if (rtc == NULL) {
rtc = bflb_device_get_by_name("rtc");
}
if (tp) {
bflb_rtc_set_time(rtc, tp->tv_usec / 31);
timestamp_base = tp->tv_sec;
}
if (tzp) {
tz.tz_dsttime = tzp->tz_dsttime;
tz.tz_minuteswest = tzp->tz_minuteswest;
}
return 0;
}
int settimeofday(const struct timeval *tp, const struct timezone *tzp)
{
return _settimeofday_r(_REENT, tp, tzp);
}

View file

@ -0,0 +1,383 @@
#include <errno.h>
#include <reent.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/stat.h>
#include "bflb_uart.h"
/** @addtogroup ttyin_config
-----------------------------------------------------------------------------
* @{
----------------------------------------------------------------------------*/
/*!< the following configuration is only valid for tty input */
/*!< block mode or nonblock mode */
#ifndef CONFIG_TTYIN_NONBLOCK
#define CONFIG_TTYIN_NONBLOCK 0
#endif
/*!< use raw data */
#ifndef CONFIG_TTYIN_RAWMODE
#define CONFIG_TTYIN_RAWMODE 0
#endif
/*!< map crnl -> nl */
#ifndef CONFIG_TTYIN_CRNL2NL
#define CONFIG_TTYIN_CRNL2NL 1
#endif
/*!< map crnl -> cr */
#ifndef CONFIG_TTYIN_CRNL2CR
#define CONFIG_TTYIN_CRNL2CR 0
#endif
/*!< map nlcr -> nl */
#ifndef CONFIG_TTYIN_NLCR2NL
#define CONFIG_TTYIN_NLCR2NL 1
#endif
/*!< map nlcr -> cr */
#ifndef CONFIG_TTYIN_NLCR2CR
#define CONFIG_TTYIN_NLCR2CR 0
#endif
/*!< map cr -> nl */
#ifndef CONFIG_TTYIN_CR2NL
#define CONFIG_TTYIN_CR2NL 1
#endif
/*!< map nl -> cr */
#ifndef CONFIG_TTYIN_NL2CR
#define CONFIG_TTYIN_NL2CR 0
#endif
/*---------------------------------------------------------------------------
* @} ttyin_config
----------------------------------------------------------------------------*/
/** @addtogroup ttyin_fifo
-----------------------------------------------------------------------------
* @{
----------------------------------------------------------------------------*/
struct _ttyin_fifo {
volatile uint32_t in;
volatile uint32_t out;
volatile uint32_t mask;
volatile void *data;
};
/*****************************************************************************
* @brief macro to define and init a fifo object
*
* @param name name of the fifo
* @param size the number of elements in the fifo,
* this must be a power of 2 !!!
*****************************************************************************/
#define TTYIN_FIFO_DEFINE(name, size) \
struct { \
struct _ttyin_fifo fifo; \
uint8_t buf[(((size) < 2) || ((size) & ((size)-1))) ? -1 : (size)]; \
}(name) = { \
.fifo.in = 0, \
.fifo.out = 0, \
.fifo.mask = (size)-1, \
.fifo.data = (name).buf \
}
/*****************************************************************************
* @brief get fifo used space size
*
* @param[in] fifo fifo object
*
* @retval uint32_t used space size
*****************************************************************************/
static inline uint32_t _ttyin_fifo_used(struct _ttyin_fifo *fifo)
{
return fifo->in - fifo->out;
}
/*****************************************************************************
* @brief get fifo unused space size
*
* @param[in] fifo fifo object
*
* @retval uint32_t unused space size
*****************************************************************************/
static inline uint32_t _ttyin_fifo_free(struct _ttyin_fifo *fifo)
{
return (fifo->mask + 1) - (fifo->in - fifo->out);
}
/*****************************************************************************
* @brief returns true if the fifo is full
*
* @param[in] fifo fifo object
*
* @retval bool
*****************************************************************************/
static inline bool _ttyin_fifo_is_full(struct _ttyin_fifo *fifo)
{
return _ttyin_fifo_used(fifo) > fifo->mask;
}
/*****************************************************************************
* @brief returns true if the fifo is empty
*
* @param[in] name fifo object
*
* @retval bool
*****************************************************************************/
static inline bool _ttyin_fifo_is_empty(struct _ttyin_fifo *fifo)
{
return fifo->in == fifo->out;
}
/*****************************************************************************
* @brief put byte into the fifo
*
* @param[in] name fifo object
* @param[in] ch data
*
*****************************************************************************/
static inline void _ttyin_fifo_put(struct _ttyin_fifo *fifo, uint8_t ch)
{
#if defined(CONFIG_TTYIN_CR2NL) && CONFIG_TTYIN_CR2NL
ch = (ch == '\r') ? '\n' : ch;
#elif defined(CONFIG_TTYIN_NL2CR) && CONFIG_TTYIN_NL2CR
ch = (ch == '\n') ? '\r' : ch;
#endif
if (!_ttyin_fifo_is_full(fifo)) {
((volatile uint8_t *)(fifo->data))[fifo->in & fifo->mask] = ch;
fifo->in++;
}
}
/*****************************************************************************
* @brief get byte from the fifo
*
* @param[in] fifo fifo object
*
* @retval int data
*****************************************************************************/
static inline int _ttyin_fifo_get(struct _ttyin_fifo *fifo)
{
register int ch = -1;
#if defined(CONFIG_TTYIN_NONBLOCK) && CONFIG_TTYIN_NONBLOCK
if (!_ttyin_fifo_is_empty(fifo))
#else
while (_ttyin_fifo_is_empty(fifo)) {}
#endif
{
ch = ((volatile uint8_t *)(fifo->data))[fifo->out & fifo->mask];
fifo->out++;
}
return ch;
}
#define ttyin_fifo_used(__fifo) _ttyin_fifo_used(&((__fifo).fifo))
#define ttyin_fifo_free(__fifo) _ttyin_fifo_free(&((__fifo).fifo))
#define ttyin_fifo_is_full(__fifo) _ttyin_fifo_is_full(&((__fifo).fifo))
#define ttyin_fifo_is_empty(__fifo) _ttyin_fifo_is_empty(&((__fifo).fifo))
#define ttyin_fifo_put(__fifo, __ch) _ttyin_fifo_put(&((__fifo).fifo), (__ch))
#define ttyin_fifo_get(__fifo) _ttyin_fifo_get(&((__fifo).fifo))
/*---------------------------------------------------------------------------
* @} ttyin_fifo
----------------------------------------------------------------------------*/
struct bflb_device_s *console = NULL;
static TTYIN_FIFO_DEFINE(stdin_fifo, 512);
void console_receive_isr(int irq, void *arg)
{
uint32_t intstatus = bflb_uart_get_intstatus(console);
if (intstatus & UART_INTSTS_RX_FIFO) {
while (bflb_uart_rxavailable(console)) {
ttyin_fifo_put(stdin_fifo, bflb_uart_getchar(console));
}
}
if (intstatus & UART_INTSTS_RTO) {
while (bflb_uart_rxavailable(console)) {
ttyin_fifo_put(stdin_fifo, bflb_uart_getchar(console));
}
bflb_uart_int_clear(console, UART_INTCLR_RTO);
}
}
void bflb_uart_set_console(struct bflb_device_s *dev)
{
console = dev;
bflb_uart_rxint_mask(console, false);
bflb_irq_attach(console->irq_num, console_receive_isr, console);
bflb_irq_enable(console->irq_num);
}
/*****************************************************************************
* @brief open
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path string pointer
* @param[in] flags open mode in fcntl.h
* @param[in] mode permission mode
*
* @retval int >=0:fd -1:Error
*****************************************************************************/
int _open_tty_r(struct _reent *reent, const char *path, int flags, int mode)
{
if (strncmp("/dev/null", path, 9) == 0) {
return 0x3ff;
} else if (strncmp("/dev/stdin", path, 10) == 0) {
return 0;
} else if (strncmp("/dev/stdout", path, 11) == 0) {
return 1;
} else if (strncmp("/dev/stderr", path, 11) == 0) {
return 2;
} else {
reent->_errno = ENOENT;
return -1;
}
}
/*****************************************************************************
* @brief close
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _close_tty_r(struct _reent *reent, int fd)
{
if (fd == 0x3ff) {
return 0;
} else if (fd == 0) {
return 0;
} else if (fd == 1) {
return 0;
} else if (fd == 2) {
return 0;
} else {
reent->_errno = EBADF;
return -1;
}
}
/*****************************************************************************
* @brief read
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes read
*
* @retval _ssize_t actual number of bytes read
*****************************************************************************/
_ssize_t _read_tty_r(struct _reent *reent, int fd, void *ptr, size_t size)
{
if (fd == 0x3ff) {
return -1;
} else if (fd == 0) {
int ch;
for (size_t i = 0; i < size; i++) {
if ((ch = ttyin_fifo_get(stdin_fifo)) <= -1) {
return i;
} else {
((uint8_t *)ptr)[i] = ch;
bflb_uart_putchar(console, ch);
}
}
return size;
} else if ((fd == 1) || (fd == 2)) {
reent->_errno = EACCES;
return -1;
} else {
reent->_errno = EBADF;
return -1;
}
}
/*****************************************************************************
* @brief write
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes write
*
* @retval _ssize_t actual number of bytes write
*****************************************************************************/
_ssize_t _write_tty_r(struct _reent *reent, int fd, const void *ptr, size_t size)
{
if (fd == 0x3ff) {
return size;
} else if (fd == 0) {
reent->_errno = EACCES;
return -1;
} else if ((fd == 1) || (fd == 2)) {
for (size_t i = 0; i < size; i++) {
bflb_uart_putchar(console, ((uint8_t *)ptr)[i]);
}
return size;
} else {
reent->_errno = EBADF;
return -1;
}
}
/*****************************************************************************
* @brief fstat (not supported)
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _fstat_tty_r(struct _reent *reent, int fd, struct stat *st)
{
if (fd == 0x3ff) {
st->st_mode = 0666 | S_IFCHR;
return 0;
} else if (fd == 0) {
st->st_mode = 0444 | S_IFCHR;
return 0;
} else if ((fd == 1) || (fd == 2)) {
st->st_mode = 0222 | S_IFCHR;
return 0;
} else {
reent->_errno = EBADF;
return -1;
}
}
/*****************************************************************************
* @brief stat
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _stat_tty_r(struct _reent *reent, const char *path, struct stat *st)
{
if (strncmp("/dev/null", path, 9) == 0) {
return _fstat_tty_r(reent, 0x3ff, st);
} else if (strncmp("/dev/stdin", path, 10) == 0) {
return _fstat_tty_r(reent, 0, st);
} else if (strncmp("/dev/stdout", path, 11) == 0) {
return _fstat_tty_r(reent, 1, st);
} else if (strncmp("/dev/stderr", path, 11) == 0) {
return _fstat_tty_r(reent, 2, st);
} else {
reent->_errno = EBADF;
return -1;
}
}

View file

@ -0,0 +1,538 @@
/* syscalls.c -- renntrant syscalls for bouffalo sdk.
*/
#include <errno.h>
#include <reent.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
/*****************************************************************************
* @brief get thread reent
*
*
* @retval struct _reent* pointer to reentrant struct
*****************************************************************************/
struct _reent *__getreent(void)
{
return _impure_ptr;
}
/*****************************************************************************
* @brief exit
*
* @param[in] rc exit status
*
*****************************************************************************/
void _exit(int rc)
{
fprintf(stderr, "exit status %d\r\n", rc);
for (;;) {}
}
void exit(int code)
{
_exit(code);
}
/*****************************************************************************
* @brief execve (not supported)
*
* @param[in] reent
* @param[in] name
* @param[in] argv
* @param[in] env
*
* @retval int
*****************************************************************************/
int _execve_r(struct _reent *reent, const char *name, char *const *argv, char *const *env)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief fork (not supported)
*
* @param[in] reent
*
* @retval int
*****************************************************************************/
int _fork_r(struct _reent *reent)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief getpid (not supported)
*
* @param[in] reent
*
* @retval int
*****************************************************************************/
int _getpid_r(struct _reent *reent)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief kill (not supported)
*
* @param[in] reent
* @param[in] pid
* @param[in] sig
*
* @retval int
*****************************************************************************/
int _kill_r(struct _reent *reent, int pid, int sig)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief wait (not supported)
*
* @param[in] reent
* @param[in] status
*
* @retval int
*****************************************************************************/
int _wait_r(struct _reent *reent, int *status)
{
reent->_errno = ENOSYS;
return -1;
}
/** @addtogroup file_stub
-----------------------------------------------------------------------------
* @{
----------------------------------------------------------------------------*/
extern int _open_tty_r(struct _reent *reent, const char *path, int flags, int mode);
extern int _close_tty_r(struct _reent *reent, int fd);
extern _ssize_t _read_tty_r(struct _reent *reent, int fd, void *ptr, size_t size);
extern _ssize_t _write_tty_r(struct _reent *reent, int fd, const void *ptr, size_t size);
extern int _fstat_tty_r(struct _reent *reent, int fd, struct stat *st);
extern int _stat_tty_r(struct _reent *reent, const char *path, struct stat *st);
extern int _open_file_r(struct _reent *reent, const char *path, int flags, int mode);
extern int _close_file_r(struct _reent *reent, int fd);
extern _ssize_t _read_file_r(struct _reent *reent, int fd, void *ptr, size_t size);
extern _ssize_t _write_file_r(struct _reent *reent, int fd, const void *ptr, size_t size);
extern _off_t _lseek_file_r(struct _reent *reent, int fd, _off_t offset, int whence);
extern int _rename_file_r(struct _reent *reent, const char *oldname, const char *newname);
extern int _unlink_file_r(struct _reent *reent, const char *path);
extern int _fstat_file_r(struct _reent *reent, int fd, struct stat *st);
extern int _stat_file_r(struct _reent *reent, const char *path, struct stat *st);
extern int _mkdir_file_r(struct _reent *reent, const char *path, int mode);
extern int _rmdir_file_r(struct _reent *reent, const char *path);
extern int _chmod_file_r(struct _reent *reent, const char *path, mode_t mode);
extern int _chdir_file_r(struct _reent *reent, const char *path);
extern char *_getcwd_file_r(struct _reent *reent, char *buf, size_t size);
extern int _chroot_file_r(struct _reent *reent, const char *path);
/*****************************************************************************
* @brief chekc fd is a tty
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
*
* @retval int 0:not tty 1:tty
*****************************************************************************/
int _isatty_r(struct _reent *reent, int fd)
{
struct stat buf;
if (_fstat_r(reent, fd, &buf) < 0) {
reent->_errno = EBADF;
return 0;
}
if (S_ISCHR(buf.st_mode)) {
return 1;
}
reent->_errno = ENOTTY;
return 0;
}
/*****************************************************************************
* @brief open
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path string pointer
* @param[in] flags open mode in fcntl.h
* @param[in] mode permission mode
*
* @retval int >=0:fd -1:Error
*****************************************************************************/
int _open_r(struct _reent *reent, const char *path, int flags, int mode)
{
if (path == NULL) {
reent->_errno = EINVAL;
return -1;
}
if (strncmp("/dev", path, 4) == 0) {
return _open_tty_r(reent, path, flags, mode);
} else {
return _open_file_r(reent, path, flags, mode);
}
}
/*****************************************************************************
* @brief close
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _close_r(struct _reent *reent, int fd)
{
if ((fd & 0x4000) == 0) {
return _close_tty_r(reent, fd);
} else {
return _close_file_r(reent, fd);
}
}
/*****************************************************************************
* @brief read
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes read
*
* @retval _ssize_t actual number of bytes read
*****************************************************************************/
_ssize_t _read_r(struct _reent *reent, int fd, void *ptr, size_t size)
{
if (ptr == NULL) {
reent->_errno = EINVAL;
return 0;
}
if ((fd & 0x4000) == 0) {
return _read_tty_r(reent, fd, ptr, size);
} else {
return _read_file_r(reent, fd, ptr, size);
}
}
/*****************************************************************************
* @brief write
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] ptr pointer to buffer
* @param[in] size number of bytes write
*
* @retval _ssize_t actual number of bytes write
*****************************************************************************/
_ssize_t _write_r(struct _reent *reent, int fd, const void *ptr, size_t size)
{
if (ptr == NULL) {
reent->_errno = EINVAL;
return 0;
}
if ((fd & 0x4000) == 0) {
return _write_tty_r(reent, fd, ptr, size);
} else {
return _write_file_r(reent, fd, ptr, size);
}
}
/*****************************************************************************
* @brief lseek
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] offset number of offset bytes
* @param[in] whence offset type
*
* @retval _off_t absolute offset of file pointer
*****************************************************************************/
_off_t _lseek_r(struct _reent *reent, int fd, _off_t offset, int whence)
{
if ((fd & 0x4000) == 0) {
reent->_errno = ESPIPE;
return -1;
} else {
return _lseek_file_r(reent, fd, offset, whence);
}
}
/*****************************************************************************
* @brief rename
*
* @param[in] reent pointer to reentrant struct
* @param[in] oldname old file path
* @param[in] newname new file path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _rename_r(struct _reent *reent, const char *oldname, const char *newname)
{
if ((oldname == NULL) || (newname == NULL)) {
reent->_errno = EINVAL;
return -1;
}
return _rename_file_r(reent, oldname, newname);
}
/*****************************************************************************
* @brief unlink
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _unlink_r(struct _reent *reent, const char *path)
{
if (path == NULL) {
reent->_errno = EINVAL;
return -1;
}
return _unlink_file_r(reent, path);
}
/*****************************************************************************
* @brief link (not supported)
*
* @param[in] reent pointer to reentrant struct
* @param[in] existing old file path
* @param[in] new new file path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _link_r(struct _reent *reent, const char *existing, const char *new)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief fcntl (not supported)
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[in] cmd command
* @param[in] arg argument
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _fcntl_r(struct _reent *reent, int fd, int cmd, int arg)
{
reent->_errno = ENOSYS;
return -1;
}
/*****************************************************************************
* @brief fstat (not supported)
*
* @param[in] reent pointer to reentrant struct
* @param[in] fd file descriptors
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _fstat_r(struct _reent *reent, int fd, struct stat *st)
{
if (st == NULL) {
reent->_errno = EINVAL;
return -1;
}
memset(st, 0, sizeof(*st));
if ((fd & 0x4000) == 0) {
return _fstat_tty_r(reent, fd, st);
} else {
return _fstat_file_r(reent, fd, st);
}
}
/*****************************************************************************
* @brief stat
*
* @param[in] reent pointer to reentrant struct
* @param[in] path file path
* @param[out] st file stat
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _stat_r(struct _reent *reent, const char *path, struct stat *st)
{
if ((path == NULL) || (st == NULL)) {
reent->_errno = EINVAL;
return -1;
}
memset(st, 0, sizeof(*st));
if (strncmp("/dev", path, 4) == 0) {
return _stat_tty_r(reent, path, st);
} else {
return _stat_file_r(reent, path, st);
}
}
/*****************************************************************************
* @brief mkdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
* @param[in] mode mode
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _mkdir_r(struct _reent *reent, const char *path, int mode)
{
if (path == NULL) {
reent->_errno = EINVAL;
return -1;
}
return _mkdir_file_r(reent, path, mode);
}
int mkdir(const char *path, mode_t mode)
{
return _mkdir_r(_REENT, path, mode);
}
/*****************************************************************************
* @brief rmdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _rmdir_r(struct _reent *reent, const char *path)
{
if (path == NULL) {
reent->_errno = EINVAL;
return -1;
}
return _rmdir_file_r(reent, path);
}
int rmdir(const char *path)
{
return _rmdir_r(_REENT, path);
}
/*****************************************************************************
* @brief chmod
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
* @param[in] mode mode
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chmod_r(struct _reent *reent, const char *path, mode_t mode)
{
if (path == NULL) {
reent->_errno = EINVAL;
return -1;
}
if (strncmp("/dev", path, 4) == 0) {
reent->_errno = EPERM;
return -1;
} else {
return _chmod_file_r(reent, path, mode);
}
}
int chmod(const char *path, mode_t mode)
{
return _chmod_r(_REENT, path, mode);
}
/*****************************************************************************
* @brief chdir
*
* @param[in] reent pointer to reentrant struct
* @param[in] path dir path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chdir_r(struct _reent *reent, const char *path)
{
if (path == NULL) {
reent->_errno = EINVAL;
return -1;
}
return _chdir_file_r(reent, path);
}
int chdir(const char *path)
{
return _chdir_r(_REENT, path);
}
/*****************************************************************************
* @brief getcwd
*
* @param[in] reent pointer to reentrant struct
* @param[in] buf buf for path
* @param[in] size buf size
*
* @retval char* pointer to path string NULL:Error
*****************************************************************************/
char *_getcwd_r(struct _reent *reent, char *buf, size_t size)
{
if (buf == NULL) {
reent->_errno = EINVAL;
return NULL;
}
return _getcwd_file_r(reent, buf, size);
}
char *getcwd(char *buf, size_t size)
{
return _getcwd_r(_REENT, buf, size);
}
/*****************************************************************************
* @brief chroot
*
* @param[in] path path
*
* @retval int 0:Success -1:Error
*****************************************************************************/
int _chroot_r(struct _reent *reent, const char *path)
{
if (path == NULL) {
reent->_errno = EINVAL;
return 0;
}
return _chroot_file_r(reent, path);
}
int chroot(const char *path)
{
return _chroot_r(_REENT, path);
}
/*---------------------------------------------------------------------------
* @} file_stub
----------------------------------------------------------------------------*/

View file

@ -0,0 +1,144 @@
#include <limits.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/stat.h>
#undef errno
int errno;
char *__env[1] = { 0 };
char **environ = __env;
void _exit(int rc)
{
for (;;)
;
}
int _chown(const char *path, uid_t owner, gid_t group)
{
errno = ENOSYS;
return -1;
}
int _close(int fildes)
{
errno = ENOSYS;
return -1;
}
int _execve(char *name, char **argv, char **env)
{
errno = ENOSYS;
return -1;
}
int _fork(void)
{
errno = ENOSYS;
return -1;
}
int _fstat(int fildes, struct stat *st)
{
errno = ENOSYS;
return -1;
}
int _getpid(void)
{
errno = ENOSYS;
return -1;
}
int _gettimeofday(struct timeval *ptimeval, void *ptimezone)
{
errno = ENOSYS;
return -1;
}
int _isatty(int file)
{
errno = ENOSYS;
return 0;
}
int _kill(int pid, int sig)
{
errno = ENOSYS;
return -1;
}
int _link(char *existing, char *new)
{
errno = ENOSYS;
return -1;
}
int _lseek(int file, int ptr, int dir)
{
errno = ENOSYS;
return -1;
}
int _open(char *file, int flags, int mode)
{
errno = ENOSYS;
return -1;
}
int _read(int file, char *ptr, int len)
{
errno = ENOSYS;
return -1;
}
int _readlink(const char *path, char *buf, size_t bufsize)
{
errno = ENOSYS;
return -1;
}
void *_sbrk(int incr)
{
errno = ENOSYS;
return NULL;
}
int _stat(const char *file, struct stat *st)
{
errno = ENOSYS;
return -1;
}
int _symlink(const char *path1, const char *path2)
{
errno = ENOSYS;
return -1;
}
clock_t _times(struct tms *buf)
{
errno = ENOSYS;
return -1;
}
int _unlink(char *name)
{
errno = ENOSYS;
return -1;
}
int _wait(int *status)
{
errno = ENOSYS;
return -1;
}
int _write(int file, char *ptr, int len)
{
errno = ENOSYS;
return -1;
}

25
components/libc/sprintf.c Normal file
View file

@ -0,0 +1,25 @@
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
/**
* This function will fill a formatted string to buffer
*
* @param buf the buffer to save formatted string.
*
* @param format is the format parameters.
*
* @return The number of characters actually written to buffer.
*/
int sprintf(char *buf, const char *format, ...)
{
int32_t n;
va_list arg_ptr;
va_start(arg_ptr, format);
n = vsprintf(buf, format, arg_ptr);
va_end(arg_ptr);
return n;
}

View file

@ -1,119 +0,0 @@
#include <errno.h>
#include <stdarg.h>
#include "bflb_uart.h"
#include "vlibc_stdio.h"
#define IOCONSOLE_IO ((uint32_t)0x00000001)
#define IOCONSOLE_NAME "console"
struct bflb_device_s *console = NULL;
int printf(const char *fmt, ...)
{
char print_buf[1024];
uint32_t len;
va_list ap;
if (console == NULL) {
return 0;
}
va_start(ap, fmt);
len = vsnprintf(print_buf, sizeof(print_buf), fmt, ap);
va_end(ap);
len = (len > sizeof(print_buf)) ? sizeof(print_buf) : len;
bflb_uart_put(console, (uint8_t *)print_buf, len);
return 0;
}
__WEAK uint32_t __vlibc_io_init(const char *name, uint8_t mode)
{
(void)mode;
if (strcmp(name, IOCONSOLE_NAME) == 0) {
return IOCONSOLE_IO;
} else {
}
return ENOENT;
}
__WEAK uint32_t __vlibc_io_deinit(struct __vlibc_io *io)
{
if (io->dev == IOCONSOLE_IO) {
return IOCONSOLE_IO;
} else {
}
return EOF;
}
__WEAK size_t __vlibc_io_mem2dev(struct __vlibc_io *io, const void *ptr, size_t size)
{
if (io->dev == IOCONSOLE_IO) {
for (size_t i = 0; i < size; i++) {
bflb_uart_putchar(console, ((char *)ptr)[i]);
}
return size;
} else {
}
return 0;
}
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
void bflb_dump_hex(const void *ptr, uint32_t buflen)
{
unsigned char *buf = (unsigned char *)ptr;
int i, j;
for (i = 0; i < buflen; i += 16) {
printf("%08X:", i);
for (j = 0; j < 16; j++)
if (i + j < buflen) {
if ((j % 8) == 0) {
printf(" ");
}
printf("%02X ", buf[i + j]);
} else
printf(" ");
printf(" ");
for (j = 0; j < 16; j++)
if (i + j < buflen)
printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
printf("\n");
}
}
void bflb_reg_dump(uint32_t addr)
{
printf("%08lx[31:0]=%08lx\r\n", addr, *(volatile uint32_t *)(uintptr_t)(addr));
}
int bflb_data_compare(const uint8_t *expected, uint8_t *input, uint32_t len)
{
int i = 0;
for (i = 0; i < len; i++) {
if (input[i] != expected[i]) {
printf("Compare fail at %d,input %02x, but expect %02x\r\n", i, input[i], expected[i]);
return -1;
}
}
return 0;
}
void bflb_uart_set_console(struct bflb_device_s *dev)
{
console = dev;
/*!< vlibc_stdout and vlibc_stderr should config by user */
// vlibc_stdout = vlibc_fopen("<" IOCONSOLE_NAME, "w");
// vlibc_setvbuf(vlibc_stdout, NULL, _IONBF, 0);
// vlibc_stderr = vlibc_stdout;
}

File diff suppressed because it is too large Load diff

View file

@ -1,170 +0,0 @@
#ifndef _VLIBC_STDIO_H
#define _VLIBC_STDIO_H
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#ifdef CONFIG_VLIBC_FATFS
#include "ff.h"
#endif
/** @addtogroup Types
* @{
*/
struct __vlibc_io {
char *bg; /*!< buffer begin pointer */
char *wp; /*!< buffer write pointer */
char *rp; /*!< buffer read pointer */
char *ed; /*!< buffer end pointer */
uint32_t dev; /*!< io device */
uint8_t flag; /*!< io flag */
uint8_t vbuf; /*!< buffer mode */
uint8_t abuf; /*!< buffer auto */
uint8_t err; /*!< error */
};
typedef struct {
uint32_t magic;
union {
struct __vlibc_io *io;
#ifdef CONFIG_VLIBC_FATFS
FIL *file;
#else
int *file;
#endif
};
} vlibc_file_t;
/*!< file type */
#define VLIBC_FILE vlibc_file_t
/**
* @}
*/
/** @addtogroup stdio extra
* @{
*/
extern uint32_t __vlibc_io_init(const char *name, uint8_t mode);
extern uint32_t __vlibc_io_deinit(struct __vlibc_io *io);
extern size_t __vlibc_io_mem2dev(struct __vlibc_io *io, const void *ptr, size_t size);
extern size_t __vlibc_io_dev2mem(struct __vlibc_io *io, void *ptr, size_t size);
/**
* @}
*/
/** @addtogroup Marcos
* @{
*/
#define _VLIBC_MAGIC_MASK ((unsigned int)(0xffff0000))
#define _VLIBC_IO_MAGIC_CODE ((unsigned int)(0x10de0000))
#define _VLIBC_FILE_MAGIC_CODE ((unsigned int)(0xf11e0000))
#define _VLIBC_IO_WRITE ((unsigned char)(0x01))
#define _VLIBC_IO_READ ((unsigned char)(0x02))
/*!< io buffer size */
#define VLIBC_BUFSIZ 256
/*!< file stack buffer size */
#define VLIBC_FBUFSIZ 256
/*!< max open file count at the same time */
#define VLIBC_FOPEN_MAX 20
/*!< max file name length */
#define VLIBC_FILENAME_MAX 256
/*!< max io name length */
#define _VLIBC_IONAME_MAX 32
/*!< max tmpnam file name length */
#define VLIBC_L_tmpnam VLIBC_FILENAME_MAX
/*!< max tmpnam rand name */
#define VLIBC_TMP_MAX 0
/*!< stand io */
extern vlibc_file_t *__vlibc_stdio_fileptrs[3];
#define vlibc_stdin (__vlibc_stdio_fileptrs[0])
#define vlibc_stdout (__vlibc_stdio_fileptrs[1])
#define vlibc_stderr (__vlibc_stdio_fileptrs[2])
/**
* @}
*/
/** @addtogroup stdio functions
* @{
*/
extern void vlibc_clearerr(VLIBC_FILE *);
extern int vlibc_feof(VLIBC_FILE *);
extern int vlibc_ferror(VLIBC_FILE *);
extern VLIBC_FILE *vlibc_fopen(const char *, const char *);
extern VLIBC_FILE *vlibc_freopen(const char *, const char *, VLIBC_FILE *);
extern int vlibc_fclose(VLIBC_FILE *);
extern size_t vlibc_fread(void *, size_t, size_t, VLIBC_FILE *);
extern size_t vlibc_fwrite(const void *, size_t, size_t, VLIBC_FILE *);
extern int vlibc_fflush(VLIBC_FILE *);
extern int vlibc_fseek(VLIBC_FILE *, long, int);
extern long vlibc_ftell(VLIBC_FILE *);
extern int vlibc_remove(const char *);
extern int vlibc_rename(const char *, const char *);
extern void vlibc_rewind(VLIBC_FILE *);
extern void vlibc_setbuf(VLIBC_FILE *, char *);
extern int vlibc_setvbuf(VLIBC_FILE *, char *, int, size_t);
extern VLIBC_FILE *vlibc_tmpfile(void);
extern char *vlibc_tmpnam(char *);
extern int vlibc_fprintf(VLIBC_FILE *, const char *, ...);
extern int vlibc_printf(const char *, ...);
extern int vlibc_sprintf(char *, const char *, ...);
extern int vlibc_snprintf(char *, size_t, const char *, ...);
extern int vlibc_vfprintf(VLIBC_FILE *, const char *, va_list);
extern int vlibc_vprintf(const char *, va_list);
extern int vlibc_vsprintf(char *, const char *, va_list);
extern int vlibc_vsnprintf(char *, size_t, const char *, va_list);
extern int vlibc_fscanf(VLIBC_FILE *, const char *, ...);
extern int vlibc_scanf(const char *, ...);
extern int vlibc_sscanf(const char *, const char *, ...);
extern int vlibc_vfscanf(VLIBC_FILE *, const char *, va_list);
extern int vlibc_vscanf(const char *, va_list);
extern int vlibc_vsscanf(const char *, const char *, va_list);
extern int vlibc_fgetc(VLIBC_FILE *);
extern char *vlibc_fgets(char *, int, VLIBC_FILE *);
extern int vlibc_fputc(int, VLIBC_FILE *);
extern int vlibc_fputs(const char *, VLIBC_FILE *);
extern int vlibc_getc(VLIBC_FILE *);
extern int vlibc_getchar(void);
extern char *vlibc_gets(char *);
extern int vlibc_putc(int, VLIBC_FILE *);
extern int vlibc_putchar(int);
extern int vlibc_puts(const char *);
extern void vlibc_perror(const char *);
/**
* @}
*/
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
/**
* This function will fill a formatted string to buffer.
*
* @param buf is the buffer to save formatted string.
*
* @param format is the format parameters.
*
* @param arg_ptr is a list of variable parameters.
*
* @return The number of characters actually written to buffer.
*/
int vsprintf(char *buf, const char *format, va_list arg_ptr)
{
return vsnprintf(buf, (size_t) - 1, format, arg_ptr);
}

View file

@ -4,8 +4,8 @@ sdk_add_compile_definitions(-DCONFIG_LWIP)
sdk_library_add_sources(src/apps/lwiperf/lwiperf.c)
sdk_library_add_sources(src/apps/http/fs.c)
sdk_library_add_sources(src/apps/http/fsdata_custom.c)
sdk_library_add_sources(src/apps/http/fsdata.c)
# sdk_library_add_sources(src/apps/http/fsdata_custom.c)
# sdk_library_add_sources(src/apps/http/fsdata.c)
# sdk_library_add_sources(src/apps/http/httpd.c)
sdk_library_add_sources(src/api/api_lib.c)

View file

@ -1,4 +1,8 @@
sdk_generate_library()
sdk_add_include_directories(core/inc)
sdk_add_include_directories(port/inc)
sdk_library_add_sources(core/src/lapi.c)
sdk_library_add_sources(core/src/lauxlib.c)
sdk_library_add_sources(core/src/lbaselib.c)
@ -27,14 +31,12 @@ sdk_library_add_sources(core/src/lstrlib.c)
sdk_library_add_sources(core/src/ltable.c)
sdk_library_add_sources(core/src/ltablib.c)
sdk_library_add_sources(core/src/ltm.c)
sdk_library_add_sources(core/src/luaport.c)
sdk_library_add_sources(core/src/lundump.c)
sdk_library_add_sources(core/src/lutf8lib.c)
sdk_library_add_sources(core/src/lvm.c)
sdk_library_add_sources(core/src/lzio.c)
sdk_library_add_sources(start/lua_start.c)
sdk_add_include_directories(core/inc)
sdk_add_compile_definitions(-DCONFIG_LUA)
sdk_library_add_sources(start/lua.c)
if(CONFIG_LUA_LHAL)
sdk_library_add_sources(lhal/llib_init.c)
@ -44,3 +46,5 @@ sdk_library_add_sources(lhal/llib_gpio.c)
sdk_add_include_directories(lhal)
sdk_add_compile_definitions(-DCONFIG_LUA_LHAL)
endif()
sdk_add_compile_definitions(-DCONFIG_LUA)

View file

@ -159,7 +159,7 @@ LUALIB_API void(luaL_requiref)(lua_State *L, const char *modname,
#if defined LUAI_ASSERT
#include <assert.h>
#define lua_assert(c) assert(c)
#define lua_assert(c) luaport_assert(c)
#else
#define lua_assert(c) ((void)0)
#endif
@ -219,10 +219,10 @@ LUALIB_API char *(luaL_buffinitsize)(lua_State *L, luaL_Buffer *B, size_t sz);
** after that initial structure).
*/
#define LUA_FILEHANDLE LUAPORT_FILEHANDLE
#define LUA_FILEHANDLE "FILE*"
typedef struct luaL_Stream {
LUAPORT_FILE *f; /* stream (NULL for incompletely created streams) */
FILE *f; /* stream (NULL for incompletely created streams) */
lua_CFunction closef; /* to close stream (NULL for closed streams) */
} luaL_Stream;
@ -236,7 +236,7 @@ typedef struct luaL_Stream {
/* print a string */
#if !defined(lua_writestring)
#define lua_writestring(s, l) luaport_fwirte((s), sizeof(char), (l), luaport_stdout)
#define lua_writestring(s, l) luaport_fwrite((s), sizeof(char), (l), luaport_stdout)
#endif
/* print a newline and flush the output */

View file

@ -9,10 +9,10 @@
#include "lobject.h"
#define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \
#define sizeCclosure(n) (cast_int(luaport_offsetof(CClosure, upvalue)) + \
cast_int(sizeof(TValue)) * (n))
#define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \
#define sizeLclosure(n) (cast_int(luaport_offsetof(LClosure, upvals)) + \
cast_int(sizeof(TValue *)) * (n))
/* test whether thread is in 'twups' list */

View file

@ -75,7 +75,7 @@ typedef LUAI_UACINT l_uacInt;
#if defined LUAI_ASSERT
#undef NDEBUG
#include <assert.h>
#define lua_assert(c) assert(c)
#define lua_assert(c) luaport_assert(c)
#endif
#if defined(lua_assert)

View file

@ -473,7 +473,7 @@ typedef struct Udata0 {
/* compute the offset of the memory area of a userdata */
#define udatamemoffset(nuv) \
((nuv) == 0 ? offsetof(Udata0, bindata) : offsetof(Udata, uv) + (sizeof(UValue) * (nuv)))
((nuv) == 0 ? luaport_offsetof(Udata0, bindata) : luaport_offsetof(Udata, uv) + (sizeof(UValue) * (nuv)))
/* get the address of the memory block inside 'Udata' */
#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue))

View file

@ -113,8 +113,9 @@ struct lua_longjmp; /* defined in ldo.c */
** is thread safe
*/
#if !defined(l_signalT)
#include <signal.h>
#define l_signalT sig_atomic_t
// #include <signal.h>
// #define l_signalT sig_atomic_t
#define l_signalT int
#endif
/*

View file

@ -21,7 +21,7 @@
** Size of a TString: Size of the header plus space for the string
** itself (including final '\0').
*/
#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char))
#define sizelstring(l) (luaport_offsetof(TString, contents) + ((l) + 1) * sizeof(char))
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s) / sizeof(char)) - 1))

View file

@ -0,0 +1,9 @@
// lua.hpp
// Lua header files for C++
// <<extern "C">> not supplied automatically because Lua also compiles as C++
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

View file

@ -75,7 +75,7 @@ static int pushglobalfuncname(lua_State *L, lua_Debug *ar)
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
if (findfield(L, top + 1, 2)) {
const char *name = lua_tostring(L, -1);
if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */
if (luaport_strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */
lua_pushstring(L, name + 3); /* push name without prefix */
lua_remove(L, -2); /* remove original name */
}
@ -172,7 +172,7 @@ LUALIB_API int luaL_argerror(lua_State *L, int arg, const char *extramsg)
if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
return luaL_error(L, "bad argument #%d (%s)", arg, extramsg);
lua_getinfo(L, "n", &ar);
if (strcmp(ar.namewhat, "method") == 0) {
if (luaport_strcmp(ar.namewhat, "method") == 0) {
arg--; /* do not count 'self' */
if (arg == 0) /* error is in the self argument itself? */
return luaL_error(L, "calling '%s' on bad self (%s)",
@ -238,22 +238,22 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...)
LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname)
{
int en = errno; /* calls to Lua API may change this value */
int en = luaport_errno; /* calls to Lua API may change this value */
if (stat) {
lua_pushboolean(L, 1);
return 1;
} else {
luaL_pushfail(L);
if (fname)
lua_pushfstring(L, "%s: %s", fname, strerror(en));
lua_pushfstring(L, "%s: %s", fname, luaport_strerror(en));
else
lua_pushstring(L, strerror(en));
lua_pushstring(L, luaport_strerror(en));
lua_pushinteger(L, en);
return 3;
}
}
#if !defined(luaport_inspectstat) /* { */
#if !defined(l_inspectstat) /* { */
#if defined(LUA_USE_POSIX)
@ -262,7 +262,7 @@ LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname)
/*
** use appropriate macros to interpret 'pclose' return status
*/
#define luaport_inspectstat(stat, what) \
#define l_inspectstat(stat, what) \
if (WIFEXITED(stat)) { \
stat = WEXITSTATUS(stat); \
} else if (WIFSIGNALED(stat)) { \
@ -272,7 +272,7 @@ LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname)
#else
#define luaport_inspectstat(stat, what) /* no op */
#define l_inspectstat(stat, what) /* no op */
#endif
@ -280,11 +280,11 @@ LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname)
LUALIB_API int luaL_execresult(lua_State *L, int stat)
{
if (stat != 0 && errno != 0) /* error with an 'errno'? */
if (stat != 0 && luaport_errno != 0) /* error with an 'errno'? */
return luaL_fileresult(L, 0, NULL);
else {
const char *what = "exit"; /* type of termination */
luaport_inspectstat(stat, what); /* interpret result */
l_inspectstat(stat, what); /* interpret result */
if (*what == 'e' && stat == 0) /* successful termination? */
lua_pushboolean(L, 1);
else
@ -359,7 +359,7 @@ LUALIB_API int luaL_checkoption(lua_State *L, int arg, const char *def,
luaL_checkstring(L, arg);
int i;
for (i = 0; lst[i]; i++)
if (strcmp(lst[i], name) == 0)
if (luaport_strcmp(lst[i], name) == 0)
return i;
return luaL_argerror(L, arg,
lua_pushfstring(L, "invalid option '%s'", name));
@ -407,7 +407,7 @@ LUALIB_API const char *luaL_optlstring(lua_State *L, int arg,
{
if (lua_isnoneornil(L, arg)) {
if (len)
*len = (def ? strlen(def) : 0);
*len = (def ? luaport_strlen(def) : 0);
return def;
} else
return luaL_checklstring(L, arg, len);
@ -579,7 +579,7 @@ LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
{
luaL_addlstring(B, s, strlen(s));
luaL_addlstring(B, s, luaport_strlen(s));
}
LUALIB_API void luaL_pushresult(luaL_Buffer *B)
@ -697,7 +697,7 @@ LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
typedef struct LoadF {
int n; /* number of pre-read characters */
LUAPORT_FILE *f; /* file being read */
FILE *f; /* file being read */
char buff[BUFSIZ]; /* area for reading file */
} LoadF;
@ -721,7 +721,7 @@ static const char *getF(lua_State *L, void *ud, size_t *size)
static int errfile(lua_State *L, const char *what, int fnameindex)
{
const char *serr = strerror(errno);
const char *serr = luaport_strerror(luaport_errno);
const char *filename = lua_tostring(L, fnameindex) + 1;
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
lua_remove(L, fnameindex);
@ -782,8 +782,7 @@ LUALIB_API int luaL_loadfilex(lua_State *L, const char *filename,
if (skipcomment(&lf, &c)) /* read initial portion */
lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
luaport_fclose(lf.f);
lf.f = luaport_fopen(filename, "rb"); /* reopen in binary mode */
lf.f = luaport_freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL)
return errfile(L, "reopen", fnameindex);
skipcomment(&lf, &c); /* re-read initial portion */
@ -829,7 +828,7 @@ LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t size,
LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
{
return luaL_loadbuffer(L, s, strlen(s), s);
return luaL_loadbuffer(L, s, luaport_strlen(s), s);
}
/* }====================================================== */
@ -980,8 +979,8 @@ LUALIB_API void luaL_addgsub(luaL_Buffer *b, const char *s,
const char *p, const char *r)
{
const char *wild;
size_t l = strlen(p);
while ((wild = strstr(s, p)) != NULL) {
size_t l = luaport_strlen(p);
while ((wild = luaport_strstr(s, p)) != NULL) {
luaL_addlstring(b, s, wild - s); /* push prefix */
luaL_addstring(b, r); /* push replacement in place of pattern */
s = wild + l; /* continue after 'p' */
@ -1039,9 +1038,9 @@ static int checkcontrol(lua_State *L, const char *message, int tocont)
if (tocont || *(message++) != '@') /* not a control message? */
return 0;
else {
if (strcmp(message, "off") == 0)
if (luaport_strcmp(message, "off") == 0)
lua_setwarnf(L, warnfoff, L); /* turn warnings off */
else if (strcmp(message, "on") == 0)
else if (luaport_strcmp(message, "on") == 0)
lua_setwarnf(L, warnfon, L); /* turn warnings on */
return 1; /* it was a control message */
}

View file

@ -59,7 +59,7 @@ static const char *b_str2int(const char *s, int base, lua_Integer *pn)
{
lua_Unsigned n = 0;
int neg = 0;
s += strspn(s, SPACECHARS); /* skip initial spaces */
s += luaport_strspn(s, SPACECHARS); /* skip initial spaces */
if (*s == '-') {
s++;
neg = 1;
@ -75,7 +75,7 @@ static const char *b_str2int(const char *s, int base, lua_Integer *pn)
n = n * base + digit;
s++;
} while (isalnum((unsigned char)*s));
s += strspn(s, SPACECHARS); /* skip trailing spaces */
s += luaport_strspn(s, SPACECHARS); /* skip trailing spaces */
*pn = (lua_Integer)((neg) ? (0u - n) : n);
return s;
}

View file

@ -165,7 +165,7 @@ static int db_getinfo(lua_State *L)
if (!lua_getinfo(L1, options, &ar))
return luaL_argerror(L, arg + 2, "invalid option");
lua_newtable(L); /* table to collect results */
if (strchr(options, 'S')) {
if (luaport_strchr(options, 'S')) {
lua_pushlstring(L, ar.source, ar.srclen);
lua_setfield(L, -2, "source");
settabss(L, "short_src", ar.short_src);
@ -173,26 +173,26 @@ static int db_getinfo(lua_State *L)
settabsi(L, "lastlinedefined", ar.lastlinedefined);
settabss(L, "what", ar.what);
}
if (strchr(options, 'l'))
if (luaport_strchr(options, 'l'))
settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u')) {
if (luaport_strchr(options, 'u')) {
settabsi(L, "nups", ar.nups);
settabsi(L, "nparams", ar.nparams);
settabsb(L, "isvararg", ar.isvararg);
}
if (strchr(options, 'n')) {
if (luaport_strchr(options, 'n')) {
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
}
if (strchr(options, 'r')) {
if (luaport_strchr(options, 'r')) {
settabsi(L, "ftransfer", ar.ftransfer);
settabsi(L, "ntransfer", ar.ntransfer);
}
if (strchr(options, 't'))
if (luaport_strchr(options, 't'))
settabsb(L, "istailcall", ar.istailcall);
if (strchr(options, 'L'))
if (luaport_strchr(options, 'L'))
treatstackoption(L, L1, "activelines");
if (strchr(options, 'f'))
if (luaport_strchr(options, 'f'))
treatstackoption(L, L1, "func");
return 1; /* return table */
}
@ -338,11 +338,11 @@ static void hookf(lua_State *L, lua_Debug *ar)
static int makemask(const char *smask, int count)
{
int mask = 0;
if (strchr(smask, 'c'))
if (luaport_strchr(smask, 'c'))
mask |= LUA_MASKCALL;
if (strchr(smask, 'r'))
if (luaport_strchr(smask, 'r'))
mask |= LUA_MASKRET;
if (strchr(smask, 'l'))
if (luaport_strchr(smask, 'l'))
mask |= LUA_MASKLINE;
if (count > 0)
mask |= LUA_MASKCOUNT;
@ -429,9 +429,9 @@ static int db_debug(lua_State *L)
char buffer[250];
lua_writestringerror("%s", "lua_debug> ");
if (luaport_fgets(buffer, sizeof(buffer), luaport_stdin) == NULL ||
strcmp(buffer, "cont\n") == 0)
luaport_strcmp(buffer, "cont\n") == 0)
return 0;
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
if (luaL_loadbuffer(L, buffer, luaport_strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0))
lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL));
lua_settop(L, 0); /* remove eventual returns */

View file

@ -393,11 +393,11 @@ LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
}
cl = ttisclosure(func) ? clvalue(func) : NULL;
status = auxgetinfo(L, what, ar, cl, ci);
if (strchr(what, 'f')) {
if (luaport_strchr(what, 'f')) {
setobj2s(L, L->top, func);
api_incr_top(L);
}
if (strchr(what, 'L'))
if (luaport_strchr(what, 'L'))
collectvalidlines(L, cl);
lua_unlock(L);
return status;
@ -512,7 +512,7 @@ static const char *gxf(const Proto *p, int pc, Instruction i, int isup)
name = upvalname(p, t);
else
getobjname(p, pc, t, &name);
return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
return (name && luaport_strcmp(name, LUA_ENV) == 0) ? "global" : "field";
}
static const char *getobjname(const Proto *p, int lastpc, int reg,
@ -804,7 +804,7 @@ l_noret luaG_ordererror(lua_State *L, const TValue *p1, const TValue *p2)
{
const char *t1 = luaT_objtypename(L, p1);
const char *t2 = luaT_objtypename(L, p2);
if (strcmp(t1, t2) == 0)
if (luaport_strcmp(t1, t2) == 0)
luaG_runerror(L, "attempt to compare two %s values", t1);
else
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);

View file

@ -74,9 +74,9 @@
#else /* }{ */
/* ISO C handling with long jumps */
#define LUAI_THROW(L, c) longjmp((c)->b, 1)
#define LUAI_THROW(L, c) luaport_longjmp((c)->b, 1)
#define LUAI_TRY(L, c, a) \
if (setjmp((c)->b) == 0) { \
if (luaport_setjmp((c)->b) == 0) { \
a \
}
#define luai_jmpbuf jmp_buf
@ -942,7 +942,7 @@ struct SParser { /* data to 'f_parser' */
static void checkmode(lua_State *L, const char *mode, const char *x)
{
if (mode && strchr(mode, x[0]) == NULL) {
if (mode && luaport_strchr(mode, x[0]) == NULL) {
luaO_pushfstring(L,
"attempt to load a %s chunk (mode is '%s')", x, mode);
luaD_throw(L, LUA_ERRSYNTAX);

View file

@ -547,8 +547,8 @@ static lu_mem traversetable(global_State *g, Table *h)
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
markobjectN(g, h->metatable);
if (mode && ttisstring(mode) && /* is there a weak mode? */
(cast_void(weakkey = strchr(svalue(mode), 'k')),
cast_void(weakvalue = strchr(svalue(mode), 'v')),
(cast_void(weakkey = luaport_strchr(svalue(mode), 'k')),
cast_void(weakvalue = luaport_strchr(svalue(mode), 'v')),
(weakkey || weakvalue))) { /* is really weak? */
if (!weakkey) /* strong keys? */
traverseweakvalue(g, h);

View file

@ -35,9 +35,9 @@
/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
static int l_checkmode(const char *mode)
{
return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
return (*mode != '\0' && luaport_strchr("rwa", *(mode++)) != NULL &&
(*mode != '+' || ((void)(++mode), 1)) && /* skip if char is '+' */
(strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
(luaport_strspn(mode, L_MODEEXT) == luaport_strlen(mode))); /* check extensions */
}
#endif
@ -73,7 +73,7 @@ static int l_checkmode(const char *mode)
#define l_popen(L, c, m) \
((void)c, (void)m, \
luaL_error(L, "'popen' not supported"), \
(LUAPORT_FILE *)0)
(FILE *)0)
#define l_pclose(L, file) ((void)L, (void)file, -1)
#endif /* } */
@ -162,7 +162,7 @@ static int io_type(lua_State *L)
return 1;
}
static int lf_tostring(lua_State *L)
static int f_tostring(lua_State *L)
{
LStream *p = tolstream(L);
if (isclosed(p))
@ -172,7 +172,7 @@ static int lf_tostring(lua_State *L)
return 1;
}
static LUAPORT_FILE *tofile(lua_State *L)
static FILE *tofile(lua_State *L)
{
LStream *p = tolstream(L);
if (l_unlikely(isclosed(p)))
@ -207,7 +207,7 @@ static int aux_close(lua_State *L)
return (*cf)(L); /* close it */
}
static int lf_close(lua_State *L)
static int f_close(lua_State *L)
{
tofile(L); /* make sure argument is an open stream */
return aux_close(L);
@ -217,10 +217,10 @@ static int io_close(lua_State *L)
{
if (lua_isnone(L, 1)) /* no argument? */
lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use default output */
return lf_close(L);
return f_close(L);
}
static int lf_gc(lua_State *L)
static int f_gc(lua_State *L)
{
LStream *p = tolstream(L);
if (!isclosed(p) && p->f != NULL)
@ -251,7 +251,7 @@ static void opencheck(lua_State *L, const char *fname, const char *mode)
LStream *p = newfile(L);
p->f = luaport_fopen(fname, mode);
if (l_unlikely(p->f == NULL))
luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
luaL_error(L, "cannot open file '%s' (%s)", fname, luaport_strerror(luaport_errno));
}
static int io_open(lua_State *L)
@ -271,7 +271,7 @@ static int io_open(lua_State *L)
static int io_pclose(lua_State *L)
{
LStream *p = tolstream(L);
errno = 0;
luaport_errno = 0;
return luaL_execresult(L, l_pclose(L, p->f));
}
@ -293,7 +293,7 @@ static int io_tmpfile(lua_State *L)
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
}
static LUAPORT_FILE *getiofile(lua_State *L, const char *findex)
static FILE *getiofile(lua_State *L, const char *findex)
{
LStream *p;
lua_getfield(L, LUA_REGISTRYINDEX, findex);
@ -358,7 +358,7 @@ static void aux_lines(lua_State *L, int toclose)
lua_pushcclosure(L, io_readline, 3 + n);
}
static int lf_lines(lua_State *L)
static int f_lines(lua_State *L)
{
tofile(L); /* check that it's a valid file handle */
aux_lines(L, 0);
@ -409,7 +409,7 @@ static int io_lines(lua_State *L)
/* auxiliary structure used by 'read_number' */
typedef struct {
LUAPORT_FILE *f; /* file being read */
FILE *f; /* file being read */
int c; /* current character (look ahead) */
int n; /* number of elements in buffer 'buff' */
char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
@ -457,7 +457,7 @@ static int readdigits(RN *rn, int hex)
** Then it calls 'lua_stringtonumber' to check whether the format is
** correct and to convert it to a Lua number.
*/
static int read_number(lua_State *L, LUAPORT_FILE *f)
static int read_number(lua_State *L, FILE *f)
{
RN rn;
int count = 0;
@ -496,19 +496,15 @@ static int read_number(lua_State *L, LUAPORT_FILE *f)
}
}
static int test_eof(lua_State *L, LUAPORT_FILE *f)
static int test_eof(lua_State *L, FILE *f)
{
int c = luaport_feof(f);
int c = luaport_getc(f);
luaport_ungetc(c, f); /* no-op when c == EOF */
lua_pushliteral(L, "");
return !c;
// int c = luaport_getc(f);
// luaport_ungetc(c, f); /* no-op when c == EOF */
// lua_pushliteral(L, "");
// return (c != EOF);
return (c != EOF);
}
static int read_line(lua_State *L, LUAPORT_FILE *f, int chop)
static int read_line(lua_State *L, FILE *f, int chop)
{
luaL_Buffer b;
int c;
@ -529,7 +525,7 @@ static int read_line(lua_State *L, LUAPORT_FILE *f, int chop)
return (c == '\n' || lua_rawlen(L, -1) > 0);
}
static void read_all(lua_State *L, LUAPORT_FILE *f)
static void read_all(lua_State *L, FILE *f)
{
size_t nr;
luaL_Buffer b;
@ -542,7 +538,7 @@ static void read_all(lua_State *L, LUAPORT_FILE *f)
luaL_pushresult(&b); /* close buffer */
}
static int read_chars(lua_State *L, LUAPORT_FILE *f, size_t n)
static int read_chars(lua_State *L, FILE *f, size_t n)
{
size_t nr; /* number of chars actually read */
char *p;
@ -555,7 +551,7 @@ static int read_chars(lua_State *L, LUAPORT_FILE *f, size_t n)
return (nr > 0); /* true iff read something */
}
static int g_read(lua_State *L, LUAPORT_FILE *f, int first)
static int g_read(lua_State *L, FILE *f, int first)
{
int nargs = lua_gettop(L) - 1;
int n, success;
@ -577,7 +573,6 @@ static int g_read(lua_State *L, LUAPORT_FILE *f, int first)
p++; /* skip optional '*' (for compatibility) */
switch (*p) {
case 'n': /* number */
return luaL_argerror(L, n, "specifier 'n' number not supported yet in this dft_platform build");
success = read_number(L, f);
break;
case 'l': /* line */
@ -610,7 +605,7 @@ static int io_read(lua_State *L)
return g_read(L, getiofile(L, IO_INPUT), 1);
}
static int lf_read(lua_State *L)
static int f_read(lua_State *L)
{
return g_read(L, tofile(L), 2);
}
@ -649,7 +644,7 @@ static int io_readline(lua_State *L)
/* }====================================================== */
static int g_write(lua_State *L, LUAPORT_FILE *f, int arg)
static int g_write(lua_State *L, FILE *f, int arg)
{
int nargs = lua_gettop(L) - arg;
int status = 1;
@ -664,7 +659,7 @@ static int g_write(lua_State *L, LUAPORT_FILE *f, int arg)
} else {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
status = status && (luaport_fwirte(s, sizeof(char), l, f) == l);
status = status && (luaport_fwrite(s, sizeof(char), l, f) == l);
}
}
if (l_likely(status))
@ -678,18 +673,18 @@ static int io_write(lua_State *L)
return g_write(L, getiofile(L, IO_OUTPUT), 1);
}
static int lf_write(lua_State *L)
static int f_write(lua_State *L)
{
LUAPORT_FILE *f = tofile(L);
FILE *f = tofile(L);
lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
return g_write(L, f, 2);
}
static int lf_seek(lua_State *L)
static int f_seek(lua_State *L)
{
static const int mode[] = { SEEK_SET, SEEK_CUR, SEEK_END };
static const char *const modenames[] = { "set", "cur", "end", NULL };
LUAPORT_FILE *f = tofile(L);
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames);
lua_Integer p3 = luaL_optinteger(L, 3, 0);
l_seeknum offset = (l_seeknum)p3;
@ -704,11 +699,11 @@ static int lf_seek(lua_State *L)
}
}
static int lf_setvbuf(lua_State *L)
static int f_setvbuf(lua_State *L)
{
static const int mode[] = { _IONBF, _IOFBF, _IOLBF };
static const char *const modenames[] = { "no", "full", "line", NULL };
LUAPORT_FILE *f = tofile(L);
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, NULL, modenames);
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
int res = luaport_setvbuf(f, NULL, mode[op], (size_t)sz);
@ -720,7 +715,7 @@ static int io_flush(lua_State *L)
return luaL_fileresult(L, luaport_fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int lf_flush(lua_State *L)
static int f_flush(lua_State *L)
{
return luaL_fileresult(L, luaport_fflush(tofile(L)) == 0, NULL);
}
@ -747,13 +742,13 @@ static const luaL_Reg iolib[] = {
** methods for file handles
*/
static const luaL_Reg meth[] = {
{ "read", lf_read },
{ "write", lf_write },
{ "lines", lf_lines },
{ "flush", lf_flush },
{ "seek", lf_seek },
{ "close", lf_close },
{ "setvbuf", lf_setvbuf },
{ "read", f_read },
{ "write", f_write },
{ "lines", f_lines },
{ "flush", f_flush },
{ "seek", f_seek },
{ "close", f_close },
{ "setvbuf", f_setvbuf },
{ NULL, NULL }
};
@ -762,9 +757,9 @@ static const luaL_Reg meth[] = {
*/
static const luaL_Reg metameth[] = {
{ "__index", NULL }, /* place holder */
{ "__gc", lf_gc },
{ "__close", lf_gc },
{ "__tostring", lf_tostring },
{ "__gc", f_gc },
{ "__close", f_gc },
{ "__tostring", f_tostring },
{ NULL, NULL }
};
@ -790,7 +785,7 @@ static int io_noclose(lua_State *L)
return 2;
}
static void createstdfile(lua_State *L, LUAPORT_FILE *f, const char *k,
static void createstdfile(lua_State *L, FILE *f, const char *k,
const char *fname)
{
LStream *p = newprefile(L);

View file

@ -164,7 +164,7 @@ static void setprogdir(lua_State *L)
char *lb;
DWORD nsize = sizeof(buff) / sizeof(char);
DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */
if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
if (n == 0 || n == nsize || (lb = luaport_strrchr(buff, '\\')) == NULL)
luaL_error(L, "unable to get ModuleFileName");
else {
*lb = '\0'; /* cut name on the last '\\' to get the path */
@ -288,10 +288,10 @@ static void setpath(lua_State *L, const char *fieldname,
path = luaport_getenv(envname); /* try unversioned name */
if (path == NULL || noenv(L)) /* no environment variable? */
lua_pushstring(L, dft); /* use default */
else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL)
else if ((dftmark = luaport_strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL)
lua_pushstring(L, path); /* nothing to change */
else { /* path contains a ";;": insert default path in its place */
size_t len = strlen(path);
size_t len = luaport_strlen(path);
luaL_Buffer b;
luaL_buffinit(L, &b);
if (path < dftmark) { /* is there a prefix before ';;'? */
@ -413,7 +413,7 @@ static int ll_loadlib(lua_State *L)
static int readable(const char *filename)
{
LUAPORT_FILE *f = luaport_fopen(filename, "r"); /* try to open file */
FILE *f = luaport_fopen(filename, "r"); /* try to open file */
if (f == NULL)
return 0; /* open failed */
luaport_fclose(f);
@ -435,7 +435,7 @@ static const char *getnextfilename(char **path, char *end)
*name = *LUA_PATH_SEP; /* restore separator */
name++; /* skip it */
}
sep = strchr(name, *LUA_PATH_SEP); /* find next separator */
sep = luaport_strchr(name, *LUA_PATH_SEP); /* find next separator */
if (sep == NULL) /* separator not found? */
sep = end; /* name goes until the end */
*sep = '\0'; /* finish file name */
@ -469,7 +469,7 @@ static const char *searchpath(lua_State *L, const char *name,
char *endpathname; /* its end */
const char *filename;
/* separator is non-empty and appears in 'name'? */
if (*sep != '\0' && strchr(name, *sep) != NULL)
if (*sep != '\0' && luaport_strchr(name, *sep) != NULL)
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
luaL_buffinit(L, &buff);
/* add path to the buffer, replacing marks ('?') with the file name */
@ -546,7 +546,7 @@ static int loadfunc(lua_State *L, const char *filename, const char *modname)
const char *openfunc;
const char *mark;
modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
mark = strchr(modname, *LUA_IGMARK);
mark = luaport_strchr(modname, *LUA_IGMARK);
if (mark) {
int stat;
openfunc = lua_pushlstring(L, modname, mark - modname);
@ -573,7 +573,7 @@ static int searcher_Croot(lua_State *L)
{
const char *filename;
const char *name = luaL_checkstring(L, 1);
const char *p = strchr(name, '.');
const char *p = luaport_strchr(name, '.');
int stat;
if (p == NULL)
return 0; /* is root */

View file

@ -295,17 +295,17 @@ static const char *l_str2dloc(const char *s, lua_Number *result, int mode)
static const char *l_str2d(const char *s, lua_Number *result)
{
const char *endptr;
const char *pmode = strpbrk(s, ".xXnN"); /* look for special chars */
const char *pmode = luaport_strpbrk(s, ".xXnN"); /* look for special chars */
int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
if (mode == 'n') /* reject 'inf' and 'nan' */
return NULL;
endptr = l_str2dloc(s, result, mode); /* try to convert */
if (endptr == NULL) { /* failed? may be a different locale */
char buff[L_MAXLENNUM + 1];
const char *pdot = strchr(s, '.');
if (pdot == NULL || strlen(s) > L_MAXLENNUM)
const char *pdot = luaport_strchr(s, '.');
if (pdot == NULL || luaport_strlen(s) > L_MAXLENNUM)
return NULL; /* string too long or no dot; fail */
strcpy(buff, s); /* copy string to buffer */
luaport_strcpy(buff, s); /* copy string to buffer */
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
endptr = l_str2dloc(buff, result, mode); /* try again */
if (endptr != NULL)
@ -404,7 +404,7 @@ static int tostringbuff(TValue *obj, char *buff)
len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj));
else {
len = lua_number2str(buff, MAXNUMBER2STR, fltvalue(obj));
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
if (buff[luaport_strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
buff[len++] = lua_getlocaledecpoint();
buff[len++] = '0'; /* adds '.0' to result */
}
@ -513,14 +513,14 @@ const char *luaO_pushvfstring(lua_State *L, const char *fmt, va_list argp)
const char *e; /* points to next '%' */
buff.pushed = buff.blen = 0;
buff.L = L;
while ((e = strchr(fmt, '%')) != NULL) {
while ((e = luaport_strchr(fmt, '%')) != NULL) {
addstr2buff(&buff, fmt, e - fmt); /* add 'fmt' up to '%' */
switch (*(e + 1)) { /* conversion specifier */
case 's': { /* zero-terminated string */
const char *s = va_arg(argp, char *);
if (s == NULL)
s = "(null)";
addstr2buff(&buff, s, strlen(s));
addstr2buff(&buff, s, luaport_strlen(s));
break;
}
case 'c': { /* an 'int' as a character */
@ -571,7 +571,7 @@ const char *luaO_pushvfstring(lua_State *L, const char *fmt, va_list argp)
}
fmt = e + 2; /* skip '%' and the specifier */
}
addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */
addstr2buff(&buff, fmt, luaport_strlen(fmt)); /* rest of 'fmt' */
clearbuff(&buff); /* empty buffer into the stack */
lua_assert(buff.pushed == 1);
return svalue(s2v(L->top - 1));
@ -614,7 +614,7 @@ void luaO_chunkid(char *out, const char *source, size_t srclen)
luaport_memcpy(out, source + 1 + srclen - bufflen, bufflen * sizeof(char));
}
} else { /* string; format as [string "source"] */
const char *nl = strchr(source, '\n'); /* find first new line (if any) */
const char *nl = luaport_strchr(source, '\n'); /* find first new line (if any) */
addstr(out, PRE, LL(PRE)); /* add prefix */
bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */
if (srclen < bufflen && nl == NULL) { /* small one-line source? */

View file

@ -90,8 +90,8 @@
#else /* }{ */
/* ISO C definitions */
#define l_gmtime(t, r) ((void)(r)->tm_sec, gmtime(t))
#define l_localtime(t, r) ((void)(r)->tm_sec, localtime(t))
#define l_gmtime(t, r) ((void)(r)->tm_sec, luaport_gmtime(t))
#define l_localtime(t, r) ((void)(r)->tm_sec, luaport_localtime(t))
#endif /* } */
@ -120,7 +120,7 @@
#define lua_tmpnam(b, e) \
{ \
strcpy(b, LUA_TMPNAMTEMPLATE); \
luaport_strcpy(b, LUA_TMPNAMTEMPLATE); \
e = mkstemp(b); \
if (e != -1) \
close(e); \
@ -145,7 +145,7 @@ static int os_execute(lua_State *L)
{
const char *cmd = luaL_optstring(L, 1, NULL);
int stat;
errno = 0;
luaport_errno = 0;
stat = luaport_system(cmd);
if (cmd != NULL)
return luaL_execresult(L, stat);
@ -279,7 +279,7 @@ static const char *checkoption(lua_State *L, const char *conv,
for (; *option != '\0' && oplen <= convlen; option += oplen) {
if (*option == '|') /* next block? */
oplen++; /* will check options with next length (+1) */
else if (memcmp(conv, option, oplen) == 0) { /* match? */
else if (luaport_memcmp(conv, option, oplen) == 0) { /* match? */
luaport_memcpy(buff, conv, oplen); /* copy valid option to buffer */
buff[oplen] = '\0';
return conv + oplen; /* return next item */
@ -290,11 +290,11 @@ static const char *checkoption(lua_State *L, const char *conv,
return conv; /* to avoid warnings */
}
static time_t l_checktime(lua_State *L, int arg)
static luaport_time_t l_checktime(lua_State *L, int arg)
{
l_timet t = l_gettime(L, arg);
luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
return (time_t)t;
luaL_argcheck(L, (luaport_time_t)t == t, arg, "time out-of-bounds");
return (luaport_time_t)t;
}
/* maximum size for an individual 'strftime' item */
@ -304,7 +304,7 @@ static int os_date(lua_State *L)
{
size_t slen;
const char *s = luaL_optlstring(L, 1, "%c", &slen);
time_t t = luaL_opt(L, l_checktime, 2, luaport_time(NULL));
luaport_time_t t = luaL_opt(L, l_checktime, 2, luaport_time(NULL));
const char *se = s + slen; /* 's' end */
struct tm tmr, *stm;
if (*s == '!') { /* UTC? */
@ -315,7 +315,7 @@ static int os_date(lua_State *L)
if (stm == NULL) /* invalid date? */
return luaL_error(L,
"date result cannot be represented in this installation");
if (strcmp(s, "*t") == 0) {
if (luaport_strcmp(s, "*t") == 0) {
lua_createtable(L, 0, 9); /* 9 = number of fields */
setallfields(L, stm);
} else {
@ -331,7 +331,7 @@ static int os_date(lua_State *L)
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
s++; /* skip '%' */
s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */
reslen = strftime(buff, SIZETIMEFMT, cc, stm);
reslen = luaport_strftime(buff, SIZETIMEFMT, cc, stm);
luaL_addsize(&b, reslen);
}
}
@ -342,7 +342,7 @@ static int os_date(lua_State *L)
static int os_time(lua_State *L)
{
time_t t;
luaport_time_t t;
if (lua_isnoneornil(L, 1)) /* called without args? */
t = luaport_time(NULL); /* get current time */
else {
@ -356,21 +356,22 @@ static int os_time(lua_State *L)
ts.tm_min = getfield(L, "min", 0, 0);
ts.tm_sec = getfield(L, "sec", 0, 0);
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
t = luaport_mktime(&ts);
setallfields(L, &ts); /* update fields with normalized values */
}
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
return luaL_error(L,
"time result cannot be represented in this installation");
// if (t != (luaport_time_t)(l_timet)t || t == (luaport_time_t)(-1))
// return luaL_error(L,
// "time result cannot be represented in this installation");
l_pushtime(L, t);
return 1;
}
static int os_difftime(lua_State *L)
{
time_t t1 = l_checktime(L, 1);
time_t t2 = l_checktime(L, 2);
lua_pushnumber(L, (lua_Number)difftime(t1, t2));
luaport_time_t t1 = l_checktime(L, 1);
luaport_time_t t2 = l_checktime(L, 2);
lua_pushnumber(L, (lua_Number)luaport_difftime(t1, t2));
return 1;
}
@ -384,7 +385,7 @@ static int os_setlocale(lua_State *L)
"numeric", "time", NULL };
const char *l = luaL_optstring(L, 1, NULL);
int op = luaL_checkoption(L, 2, "all", catnames);
lua_pushstring(L, setlocale(cat[op], l));
lua_pushstring(L, luaport_setlocale(cat[op], l));
return 1;
}

View file

@ -1679,8 +1679,7 @@ static void test_then_block(LexState *ls, int *escapelist)
luaX_next(ls); /* skip 'break' */
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
while (testnext(ls, ';')) {
} /* skip semicolons */
while (testnext(ls, ';')) {} /* skip semicolons */
if (block_follow(ls, 0)) { /* jump is the entire block? */
leaveblock(fs);
return; /* and that is it */
@ -1731,9 +1730,9 @@ static int getlocalattribute(LexState *ls)
if (testnext(ls, '<')) {
const char *attr = getstr(str_checkname(ls));
checknext(ls, '>');
if (strcmp(attr, "const") == 0)
if (luaport_strcmp(attr, "const") == 0)
return RDKCONST; /* read-only variable */
else if (strcmp(attr, "close") == 0)
else if (luaport_strcmp(attr, "close") == 0)
return RDKTOCLOSE; /* to-be-closed variable */
else
luaK_semerror(ls,

View file

@ -42,7 +42,7 @@ typedef struct LG {
global_State g;
} LG;
#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - luaport_offsetof(LX, l)))
/*
** A macro to create a "random" seed when a state is created;

View file

@ -34,7 +34,7 @@ int luaS_eqlngstr(TString *a, TString *b)
lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
return (a == b) || /* same instance or... */
((len == b->u.lnglen) && /* equal length and ... */
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
(luaport_memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
}
unsigned int luaS_hash(const char *str, size_t l, unsigned int seed)
@ -189,7 +189,7 @@ static TString *internshrstr(lua_State *L, const char *str, size_t l)
TString **list = &tb->hash[lmod(h, tb->size)];
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
if (l == ts->shrlen && (luaport_memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
/* found! */
if (isdead(g, ts)) /* dead (but not collected yet)? */
changewhite(ts); /* resurrect it */
@ -239,14 +239,14 @@ TString *luaS_new(lua_State *L, const char *str)
int j;
TString **p = G(L)->strcache[i];
for (j = 0; j < STRCACHE_M; j++) {
if (strcmp(str, getstr(p[j])) == 0) /* hit? */
if (luaport_strcmp(str, getstr(p[j])) == 0) /* hit? */
return p[j]; /* that is it */
}
/* normal route */
for (j = STRCACHE_M - 1; j > 0; j--)
p[j] = p[j - 1]; /* move out last element */
/* new element is first in the list */
p[0] = luaS_newlstr(L, str, strlen(str));
p[0] = luaS_newlstr(L, str, luaport_strlen(str));
return p[0];
}

View file

@ -591,7 +591,7 @@ static const char *match_capture(MatchState *ms, const char *s, int l)
l = check_capture(ms, l);
len = ms->capture[l].len;
if ((size_t)(ms->src_end - s) >= len &&
memcmp(ms->capture[l].init, s, len) == 0)
luaport_memcmp(ms->capture[l].init, s, len) == 0)
return s + len;
else
return NULL;
@ -725,9 +725,9 @@ static const char *lmemfind(const char *s1, size_t l1,
const char *init; /* to search for a '*s2' inside 's1' */
l2--; /* 1st char will be checked by 'memchr' */
l1 = l1 - l2; /* 's2' cannot be found after that */
while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
while (l1 > 0 && (init = (const char *)luaport_memchr(s1, *s2, l1)) != NULL) {
init++; /* 1st char is already checked */
if (memcmp(init, s2 + 1, l2) == 0)
if (luaport_memcmp(init, s2 + 1, l2) == 0)
return init - 1;
else { /* correct 'l1' and 's1' to try again */
l1 -= init - s1;
@ -792,9 +792,9 @@ static int nospecials(const char *p, size_t l)
{
size_t upto = 0;
do {
if (strpbrk(p + upto, SPECIALS))
if (luaport_strpbrk(p + upto, SPECIALS))
return 0; /* pattern has a special character */
upto += strlen(p + upto) + 1; /* may have more after \0 */
upto += luaport_strlen(p + upto) + 1; /* may have more after \0 */
} while (upto <= l);
return 1; /* no special chars found */
}
@ -920,7 +920,7 @@ static void add_s(MatchState *ms, luaL_Buffer *b, const char *s,
lua_State *L = ms->L;
const char *news = lua_tolstring(L, 3, &l);
const char *p;
while ((p = (char *)memchr(news, L_ESC, l)) != NULL) {
while ((p = (char *)luaport_memchr(news, L_ESC, l)) != NULL) {
luaL_addlstring(b, news, p - news);
p++; /* skip ESC */
if (*p == L_ESC) /* '%%' */
@ -1195,9 +1195,9 @@ static int quotefloat(lua_State *L, char *buff, lua_Number n)
int nb = lua_number2strx(L, buff, MAX_ITEM,
"%" LUA_NUMBER_FRMLEN "a", n);
/* ensures that 'buff' string uses a dot as the radix character */
if (memchr(buff, '.', nb) == NULL) { /* no dot? */
if (luaport_memchr(buff, '.', nb) == NULL) { /* no dot? */
char point = lua_getlocaledecpoint(); /* try locale point */
char *ppoint = (char *)memchr(buff, point, nb);
char *ppoint = (char *)luaport_memchr(buff, point, nb);
if (ppoint)
*ppoint = '.'; /* change it to a dot */
}
@ -1219,11 +1219,9 @@ static void addliteral(lua_State *L, luaL_Buffer *b, int arg)
case LUA_TNUMBER: {
char *buff = luaL_prepbuffsize(b, MAX_ITEM);
int nb;
if (!lua_isinteger(L, arg)) { /* float? */
luaL_error(L, "specifier '%%q' not supported yet in this dft_platform build");
return;
if (!lua_isinteger(L, arg)) /* float? */
nb = quotefloat(L, buff, lua_tonumber(L, arg));
} else { /* integers */
else { /* integers */
lua_Integer n = lua_tointeger(L, arg);
const char *format = (n == LUA_MININTEGER) /* corner case? */
?
@ -1267,7 +1265,7 @@ static void checkformat(lua_State *L, const char *form, const char *flags,
int precision)
{
const char *spec = form + 1; /* skip '%' */
spec += strspn(spec, flags); /* skip flags */
spec += luaport_strspn(spec, flags); /* skip flags */
if (*spec != '0') { /* a width cannot start with '0' */
spec = get2digits(spec); /* skip width */
if (*spec == '.' && precision) {
@ -1287,7 +1285,7 @@ static const char *getformat(lua_State *L, const char *strfrmt,
char *form)
{
/* spans flags, width, and precision ('0' is included as a flag) */
size_t len = strspn(strfrmt, L_FMTFLAGSF "123456789.");
size_t len = luaport_strspn(strfrmt, L_FMTFLAGSF "123456789.");
len++; /* adds following character (should be the specifier) */
/* still needs space for '%', '\0', plus a length modifier */
if (len >= MAX_FORMAT - 10)
@ -1303,10 +1301,10 @@ static const char *getformat(lua_State *L, const char *strfrmt,
*/
static void addlenmod(char *form, const char *lenmod)
{
size_t l = strlen(form);
size_t lm = strlen(lenmod);
size_t l = luaport_strlen(form);
size_t lm = luaport_strlen(lenmod);
char spec = form[l - 1];
strcpy(form + l - 1, lenmod);
luaport_strcpy(form + l - 1, lenmod);
form[l + lm - 1] = spec;
form[l + lm] = '\0';
}
@ -1360,7 +1358,6 @@ static int str_format(lua_State *L)
}
case 'a':
case 'A':
return luaL_error(L, "specifier '%%a' or '%%A' not supported yet in this dft_platform build");
checkformat(L, form, L_FMTFLAGSF, 1);
addlenmod(form, LUA_NUMBER_FRMLEN);
nb = lua_number2strx(L, buff, maxitem, form,
@ -1385,7 +1382,7 @@ static int str_format(lua_State *L)
checkformat(L, form, L_FMTFLAGSC, 0);
if (p == NULL) { /* avoid calling 'printf' with argument NULL */
p = "(null)"; /* result */
form[strlen(form) - 1] = 's'; /* format it as a string */
form[luaport_strlen(form) - 1] = 's'; /* format it as a string */
}
nb = l_sprintf(buff, maxitem, form, p);
break;
@ -1402,9 +1399,9 @@ static int str_format(lua_State *L)
if (form[2] == '\0') /* no modifiers? */
luaL_addvalue(&b); /* keep entire string */
else {
luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
luaL_argcheck(L, l == luaport_strlen(s), arg, "string contains zeros");
checkformat(L, form, L_FMTFLAGSC, 1);
if (strchr(form, '.') == NULL && l >= 100) {
if (luaport_strchr(form, '.') == NULL && l >= 100) {
/* no precision and string is too long to be formatted */
luaL_addvalue(&b); /* keep entire string */
} else { /* format the string into 'buff' */
@ -1612,7 +1609,7 @@ static KOption getoption(Header *h, const char **fmt, int *size)
h->islittle = nativeendian.little;
break;
case '!': {
const int maxalign = offsetof(struct cD, u);
const int maxalign = luaport_offsetof(struct cD, u);
h->maxalign = getnumlimit(h, fmt, maxalign);
break;
}
@ -1773,7 +1770,7 @@ static int str_pack(lua_State *L)
case Kzstr: { /* zero-terminated string */
size_t len;
const char *s = luaL_checklstring(L, arg, &len);
luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
luaL_argcheck(L, luaport_strlen(s) == len, arg, "string contains zeros");
luaL_addlstring(&b, s, len);
luaL_addchar(&b, '\0'); /* add zero at the end */
totalsize += len + 1;
@ -1901,7 +1898,7 @@ static int str_unpack(lua_State *L)
break;
}
case Kzstr: {
size_t len = strlen(data + pos);
size_t len = luaport_strlen(data + pos);
luaL_argcheck(L, pos + len < ld, 2,
"unfinished string for format 'z'");
lua_pushlstring(L, data + pos, len);

View file

@ -238,7 +238,7 @@ typedef unsigned int IdxT;
static unsigned int l_randomizePivot(void)
{
clock_t c = luaport_clock();
time_t t = luaport_time(NULL);
luaport_time_t t = luaport_time(NULL);
unsigned int buff[sof(c) + sof(t)];
unsigned int i, rnd = 0;
luaport_memcpy(buff, &c, sof(c) * sizeof(unsigned int));

View file

@ -267,9 +267,9 @@ static void loadFunction(LoadState *S, Proto *f, TString *psource)
static void checkliteral(LoadState *S, const char *s, const char *msg)
{
char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
size_t len = strlen(s);
size_t len = luaport_strlen(s);
loadVector(S, buff, len);
if (memcmp(s, buff, len) != 0)
if (luaport_memcmp(s, buff, len) != 0)
error(S, msg);
}

View file

@ -367,11 +367,11 @@ static int l_strcmp(const TString *ls, const TString *rs)
const char *r = getstr(rs);
size_t lr = tsslen(rs);
for (;;) { /* for each segment */
int temp = strcoll(l, r);
int temp = luaport_strcoll(l, r);
if (temp != 0) /* not equal? */
return temp; /* done */
else { /* strings are equal up to a '\0' */
size_t len = strlen(l); /* index of first '\0' in both strings */
size_t len = luaport_strlen(l); /* index of first '\0' in both strings */
if (len == lr) /* 'rs' is finished? */
return (len == ll) ? 0 : 1; /* check 'ls' */
else if (len == ll) /* 'ls' is finished? */
@ -1207,7 +1207,7 @@ returning: /* trap already set */
vmfetch();
#if 0
/* low-level line tracing for debugging Lua */
printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
luaport_printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
#endif
lua_assert(base == ci->func + 1);
lua_assert(base <= L->top && L->top < L->stack_last);

View file

@ -0,0 +1,754 @@
/*
** $Id: luaconf.h $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
#ifndef luaconf_h
#define luaconf_h
#include <limits.h>
#include <stddef.h>
#include "luaport.h"
/*
** ===================================================================
** General Configuration File for Lua
**
** Some definitions here can be changed externally, through the compiler
** (e.g., with '-D' options): They are commented out or protected
** by '#if !defined' guards. However, several other definitions
** should be changed directly here, either because they affect the
** Lua ABI (by making the changes here, you ensure that all software
** connected to Lua, such as C libraries, will be compiled with the same
** configuration); or because they are seldom changed.
**
** Search for "@@" to find all configurable definitions.
** ===================================================================
*/
/*
** {====================================================================
** System Configuration: macros to adapt (if needed) Lua to some
** particular platform, for instance restricting it to C89.
** =====================================================================
*/
/*
@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
** Define it if you want Lua to avoid the use of a few C99 features
** or Windows-specific features on Windows.
*/
/* #define LUA_USE_C89 */
/*
** By default, Lua on Windows use (some) specific Windows features
*/
#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE)
#define LUA_USE_WINDOWS /* enable goodies for regular Windows */
#endif
#if defined(LUA_USE_WINDOWS)
// #define LUA_DL_DLL /* enable support for DLL */
#define LUA_USE_C89 /* broadly, Windows is C89 */
#endif
#if defined(LUA_USE_LINUX)
// #define LUA_USE_POSIX
// #define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#endif
#if defined(LUA_USE_MACOSX)
// #define LUA_USE_POSIX
// #define LUA_USE_DLOPEN /* MacOS does not need -ldl */
#endif
#if defined(LUA_USE_MCU)
// #define LUA_USE_POSIX
#endif
/*
@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits.
*/
#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3)
/* }================================================================== */
/*
** {==================================================================
** Configuration for Number types. These options should not be
** set externally, because any other code connected to Lua must
** use the same configuration.
** ===================================================================
*/
/*
@@ LUA_INT_TYPE defines the type for Lua integers.
@@ LUA_FLOAT_TYPE defines the type for Lua floats.
** Lua should work fine with any mix of these options supported
** by your C compiler. The usual configurations are 64-bit integers
** and 'double' (the default), 32-bit integers and 'float' (for
** restricted platforms), and 'long'/'double' (for C compilers not
** compliant with C99, which may not have support for 'long long').
*/
/* predefined options for LUA_INT_TYPE */
#define LUA_INT_INT 1
#define LUA_INT_LONG 2
#define LUA_INT_LONGLONG 3
/* predefined options for LUA_FLOAT_TYPE */
#define LUA_FLOAT_FLOAT 1
#define LUA_FLOAT_DOUBLE 2
#define LUA_FLOAT_LONGDOUBLE 3
/* Default configuration ('long long' and 'double', for 64-bit Lua) */
#define LUA_INT_DEFAULT LUA_INT_LONGLONG
#define LUA_FLOAT_DEFAULT LUA_FLOAT_FLOAT
/*
@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
*/
#define LUA_32BITS 0
/*
@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
** C89 ('long' and 'double'); Windows always has '__int64', so it does
** not need to use this case.
*/
#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
#define LUA_C89_NUMBERS 1
#else
#define LUA_C89_NUMBERS 0
#endif
#if LUA_32BITS /* { */
/*
** 32-bit integers and 'float'
*/
#if LUAI_IS32INT /* use 'int' if big enough */
#define LUA_INT_TYPE LUA_INT_INT
#else /* otherwise use 'long' */
#define LUA_INT_TYPE LUA_INT_LONG
#endif
#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
#elif LUA_C89_NUMBERS /* }{ */
/*
** largest types available for C89 ('long' and 'double')
*/
#define LUA_INT_TYPE LUA_INT_LONG
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
#else /* }{ */
/* use defaults */
#define LUA_INT_TYPE LUA_INT_DEFAULT
#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for Paths.
** ===================================================================
*/
/*
** LUA_PATH_SEP is the character that separates templates in a path.
** LUA_PATH_MARK is the string that marks the substitution points in a
** template.
** LUA_EXEC_DIR in a Windows path is replaced by the executable's
** directory.
*/
#define LUA_PATH_SEP ";"
#define LUA_PATH_MARK "?"
#define LUA_EXEC_DIR "!"
/*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
** Lua libraries.
@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
** C libraries.
** CHANGE them if your machine has a non-conventional directory
** hierarchy or if you want to install your libraries in
** non-conventional directories.
*/
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#if defined(_WIN32) /* { */
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\"
#if !defined(LUA_PATH_DEFAULT)
#define LUA_PATH_DEFAULT \
LUA_LDIR "?.lua;" LUA_LDIR "?\\init.lua;" LUA_CDIR "?.lua;" LUA_CDIR "?\\init.lua;" LUA_SHRDIR "?.lua;" LUA_SHRDIR "?\\init.lua;" \
".\\?.lua;" \
".\\?\\init.lua"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR "?.dll;" LUA_CDIR "..\\lib\\lua\\" LUA_VDIR "\\?.dll;" LUA_CDIR "loadall.dll;" \
".\\?.dll"
#endif
#elif defined(LUA_USE_MCU) /* }{ */
#define LUA_ROOT "/sd/"
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
#if !defined(LUA_PATH_DEFAULT)
#define LUA_PATH_DEFAULT \
LUA_LDIR "?.lua;" LUA_LDIR "?/init.lua;" LUA_CDIR "?.lua;" LUA_CDIR "?/init.lua;" \
"./?.lua;" \
"./?/init.lua"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR "?.so;" LUA_CDIR "loadall.so;" \
"./?.so"
#endif
#else /* }{ */
#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
#if !defined(LUA_PATH_DEFAULT)
#define LUA_PATH_DEFAULT \
LUA_LDIR "?.lua;" LUA_LDIR "?/init.lua;" LUA_CDIR "?.lua;" LUA_CDIR "?/init.lua;" \
"./?.lua;" \
"./?/init.lua"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR "?.so;" LUA_CDIR "loadall.so;" \
"./?.so"
#endif
#endif /* } */
/*
@@ LUA_DIRSEP is the directory separator (for submodules).
** CHANGE it if your machine does not use "/" as the directory separator
** and is not Windows. (On Windows Lua automatically uses "\".)
*/
#if !defined(LUA_DIRSEP)
#if defined(_WIN32)
#define LUA_DIRSEP "\\"
#else
#define LUA_DIRSEP "/"
#endif
#endif
/* }================================================================== */
/*
** {==================================================================
** Marks for exported symbols in the C code
** ===================================================================
*/
/*
@@ LUA_API is a mark for all core API functions.
@@ LUALIB_API is a mark for all auxiliary library functions.
@@ LUAMOD_API is a mark for all standard library opening functions.
** CHANGE them if you need to define those functions in some special way.
** For instance, if you want to create one Windows DLL with the core and
** the libraries, you may want to use the following definition (define
** LUA_BUILD_AS_DLL to get it).
*/
#if defined(LUA_BUILD_AS_DLL) /* { */
#if defined(LUA_CORE) || defined(LUA_LIB) /* { */
#define LUA_API __declspec(dllexport)
#else /* }{ */
#define LUA_API __declspec(dllimport)
#endif /* } */
#else /* }{ */
#define LUA_API extern
#endif /* } */
/*
** More often than not the libs go together with the core.
*/
#define LUALIB_API LUA_API
#define LUAMOD_API LUA_API
/*
@@ LUAI_FUNC is a mark for all extern functions that are not to be
** exported to outside modules.
@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables,
** none of which to be exported to outside modules (LUAI_DDEF for
** definitions and LUAI_DDEC for declarations).
** CHANGE them if you need to mark them in some special way. Elf/gcc
** (versions 3.2 and later) mark them as "hidden" to optimize access
** when Lua is compiled as a shared library. Not all elf targets support
** this attribute. Unfortunately, gcc does not offer a way to check
** whether the target offers that support, and those without support
** give a warning about it. To avoid these warnings, change to the
** default definition.
*/
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) /* { */
#define LUAI_FUNC __attribute__((visibility("internal"))) extern
#else /* }{ */
#define LUAI_FUNC extern
#endif /* } */
#define LUAI_DDEC(dec) LUAI_FUNC dec
#define LUAI_DDEF /* empty */
/* }================================================================== */
/*
** {==================================================================
** Compatibility with previous versions
** ===================================================================
*/
/*
@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3.
** You can define it to get all options, or change specific options
** to fit your specific needs.
*/
#if defined(LUA_COMPAT_5_3) /* { */
/*
@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
** functions in the mathematical library.
** (These functions were already officially removed in 5.3;
** nevertheless they are still available here.)
*/
#define LUA_COMPAT_MATHLIB
/*
@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for
** manipulating other integer types (lua_pushunsigned, lua_tounsigned,
** luaL_checkint, luaL_checklong, etc.)
** (These macros were also officially removed in 5.3, but they are still
** available here.)
*/
#define LUA_COMPAT_APIINTCASTS
/*
@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod
** using '__lt'.
*/
#define LUA_COMPAT_LT_LE
/*
@@ The following macros supply trivial compatibility for some
** changes in the API. The macros themselves document how to
** change your code to avoid using them.
** (Once more, these macros were officially removed in 5.3, but they are
** still available here.)
*/
#define lua_strlen(L, i) lua_rawlen(L, (i))
#define lua_objlen(L, i) lua_rawlen(L, (i))
#define lua_equal(L, idx1, idx2) lua_compare(L, (idx1), (idx2), LUA_OPEQ)
#define lua_lessthan(L, idx1, idx2) lua_compare(L, (idx1), (idx2), LUA_OPLT)
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for Numbers (low-level part).
** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
** satisfy your needs.
** ===================================================================
*/
/*
@@ LUAI_UACNUMBER is the result of a 'default argument promotion'
@@ over a floating number.
@@ l_floatatt(x) corrects float attribute 'x' to the proper float type
** by prefixing it with one of FLT/DBL/LDBL.
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
@@ LUA_NUMBER_FMT is the format for writing floats.
@@ lua_number2str converts a float to a string.
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
@@ l_floor takes the floor of a float.
@@ lua_str2number converts a decimal numeral to a number.
*/
/* The following definitions are good for most cases here */
#define l_floor(x) (l_mathop(floor)(x))
#define lua_number2str(s, sz, n) \
l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n))
/*
@@ lua_numbertointeger converts a float number with an integral value
** to an integer, or returns 0 if float is not within the range of
** a lua_Integer. (The range comparisons are tricky because of
** rounding. The tests here assume a two-complement representation,
** where MININTEGER always has an exact representation as a float;
** MAXINTEGER may not have one, and therefore its conversion to float
** may have an ill-defined value.)
*/
#define lua_numbertointeger(n, p) \
((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
(n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
(*(p) = (LUA_INTEGER)(n), 1))
/* now the variable definitions */
#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */
#define LUA_NUMBER float
#define l_floatatt(n) (FLT_##n)
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
#define LUA_NUMBER_FMT "%.7g"
#define l_mathop(op) op##f
#define lua_str2number(s, p) luaport_strtof((s), (p))
#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */
#define LUA_NUMBER long double
#define l_floatatt(n) (LDBL_##n)
#define LUAI_UACNUMBER long double
#define LUA_NUMBER_FRMLEN "L"
#define LUA_NUMBER_FMT "%.19Lg"
#define l_mathop(op) op##l
#define lua_str2number(s, p) strtold((s), (p))
#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */
#define LUA_NUMBER double
#define l_floatatt(n) (DBL_##n)
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
#define LUA_NUMBER_FMT "%.14g"
#define l_mathop(op) op
#define lua_str2number(s, p) luaport_strtod((s), (p))
#else /* }{ */
#error "numeric float type not defined"
#endif /* } */
/*
@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
@@ LUAI_UACINT is the result of a 'default argument promotion'
@@ over a LUA_INTEGER.
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
@@ LUA_INTEGER_FMT is the format for writing integers.
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
@@ lua_integer2str converts an integer to a string.
*/
/* The following definitions are good for most cases here */
#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
#define LUAI_UACINT LUA_INTEGER
#define lua_integer2str(s, sz, n) \
l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n))
/*
** use LUAI_UACINT here to avoid problems with promotions (which
** can turn a comparison between unsigneds into a signed comparison)
*/
#define LUA_UNSIGNED unsigned LUAI_UACINT
/* now the variable definitions */
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
#define LUA_INTEGER int
#define LUA_INTEGER_FRMLEN ""
#define LUA_MAXINTEGER INT_MAX
#define LUA_MININTEGER INT_MIN
#define LUA_MAXUNSIGNED UINT_MAX
#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */
#define LUA_INTEGER long
#define LUA_INTEGER_FRMLEN "l"
#define LUA_MAXINTEGER LONG_MAX
#define LUA_MININTEGER LONG_MIN
#define LUA_MAXUNSIGNED ULONG_MAX
#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
/* use presence of macro LLONG_MAX as proxy for C99 compliance */
#if defined(LLONG_MAX) /* { */
/* use ISO C99 stuff */
#define LUA_INTEGER long long
#define LUA_INTEGER_FRMLEN "ll"
#define LUA_MAXINTEGER LLONG_MAX
#define LUA_MININTEGER LLONG_MIN
#define LUA_MAXUNSIGNED ULLONG_MAX
#elif defined(LUA_USE_WINDOWS) /* }{ */
/* in Windows, can use specific Windows types */
#define LUA_INTEGER __int64
#define LUA_INTEGER_FRMLEN "I64"
#define LUA_MAXINTEGER _I64_MAX
#define LUA_MININTEGER _I64_MIN
#define LUA_MAXUNSIGNED _UI64_MAX
#else /* }{ */
#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
#endif /* } */
#else /* }{ */
#error "numeric integer type not defined"
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Dependencies with C99 and other C details
** ===================================================================
*/
/*
@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89.
** (All uses in Lua have only one format item.)
*/
#if !defined(LUA_USE_C89)
#define l_sprintf(s, sz, f, i) luaport_snprintf(s, sz, f, i)
#else
#define l_sprintf(s, sz, f, i) ((void)(sz), luaport_sprintf(s, f, i))
#endif
/*
@@ lua_strx2number converts a hexadecimal numeral to a number.
** In C99, 'strtod' does that conversion. Otherwise, you can
** leave 'lua_strx2number' undefined and Lua will provide its own
** implementation.
*/
#if !defined(LUA_USE_C89)
#define lua_strx2number(s, p) lua_str2number(s, p)
#endif
/*
@@ lua_pointer2str converts a pointer to a readable string in a
** non-specified way.
*/
#define lua_pointer2str(buff, sz, p) l_sprintf(buff, sz, "%p", p)
/*
@@ lua_number2strx converts a float to a hexadecimal numeral.
** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
** provide its own implementation.
*/
#if !defined(LUA_USE_C89)
#define lua_number2strx(L, b, sz, f, n) \
((void)L, l_sprintf(b, sz, f, (LUAI_UACNUMBER)(n)))
#endif
/*
** 'strtof' and 'opf' variants for math functions are not valid in
** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the
** availability of these variants. ('math.h' is already included in
** all files that use these macros.)
*/
#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF))
#undef l_mathop /* variants not available */
#undef lua_str2number
#define l_mathop(op) (lua_Number) op /* no variant */
#define lua_str2number(s, p) ((lua_Number)luaport_strtod((s), (p)))
#endif
/*
@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation
** functions. It must be a numerical type; Lua will use 'intptr_t' if
** available, otherwise it will use 'ptrdiff_t' (the nearest thing to
** 'intptr_t' in C89)
*/
#define LUA_KCONTEXT ptrdiff_t
#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
__STDC_VERSION__ >= 199901L
#include <stdint.h>
#if defined(INTPTR_MAX) /* even in C99 this type is optional */
#undef LUA_KCONTEXT
#define LUA_KCONTEXT intptr_t
#endif
#endif
/*
@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
** Change that if you do not want to use C locales. (Code using this
** macro must include the header 'locale.h'.)
*/
#if !defined(lua_getlocaledecpoint)
#define lua_getlocaledecpoint() (luaport_localeconv()->decimal_point[0])
#endif
/*
** macros to improve jump prediction, used mostly for error handling
** and debug facilities. (Some macros in the Lua API use these macros.
** Define LUA_NOBUILTIN if you do not want '__builtin_expect' in your
** code.)
*/
#if !defined(luai_likely)
#if defined(__GNUC__) && !defined(LUA_NOBUILTIN)
#define luai_likely(x) (__builtin_expect(((x) != 0), 1))
#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0))
#else
#define luai_likely(x) (x)
#define luai_unlikely(x) (x)
#endif
#endif
#if defined(LUA_CORE) || defined(LUA_LIB)
/* shorter names for Lua's own use */
#define l_likely(x) luai_likely(x)
#define l_unlikely(x) luai_unlikely(x)
#endif
/* }================================================================== */
/*
** {==================================================================
** Language Variations
** =====================================================================
*/
/*
@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some
** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from
** numbers to strings. Define LUA_NOCVTS2N to turn off automatic
** coercion from strings to numbers.
*/
/* #define LUA_NOCVTN2S */
/* #define LUA_NOCVTS2N */
/*
@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
** Define it as a help when debugging C code.
*/
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(l, e) luaport_assert(e)
#endif
/* }================================================================== */
/*
** {==================================================================
** Macros that affect the API and must be stable (that is, must be the
** same when you compile Lua and when you compile code that links to
** Lua).
** =====================================================================
*/
/*
@@ LUAI_MAXSTACK limits the size of the Lua stack.
** CHANGE it if you need a different limit. This limit is arbitrary;
** its only purpose is to stop Lua from consuming unlimited stack
** space (and to reserve some numbers for pseudo-indices).
** (It must fit into max(size_t)/32.)
*/
#if LUAI_IS32INT
#define LUAI_MAXSTACK 1000000
#else
#define LUAI_MAXSTACK 15000
#endif
/*
@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
** a Lua state with very fast access.
** CHANGE it if you need a different size.
*/
#define LUA_EXTRASPACE (sizeof(void *))
/*
@@ LUA_IDSIZE gives the maximum size for the description of the source
@@ of a function in debug information.
** CHANGE it if you want a different size.
*/
#define LUA_IDSIZE 60
/*
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
*/
#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void *) * sizeof(lua_Number)))
/*
@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure
** maximum alignment for the other items in that union.
*/
#define LUAI_MAXALIGN \
lua_Number n; \
double u; \
void *s; \
lua_Integer i; \
long l
/* }================================================================== */
/* =================================================================== */
/*
** Local configuration. You can use this space to add your redefinitions
** without modifying the main part of the file.
*/
#endif

View file

@ -0,0 +1,98 @@
/*
** $Id: luaport.h $
** Lua Port
** See Copyright Notice in lua.h
*/
#ifndef luaport_h
#define luaport_h
#define LUA_USE_MCU
#define LUA_USE_APICHECK
// #define LUAI_ASSERT
#include <assert.h>
#define luaport_assert assert
#include <stdarg.h>
#define luaport_offsetof offsetof
#include <stdio.h>
#define luaport_stdin stdin
#define luaport_stdout stdout
#define luaport_stderr stderr
#define luaport_tmpfile tmpfile
#define luaport_tmpnam tmpnam
#define luaport_fclose fclose
#define luaport_fflush fflush
#define luaport_freopen freopen
#define luaport_setvbuf setvbuf
#define luaport_fprintf fprintf
#define luaport_printf printf
#define luaport_fgets fgets
#define luaport_fputs fputs
#define luaport_getc getc
#define luaport_ungetc ungetc
#define luaport_fread fread
#define luaport_fwrite fwrite
#define luaport_fseek fseek
#define luaport_ftell ftell
#define luaport_clearerr clearerr
#define luaport_feof feof
#define luaport_ferror ferror
#define luaport_fopen fopen
#define luaport_sprintf sprintf
#define luaport_remove remove
#define luaport_rename rename
#define luaport_snprintf snprintf
#include <string.h>
#define luaport_memchr memchr
#define luaport_memcmp memcmp
#define luaport_memcpy memcpy
#define luaport_strchr strchr
#define luaport_strcmp strcmp
#define luaport_strcoll strcoll
#define luaport_strcpy strcpy
#define luaport_strerror strerror
#define luaport_strlen strlen
#define luaport_strncmp strncmp
#define luaport_strpbrk strpbrk
#define luaport_strrchr strrchr
#define luaport_strspn strspn
#define luaport_strstr strstr
#include <errno.h>
#define luaport_errno errno
#include <stdlib.h>
#define luaport_abort abort
#define luaport_exit exit
#define luaport_free free
#define luaport_getenv getenv
#define luaport_realloc realloc
#define luaport_strtod strtod
#define luaport_strtof strtof
#define luaport_system system
#include <setjmp.h>
#define luaport_longjmp longjmp
#define luaport_setjmp setjmp
#include <locale.h>
#define luaport_setlocale setlocale
#define luaport_localeconv localeconv
#include <time.h>
#define luaport_time_t long long
#define luaport_clock clock
#define luaport_difftime difftime
#define luaport_mktime mktime
#define luaport_time time
#define luaport_gmtime gmtime
#define luaport_localtime localtime
#define luaport_strftime strftime
#define luaport_signal(sig,func) NULL
#endif

View file

@ -0,0 +1,698 @@
/*
** $Id: lua.c $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
#define lua_c
#include "lprefix.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// #include <signal.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#if !defined(LUA_PROGNAME)
#define LUA_PROGNAME "lua"
#endif
#if !defined(LUA_INIT_VAR)
#define LUA_INIT_VAR "LUA_INIT"
#endif
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
static lua_State *globalL = NULL;
static const char *progname = LUA_PROGNAME;
#if defined(LUA_USE_POSIX) /* { */
/*
** Use 'sigaction' when available.
*/
static void
setsignal(int sig, void (*handler)(int))
{
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask); /* do not mask any signal */
sigaction(sig, &sa, NULL);
}
#else /* }{ */
#define setsignal luaport_signal
#endif /* } */
/*
** Hook set by signal function to stop the interpreter.
*/
static void
lstop(lua_State *L, lua_Debug *ar)
{
(void)ar; /* unused arg. */
lua_sethook(L, NULL, 0, 0); /* reset hook */
luaL_error(L, "interrupted!");
}
/*
** Function to be called at a C signal. Because a C signal cannot
** just change a Lua state (as there is no proper synchronization),
** this function only sets a hook that, when called, will stop the
** interpreter.
*/
static void
laction(int i)
{
int flag = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT;
setsignal(i, SIG_DFL); /* if another SIGINT happens, terminate process */
lua_sethook(globalL, lstop, flag, 1);
}
static void
print_usage(const char *badoption)
{
lua_writestringerror("%s: ", progname);
if (badoption[1] == 'e' || badoption[1] == 'l')
lua_writestringerror("'%s' needs argument\n", badoption);
else
lua_writestringerror("unrecognized option '%s'\n", badoption);
lua_writestringerror(
"usage: %s [options] [script [args]]\n"
"Available options are:\n"
" -e stat execute string 'stat'\n"
" -i enter interactive mode after executing 'script'\n"
" -l mod require library 'mod' into global 'mod'\n"
" -l g=mod require library 'mod' into global 'g'\n"
" -v show version information\n"
" -E ignore environment variables\n"
" -W turn warnings on\n"
" -- stop handling options\n"
" - stop handling options and execute stdin\n",
progname);
}
/*
** Prints an error message, adding the program name in front of it
** (if present)
*/
static void
l_message(const char *pname, const char *msg)
{
if (pname)
lua_writestringerror("%s: ", pname);
lua_writestringerror("%s\n", msg);
}
/*
** Check whether 'status' is not OK and, if so, prints the error
** message on the top of the stack. It assumes that the error object
** is a string, as it was either generated by Lua or by 'msghandler'.
*/
static int
report(lua_State *L, int status)
{
if (status != LUA_OK) {
const char *msg = lua_tostring(L, -1);
l_message(progname, msg);
lua_pop(L, 1); /* remove message */
}
return status;
}
/*
** Message handler used to run all chunks
*/
static int
msghandler(lua_State *L)
{
const char *msg = lua_tostring(L, 1);
if (msg == NULL) { /* is error object not a string? */
if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */
lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */
return 1; /* that is the message */
else
msg = lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1));
}
luaL_traceback(L, L, msg, 1); /* append a standard traceback */
return 1; /* return the traceback */
}
/*
** Interface to 'lua_pcall', which sets appropriate message function
** and C-signal handler. Used to run all chunks.
*/
static int
docall(lua_State *L, int narg, int nres)
{
int status;
int base = lua_gettop(L) - narg; /* function index */
lua_pushcfunction(L, msghandler); /* push message handler */
lua_insert(L, base); /* put it under function and args */
globalL = L; /* to be available to 'laction' */
setsignal(SIGINT, laction); /* set C-signal handler */
status = lua_pcall(L, narg, nres, base);
setsignal(SIGINT, SIG_DFL); /* reset C-signal handler */
lua_remove(L, base); /* remove message handler from the stack */
return status;
}
static void
print_version(void)
{
lua_writestring(LUA_COPYRIGHT, luaport_strlen(LUA_COPYRIGHT));
lua_writeline();
}
/*
** Create the 'arg' table, which stores all arguments from the
** command line ('argv'). It should be aligned so that, at index 0,
** it has 'argv[script]', which is the script name. The arguments
** to the script (everything after 'script') go to positive indices;
** other arguments (before the script name) go to negative indices.
** If there is no script name, assume interpreter's name as base.
*/
static void
createargtable(lua_State *L, char **argv, int argc, int script)
{
int i, narg;
if (script == argc)
script = 0; /* no script name? */
narg = argc - (script + 1); /* number of positive indices */
lua_createtable(L, narg, script + 1);
for (i = 0; i < argc; i++) {
lua_pushstring(L, argv[i]);
lua_rawseti(L, -2, i - script);
}
lua_setglobal(L, "arg");
}
static int
dochunk(lua_State *L, int status)
{
if (status == LUA_OK)
status = docall(L, 0, 0);
return report(L, status);
}
static int
dofile(lua_State *L, const char *name)
{
return dochunk(L, luaL_loadfile(L, name));
}
static int
dostring(lua_State *L, const char *s, const char *name)
{
return dochunk(L, luaL_loadbuffer(L, s, luaport_strlen(s), name));
}
/*
** Receives 'globname[=modname]' and runs 'globname = require(modname)'.
*/
static int
dolibrary(lua_State *L, char *globname)
{
int status;
char *modname = luaport_strchr(globname, '=');
if (modname == NULL) /* no explicit name? */
modname = globname; /* module name is equal to global name */
else {
*modname = '\0'; /* global name ends here */
modname++; /* module name starts after the '=' */
}
lua_getglobal(L, "require");
lua_pushstring(L, modname);
status = docall(L, 1, 1); /* call 'require(modname)' */
if (status == LUA_OK)
lua_setglobal(L, globname); /* globname = require(modname) */
return report(L, status);
}
/*
** Push on the stack the contents of table 'arg' from 1 to #arg
*/
static int
pushargs(lua_State *L)
{
int i, n;
if (lua_getglobal(L, "arg") != LUA_TTABLE)
luaL_error(L, "'arg' is not a table");
n = (int)luaL_len(L, -1);
luaL_checkstack(L, n + 3, "too many arguments to script");
for (i = 1; i <= n; i++)
lua_rawgeti(L, -i, i);
lua_remove(L, -i); /* remove table from the stack */
return n;
}
static int
handle_script(lua_State *L, char **argv)
{
int status;
const char *fname = argv[0];
if (luaport_strcmp(fname, "-") == 0 && luaport_strcmp(argv[-1], "--") != 0)
fname = NULL; /* stdin */
status = luaL_loadfile(L, fname);
if (status == LUA_OK) {
int n = pushargs(L); /* push arguments to script */
status = docall(L, n, LUA_MULTRET);
}
return report(L, status);
}
/* bits of various argument indicators in 'args' */
#define has_error 1 /* bad option */
#define has_i 2 /* -i */
#define has_v 4 /* -v */
#define has_e 8 /* -e */
#define has_E 16 /* -E */
/*
** Traverses all arguments from 'argv', returning a mask with those
** needed before running any Lua code (or an error code if it finds
** any invalid argument). 'first' returns the first not-handled argument
** (either the script name or a bad argument in case of error).
*/
static int
collectargs(char **argv, int *first)
{
int args = 0;
int i;
for (i = 1; argv[i] != NULL; i++) {
*first = i;
if (argv[i][0] != '-') /* not an option? */
return args; /* stop handling options */
switch (argv[i][1]) { /* else check option */
case '-': /* '--' */
if (argv[i][2] != '\0') /* extra characters after '--'? */
return has_error; /* invalid option */
*first = i + 1;
return args;
case '\0': /* '-' */
return args; /* script "name" is '-' */
case 'E':
if (argv[i][2] != '\0') /* extra characters? */
return has_error; /* invalid option */
args |= has_E;
break;
case 'W':
if (argv[i][2] != '\0') /* extra characters? */
return has_error; /* invalid option */
break;
case 'i':
args |= has_i; /* (-i implies -v) */ /* FALLTHROUGH */
case 'v':
if (argv[i][2] != '\0') /* extra characters? */
return has_error; /* invalid option */
args |= has_v;
break;
case 'e':
args |= has_e; /* FALLTHROUGH */
case 'l': /* both options need an argument */
if (argv[i][2] == '\0') { /* no concatenated argument? */
i++; /* try next 'argv' */
if (argv[i] == NULL || argv[i][0] == '-')
return has_error; /* no next argument or it is another option */
}
break;
default: /* invalid option */
return has_error;
}
}
*first = i; /* no script name */
return args;
}
/*
** Processes options 'e' and 'l', which involve running Lua code, and
** 'W', which also affects the state.
** Returns 0 if some code raises an error.
*/
static int
runargs(lua_State *L, char **argv, int n)
{
int i;
for (i = 1; i < n; i++) {
int option = argv[i][1];
lua_assert(argv[i][0] == '-'); /* already checked */
switch (option) {
case 'e':
case 'l': {
int status;
char *extra = argv[i] + 2; /* both options need an argument */
if (*extra == '\0')
extra = argv[++i];
lua_assert(extra != NULL);
status = (option == 'e') ? dostring(L, extra, "=(command line)") : dolibrary(L, extra);
if (status != LUA_OK)
return 0;
break;
}
case 'W':
lua_warning(L, "@on", 0); /* warnings on */
break;
}
}
return 1;
}
static int
handle_luainit(lua_State *L)
{
const char *name = "=" LUA_INITVARVERSION;
const char *init = luaport_getenv(name + 1);
if (init == NULL) {
name = "=" LUA_INIT_VAR;
init = luaport_getenv(name + 1); /* try alternative name */
}
if (init == NULL)
return LUA_OK;
else if (init[0] == '@')
return dofile(L, init + 1);
else
return dostring(L, init, name);
}
/*
** {==================================================================
** Read-Eval-Print Loop (REPL)
** ===================================================================
*/
#if !defined(LUA_PROMPT)
#define LUA_PROMPT "> "
#define LUA_PROMPT2 ">> "
#endif
#if !defined(LUA_MAXINPUT)
#define LUA_MAXINPUT 512
#endif
/*
** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
** is, whether we're running lua interactively).
*/
#if !defined(lua_stdin_is_tty) /* { */
#if defined(LUA_USE_POSIX) /* { */
#include <unistd.h>
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_USE_WINDOWS) /* }{ */
#include <io.h>
#include <windows.h>
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else /* }{ */
/* ISO C definition */
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
#endif /* } */
#endif /* } */
/*
** lua_readline defines how to show a prompt and then read a line from
** the standard input.
** lua_saveline defines how to "save" a read line in a "history".
** lua_freeline defines how to free a line read by lua_readline.
*/
#if !defined(lua_readline) /* { */
#if defined(LUA_USE_READLINE) /* { */
#include <readline/readline.h>
#include <readline/history.h>
#define lua_initreadline(L) ((void)L, rl_readline_name = "lua")
#define lua_readline(L, b, p) ((void)L, ((b) = readline(p)) != NULL)
#define lua_saveline(L, line) ((void)L, add_history(line))
#define lua_freeline(L, b) ((void)L, free(b))
#else /* }{ */
#define lua_initreadline(L) ((void)L)
#define lua_readline(L, b, p) \
((void)L, luaport_fputs(p, luaport_stdout), luaport_fflush(luaport_stdout), /* show prompt */ \
luaport_fgets(b, LUA_MAXINPUT, luaport_stdin) != NULL) /* get line */
#define lua_saveline(L, line) \
{ \
(void)L; \
(void)line; \
}
#define lua_freeline(L, b) \
{ \
(void)L; \
(void)b; \
}
#endif /* } */
#endif /* } */
/*
** Return the string to be used as a prompt by the interpreter. Leave
** the string (or nil, if using the default value) on the stack, to keep
** it anchored.
*/
static const char *
get_prompt(lua_State *L, int firstline)
{
if (lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2") == LUA_TNIL)
return (firstline ? LUA_PROMPT : LUA_PROMPT2); /* use the default */
else { /* apply 'tostring' over the value */
const char *p = luaL_tolstring(L, -1, NULL);
lua_remove(L, -2); /* remove original value */
return p;
}
}
/* mark in error messages for incomplete statements */
#define EOFMARK "<eof>"
#define marklen (sizeof(EOFMARK) / sizeof(char) - 1)
/*
** Check whether 'status' signals a syntax error and the error
** message at the top of the stack ends with the above mark for
** incomplete statements.
*/
static int
incomplete(lua_State *L, int status)
{
if (status == LUA_ERRSYNTAX) {
size_t lmsg;
const char *msg = lua_tolstring(L, -1, &lmsg);
if (lmsg >= marklen && luaport_strcmp(msg + lmsg - marklen, EOFMARK) == 0) {
lua_pop(L, 1);
return 1;
}
}
return 0; /* else... */
}
/*
** Prompt the user, read a line, and push it into the Lua stack.
*/
static int
pushline(lua_State *L, int firstline)
{
char buffer[LUA_MAXINPUT];
char *b = buffer;
size_t l;
const char *prmt = get_prompt(L, firstline);
int readstatus = lua_readline(L, b, prmt);
if (readstatus == 0)
return 0; /* no input (prompt will be popped by caller) */
lua_pop(L, 1); /* remove prompt */
l = luaport_strlen(b);
if (l > 0 && b[l - 1] == '\n') /* line ends with newline? */
b[--l] = '\0'; /* remove it */
if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */
lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */
else
lua_pushlstring(L, b, l);
lua_freeline(L, b);
return 1;
}
/*
** Try to compile line on the stack as 'return <line>;'; on return, stack
** has either compiled chunk or original line (if compilation failed).
*/
static int
addreturn(lua_State *L)
{
const char *line = lua_tostring(L, -1); /* original line */
const char *retline = lua_pushfstring(L, "return %s;", line);
int status = luaL_loadbuffer(L, retline, luaport_strlen(retline), "=stdin");
if (status == LUA_OK) {
lua_remove(L, -2); /* remove modified line */
if (line[0] != '\0') /* non empty? */
lua_saveline(L, line); /* keep history */
} else
lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */
return status;
}
/*
** Read multiple lines until a complete Lua statement
*/
static int
multiline(lua_State *L)
{
for (;;) { /* repeat until gets a complete statement */
size_t len;
const char *line = lua_tolstring(L, 1, &len); /* get what it has */
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
if (!incomplete(L, status) || !pushline(L, 0)) {
lua_saveline(L, line); /* keep history */
return status; /* cannot or should not try to add continuation line */
}
lua_pushliteral(L, "\n"); /* add newline... */
lua_insert(L, -2); /* ...between the two lines */
lua_concat(L, 3); /* join them */
}
}
/*
** Read a line and try to load (compile) it first as an expression (by
** adding "return " in front of it) and second as a statement. Return
** the final status of load/call with the resulting function (if any)
** in the top of the stack.
*/
static int
loadline(lua_State *L)
{
int status;
lua_settop(L, 0);
if (!pushline(L, 1))
return -1; /* no input */
if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */
status = multiline(L); /* try as command, maybe with continuation lines */
lua_remove(L, 1); /* remove line from the stack */
lua_assert(lua_gettop(L) == 1);
return status;
}
/*
** Prints (calling the Lua 'print' function) any values on the stack
*/
static void
l_print(lua_State *L)
{
int n = lua_gettop(L);
if (n > 0) { /* any result to be printed? */
luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
lua_getglobal(L, "print");
lua_insert(L, 1);
if (lua_pcall(L, n, 0, 0) != LUA_OK)
l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)", lua_tostring(L, -1)));
}
}
/*
** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and
** print any results.
*/
static void
doREPL(lua_State *L)
{
int status;
const char *oldprogname = progname;
progname = NULL; /* no 'progname' on errors in interactive mode */
lua_initreadline(L);
while ((status = loadline(L)) != -1) {
if (status == LUA_OK)
status = docall(L, 0, LUA_MULTRET);
if (status == LUA_OK)
l_print(L);
else
report(L, status);
}
lua_settop(L, 0); /* clear stack */
lua_writeline();
progname = oldprogname;
}
/* }================================================================== */
/*
** Main body of stand-alone interpreter (to be called in protected mode).
** Reads the options and handles them all.
*/
static int
pmain(lua_State *L)
{
int argc = (int)lua_tointeger(L, 1);
char **argv = (char **)lua_touserdata(L, 2);
int script;
int args = collectargs(argv, &script);
luaL_checkversion(L); /* check that interpreter has correct version */
if (argv[0] && argv[0][0])
progname = argv[0];
if (args == has_error) { /* bad arg? */
print_usage(argv[script]); /* 'script' has index of bad arg. */
return 0;
}
if (args & has_v) /* option '-v'? */
print_version();
if (args & has_E) { /* option '-E'? */
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
}
luaL_openlibs(L); /* open standard libraries */
createargtable(L, argv, argc, script); /* create table 'arg' */
lua_gc(L, LUA_GCGEN, 0, 0); /* GC in generational mode */
if (!(args & has_E)) { /* no option '-E'? */
if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
return 0; /* error running LUA_INIT */
}
if (!runargs(L, argv, script)) /* execute arguments -e and -l */
return 0; /* something failed */
if (script < argc && /* execute main script (if there is one) */
handle_script(L, argv + script) != LUA_OK)
return 0;
if (args & has_i) /* -i option? */
doREPL(L); /* do read-eval-print loop */
else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */
if (lua_stdin_is_tty()) { /* running in interactive mode? */
print_version();
doREPL(L); /* do read-eval-print loop */
} else
dofile(L, NULL); /* executes stdin as a file */
}
lua_pushboolean(L, 1); /* signal no errors */
return 1;
}
int lua_main(int argc, char **argv)
{
int status, result;
lua_State *L = luaL_newstate(); /* create state */
if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
}
lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
lua_pushinteger(L, argc); /* 1st argument */
lua_pushlightuserdata(L, argv); /* 2nd argument */
status = lua_pcall(L, 2, 1, 0); /* do the call */
result = lua_toboolean(L, -1); /* get result */
report(L, status);
lua_close(L);
return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View file

@ -0,0 +1,775 @@
/*
** $Id: luac.c $
** Lua compiler (saves bytecodes to files; also lists bytecodes)
** See Copyright Notice in lua.h
*/
#define luac_c
#define LUA_CORE
#include "lprefix.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "ldebug.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lopnames.h"
#include "lstate.h"
#include "lundump.h"
static void PrintFunction(const Proto *f, int full);
#define luaU_print PrintFunction
#define PROGNAME "luac" /* default program name */
#define OUTPUT PROGNAME ".out" /* default output file */
static int listing = 0; /* list bytecodes? */
static int dumping = 1; /* dump bytecodes? */
static int stripping = 0; /* strip debug information? */
static char Output[] = { OUTPUT }; /* default output file name */
static const char *output = Output; /* actual output file name */
static const char *progname = PROGNAME; /* actual program name */
static TString **tmname;
static void fatal(const char *message)
{
luaport_fprintf(luaport_stderr, "%s: %s\n", progname, message);
luaport_exit(EXIT_FAILURE);
}
static void cannot(const char *what)
{
luaport_fprintf(luaport_stderr, "%s: cannot %s %s: %s\n", progname, what, output, luaport_strerror(luaport_errno));
luaport_exit(EXIT_FAILURE);
}
static void usage(const char *message)
{
if (*message == '-')
luaport_fprintf(luaport_stderr, "%s: unrecognized option '%s'\n", progname, message);
else
luaport_fprintf(luaport_stderr, "%s: %s\n", progname, message);
luaport_fprintf(luaport_stderr,
"usage: %s [options] [filenames]\n"
"Available options are:\n"
" -l list (use -l -l for full listing)\n"
" -o name output to file 'name' (default is \"%s\")\n"
" -p parse only\n"
" -s strip debug information\n"
" -v show version information\n"
" -- stop handling options\n"
" - stop handling options and process stdin\n",
progname, Output);
luaport_exit(EXIT_FAILURE);
}
#define IS(s) (luaport_strcmp(argv[i], s) == 0)
static int doargs(int argc, char *argv[])
{
int i;
int version = 0;
if (argv[0] != NULL && *argv[0] != 0)
progname = argv[0];
for (i = 1; i < argc; i++) {
if (*argv[i] != '-') /* end of options; keep it */
break;
else if (IS("--")) /* end of options; skip it */
{
++i;
if (version)
++version;
break;
} else if (IS("-")) /* end of options; use stdin */
break;
else if (IS("-l")) /* list */
++listing;
else if (IS("-o")) /* output file */
{
output = argv[++i];
if (output == NULL || *output == 0 || (*output == '-' && output[1] != 0))
usage("'-o' needs argument");
if (IS("-"))
output = NULL;
} else if (IS("-p")) /* parse only */
dumping = 0;
else if (IS("-s")) /* strip debug information */
stripping = 1;
else if (IS("-v")) /* show version */
++version;
else /* unknown option */
usage(argv[i]);
}
if (i == argc && (listing || !dumping)) {
dumping = 0;
argv[--i] = Output;
}
if (version) {
luaport_printf("%s\n", LUA_COPYRIGHT);
if (version == argc - 1)
luaport_exit(EXIT_SUCCESS);
}
return i;
}
#define FUNCTION "(function()end)();"
static const char *reader(lua_State *L, void *ud, size_t *size)
{
UNUSED(L);
if ((*(int *)ud)--) {
*size = sizeof(FUNCTION) - 1;
return FUNCTION;
} else {
*size = 0;
return NULL;
}
}
#define toproto(L, i) getproto(s2v(L->top + (i)))
static const Proto *combine(lua_State *L, int n)
{
if (n == 1)
return toproto(L, -1);
else {
Proto *f;
int i = n;
if (lua_load(L, reader, &i, "=(" PROGNAME ")", NULL) != LUA_OK)
fatal(lua_tostring(L, -1));
f = toproto(L, -1);
for (i = 0; i < n; i++) {
f->p[i] = toproto(L, i - n - 1);
if (f->p[i]->sizeupvalues > 0)
f->p[i]->upvalues[0].instack = 0;
}
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
f->sizelineinfo = 0;
return f;
}
}
static int writer(lua_State *L, const void *p, size_t size, void *u)
{
UNUSED(L);
return (luaport_fwrite(p, size, 1, (FILE *)u) != 1) && (size != 0);
}
static int pmain(lua_State *L)
{
int argc = (int)lua_tointeger(L, 1);
char **argv = (char **)lua_touserdata(L, 2);
const Proto *f;
int i;
tmname = G(L)->tmname;
if (!lua_checkstack(L, argc))
fatal("too many input files");
for (i = 0; i < argc; i++) {
const char *filename = IS("-") ? NULL : argv[i];
if (luaL_loadfile(L, filename) != LUA_OK)
fatal(lua_tostring(L, -1));
}
f = combine(L, argc);
if (listing)
luaU_print(f, listing > 1);
if (dumping) {
FILE *D = (output == NULL) ? luaport_stdout : luaport_fopen(output, "wb");
if (D == NULL)
cannot("open");
lua_lock(L);
luaU_dump(L, f, writer, D, stripping);
lua_unlock(L);
if (luaport_ferror(D))
cannot("write");
if (luaport_fclose(D))
cannot("close");
}
return 0;
}
int main(int argc, char *argv[])
{
lua_State *L;
int i = doargs(argc, argv);
argc -= i;
argv += i;
if (argc <= 0)
usage("no input files given");
L = luaL_newstate();
if (L == NULL)
fatal("cannot create state: not enough memory");
lua_pushcfunction(L, &pmain);
lua_pushinteger(L, argc);
lua_pushlightuserdata(L, argv);
if (lua_pcall(L, 2, 0, 0) != LUA_OK)
fatal(lua_tostring(L, -1));
lua_close(L);
return EXIT_SUCCESS;
}
/*
** print bytecodes
*/
#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
#define VOID(p) ((const void *)(p))
#define eventname(i) (getstr(tmname[i]))
static void PrintString(const TString *ts)
{
const char *s = getstr(ts);
size_t i, n = tsslen(ts);
luaport_printf("\"");
for (i = 0; i < n; i++) {
int c = (int)(unsigned char)s[i];
switch (c) {
case '"':
luaport_printf("\\\"");
break;
case '\\':
luaport_printf("\\\\");
break;
case '\a':
luaport_printf("\\a");
break;
case '\b':
luaport_printf("\\b");
break;
case '\f':
luaport_printf("\\f");
break;
case '\n':
luaport_printf("\\n");
break;
case '\r':
luaport_printf("\\r");
break;
case '\t':
luaport_printf("\\t");
break;
case '\v':
luaport_printf("\\v");
break;
default:
if (isprint(c))
luaport_printf("%c", c);
else
luaport_printf("\\%03d", c);
break;
}
}
luaport_printf("\"");
}
static void PrintType(const Proto *f, int i)
{
const TValue *o = &f->k[i];
switch (ttypetag(o)) {
case LUA_VNIL:
luaport_printf("N");
break;
case LUA_VFALSE:
case LUA_VTRUE:
luaport_printf("B");
break;
case LUA_VNUMFLT:
luaport_printf("F");
break;
case LUA_VNUMINT:
luaport_printf("I");
break;
case LUA_VSHRSTR:
case LUA_VLNGSTR:
luaport_printf("S");
break;
default: /* cannot happen */
luaport_printf("?%d", ttypetag(o));
break;
}
luaport_printf("\t");
}
static void PrintConstant(const Proto *f, int i)
{
const TValue *o = &f->k[i];
switch (ttypetag(o)) {
case LUA_VNIL:
luaport_printf("nil");
break;
case LUA_VFALSE:
luaport_printf("false");
break;
case LUA_VTRUE:
luaport_printf("true");
break;
case LUA_VNUMFLT: {
char buff[100];
luaport_sprintf(buff, LUA_NUMBER_FMT, fltvalue(o));
luaport_printf("%s", buff);
if (buff[luaport_strspn(buff, "-0123456789")] == '\0')
luaport_printf(".0");
break;
}
case LUA_VNUMINT:
luaport_printf(LUA_INTEGER_FMT, ivalue(o));
break;
case LUA_VSHRSTR:
case LUA_VLNGSTR:
PrintString(tsvalue(o));
break;
default: /* cannot happen */
luaport_printf("?%d", ttypetag(o));
break;
}
}
#define COMMENT "\t; "
#define EXTRAARG GETARG_Ax(code[pc + 1])
#define EXTRAARGC (EXTRAARG * (MAXARG_C + 1))
#define ISK (isk ? "k" : "")
static void PrintCode(const Proto *f)
{
const Instruction *code = f->code;
int pc, n = f->sizecode;
for (pc = 0; pc < n; pc++) {
Instruction i = code[pc];
OpCode o = GET_OPCODE(i);
int a = GETARG_A(i);
int b = GETARG_B(i);
int c = GETARG_C(i);
int ax = GETARG_Ax(i);
int bx = GETARG_Bx(i);
int sb = GETARG_sB(i);
int sc = GETARG_sC(i);
int sbx = GETARG_sBx(i);
int isk = GETARG_k(i);
int line = luaG_getfuncline(f, pc);
luaport_printf("\t%d\t", pc + 1);
if (line > 0)
luaport_printf("[%d]\t", line);
else
luaport_printf("[-]\t");
luaport_printf("%-9s\t", opnames[o]);
switch (o) {
case OP_MOVE:
luaport_printf("%d %d", a, b);
break;
case OP_LOADI:
luaport_printf("%d %d", a, sbx);
break;
case OP_LOADF:
luaport_printf("%d %d", a, sbx);
break;
case OP_LOADK:
luaport_printf("%d %d", a, bx);
luaport_printf(COMMENT);
PrintConstant(f, bx);
break;
case OP_LOADKX:
luaport_printf("%d", a);
luaport_printf(COMMENT);
PrintConstant(f, EXTRAARG);
break;
case OP_LOADFALSE:
luaport_printf("%d", a);
break;
case OP_LFALSESKIP:
luaport_printf("%d", a);
break;
case OP_LOADTRUE:
luaport_printf("%d", a);
break;
case OP_LOADNIL:
luaport_printf("%d %d", a, b);
luaport_printf(COMMENT "%d out", b + 1);
break;
case OP_GETUPVAL:
luaport_printf("%d %d", a, b);
luaport_printf(COMMENT "%s", UPVALNAME(b));
break;
case OP_SETUPVAL:
luaport_printf("%d %d", a, b);
luaport_printf(COMMENT "%s", UPVALNAME(b));
break;
case OP_GETTABUP:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT "%s", UPVALNAME(b));
luaport_printf(" ");
PrintConstant(f, c);
break;
case OP_GETTABLE:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_GETI:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_GETFIELD:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_SETTABUP:
luaport_printf("%d %d %d%s", a, b, c, ISK);
luaport_printf(COMMENT "%s", UPVALNAME(a));
luaport_printf(" ");
PrintConstant(f, b);
if (isk) {
luaport_printf(" ");
PrintConstant(f, c);
}
break;
case OP_SETTABLE:
luaport_printf("%d %d %d%s", a, b, c, ISK);
if (isk) {
luaport_printf(COMMENT);
PrintConstant(f, c);
}
break;
case OP_SETI:
luaport_printf("%d %d %d%s", a, b, c, ISK);
if (isk) {
luaport_printf(COMMENT);
PrintConstant(f, c);
}
break;
case OP_SETFIELD:
luaport_printf("%d %d %d%s", a, b, c, ISK);
luaport_printf(COMMENT);
PrintConstant(f, b);
if (isk) {
luaport_printf(" ");
PrintConstant(f, c);
}
break;
case OP_NEWTABLE:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT "%d", c + EXTRAARGC);
break;
case OP_SELF:
luaport_printf("%d %d %d%s", a, b, c, ISK);
if (isk) {
luaport_printf(COMMENT);
PrintConstant(f, c);
}
break;
case OP_ADDI:
luaport_printf("%d %d %d", a, b, sc);
break;
case OP_ADDK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_SUBK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_MULK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_MODK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_POWK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_DIVK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_IDIVK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_BANDK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_BORK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_BXORK:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
PrintConstant(f, c);
break;
case OP_SHRI:
luaport_printf("%d %d %d", a, b, sc);
break;
case OP_SHLI:
luaport_printf("%d %d %d", a, b, sc);
break;
case OP_ADD:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_SUB:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_MUL:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_MOD:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_POW:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_DIV:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_IDIV:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_BAND:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_BOR:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_BXOR:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_SHL:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_SHR:
luaport_printf("%d %d %d", a, b, c);
break;
case OP_MMBIN:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT "%s", eventname(c));
break;
case OP_MMBINI:
luaport_printf("%d %d %d %d", a, sb, c, isk);
luaport_printf(COMMENT "%s", eventname(c));
if (isk)
luaport_printf(" flip");
break;
case OP_MMBINK:
luaport_printf("%d %d %d %d", a, b, c, isk);
luaport_printf(COMMENT "%s ", eventname(c));
PrintConstant(f, b);
if (isk)
luaport_printf(" flip");
break;
case OP_UNM:
luaport_printf("%d %d", a, b);
break;
case OP_BNOT:
luaport_printf("%d %d", a, b);
break;
case OP_NOT:
luaport_printf("%d %d", a, b);
break;
case OP_LEN:
luaport_printf("%d %d", a, b);
break;
case OP_CONCAT:
luaport_printf("%d %d", a, b);
break;
case OP_CLOSE:
luaport_printf("%d", a);
break;
case OP_TBC:
luaport_printf("%d", a);
break;
case OP_JMP:
luaport_printf("%d", GETARG_sJ(i));
luaport_printf(COMMENT "to %d", GETARG_sJ(i) + pc + 2);
break;
case OP_EQ:
luaport_printf("%d %d %d", a, b, isk);
break;
case OP_LT:
luaport_printf("%d %d %d", a, b, isk);
break;
case OP_LE:
luaport_printf("%d %d %d", a, b, isk);
break;
case OP_EQK:
luaport_printf("%d %d %d", a, b, isk);
luaport_printf(COMMENT);
PrintConstant(f, b);
break;
case OP_EQI:
luaport_printf("%d %d %d", a, sb, isk);
break;
case OP_LTI:
luaport_printf("%d %d %d", a, sb, isk);
break;
case OP_LEI:
luaport_printf("%d %d %d", a, sb, isk);
break;
case OP_GTI:
luaport_printf("%d %d %d", a, sb, isk);
break;
case OP_GEI:
luaport_printf("%d %d %d", a, sb, isk);
break;
case OP_TEST:
luaport_printf("%d %d", a, isk);
break;
case OP_TESTSET:
luaport_printf("%d %d %d", a, b, isk);
break;
case OP_CALL:
luaport_printf("%d %d %d", a, b, c);
luaport_printf(COMMENT);
if (b == 0)
luaport_printf("all in ");
else
luaport_printf("%d in ", b - 1);
if (c == 0)
luaport_printf("all out");
else
luaport_printf("%d out", c - 1);
break;
case OP_TAILCALL:
luaport_printf("%d %d %d%s", a, b, c, ISK);
luaport_printf(COMMENT "%d in", b - 1);
break;
case OP_RETURN:
luaport_printf("%d %d %d%s", a, b, c, ISK);
luaport_printf(COMMENT);
if (b == 0)
luaport_printf("all out");
else
luaport_printf("%d out", b - 1);
break;
case OP_RETURN0:
break;
case OP_RETURN1:
luaport_printf("%d", a);
break;
case OP_FORLOOP:
luaport_printf("%d %d", a, bx);
luaport_printf(COMMENT "to %d", pc - bx + 2);
break;
case OP_FORPREP:
luaport_printf("%d %d", a, bx);
luaport_printf(COMMENT "exit to %d", pc + bx + 3);
break;
case OP_TFORPREP:
luaport_printf("%d %d", a, bx);
luaport_printf(COMMENT "to %d", pc + bx + 2);
break;
case OP_TFORCALL:
luaport_printf("%d %d", a, c);
break;
case OP_TFORLOOP:
luaport_printf("%d %d", a, bx);
luaport_printf(COMMENT "to %d", pc - bx + 2);
break;
case OP_SETLIST:
luaport_printf("%d %d %d", a, b, c);
if (isk)
luaport_printf(COMMENT "%d", c + EXTRAARGC);
break;
case OP_CLOSURE:
luaport_printf("%d %d", a, bx);
luaport_printf(COMMENT "%p", VOID(f->p[bx]));
break;
case OP_VARARG:
luaport_printf("%d %d", a, c);
luaport_printf(COMMENT);
if (c == 0)
luaport_printf("all out");
else
luaport_printf("%d out", c - 1);
break;
case OP_VARARGPREP:
luaport_printf("%d", a);
break;
case OP_EXTRAARG:
luaport_printf("%d", ax);
break;
#if 0
default:
luaport_printf("%d %d %d",a,b,c);
luaport_printf(COMMENT "not handled");
break;
#endif
}
luaport_printf("\n");
}
}
#define SS(x) ((x == 1) ? "" : "s")
#define S(x) (int)(x), SS(x)
static void PrintHeader(const Proto *f)
{
const char *s = f->source ? getstr(f->source) : "=?";
if (*s == '@' || *s == '=')
s++;
else if (*s == LUA_SIGNATURE[0])
s = "(bstring)";
else
s = "(string)";
luaport_printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
(f->linedefined == 0) ? "main" : "function", s,
f->linedefined, f->lastlinedefined,
S(f->sizecode), VOID(f));
luaport_printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
(int)(f->numparams), f->is_vararg ? "+" : "", SS(f->numparams),
S(f->maxstacksize), S(f->sizeupvalues));
luaport_printf("%d local%s, %d constant%s, %d function%s\n",
S(f->sizelocvars), S(f->sizek), S(f->sizep));
}
static void PrintDebug(const Proto *f)
{
int i, n;
n = f->sizek;
luaport_printf("constants (%d) for %p:\n", n, VOID(f));
for (i = 0; i < n; i++) {
luaport_printf("\t%d\t", i);
PrintType(f, i);
PrintConstant(f, i);
luaport_printf("\n");
}
n = f->sizelocvars;
luaport_printf("locals (%d) for %p:\n", n, VOID(f));
for (i = 0; i < n; i++) {
luaport_printf("\t%d\t%s\t%d\t%d\n",
i, getstr(f->locvars[i].varname), f->locvars[i].startpc + 1, f->locvars[i].endpc + 1);
}
n = f->sizeupvalues;
luaport_printf("upvalues (%d) for %p:\n", n, VOID(f));
for (i = 0; i < n; i++) {
luaport_printf("\t%d\t%s\t%d\t%d\n",
i, UPVALNAME(i), f->upvalues[i].instack, f->upvalues[i].idx);
}
}
static void PrintFunction(const Proto *f, int full)
{
int i, n = f->sizep;
PrintHeader(f);
PrintCode(f);
if (full)
PrintDebug(f);
for (i = 0; i < n; i++)
PrintFunction(f->p[i], full);
}

View file

@ -32,6 +32,11 @@ struct shell _shell;
static struct shell *shell;
static char *shell_prompt_custom = NULL;
extern void shell_abort_exec(int sig);
extern int shell_start_exec(cmd_function_t func, int argc, char *argv[]);
extern void shell_dup_line(char *cmd, uint32_t length);
static volatile shell_sig_func_ptr shell_sig_func;
int shell_help(int argc, char **argv)
{
SHELL_DGB("shell commands list:\r\n");
@ -514,7 +519,10 @@ static int shell_exec_cmd(char *cmd, uint32_t length, int *retp)
}
/* exec this command */
*retp = cmd_func(argc, argv);
shell_signal(SHELL_SIGINT, SHELL_SIG_DFL);
shell_dup_line(cmd, length);
*retp = shell_start_exec(cmd_func, argc, argv);
// *retp = cmd_func(argc, argv);
return 0;
}
@ -626,6 +634,19 @@ void shell_handler(uint8_t data)
* right key:0x1b 0x5b 0x43
* left key: 0x1b 0x5b 0x44
*/
if (data == 0x03) {
/*!< ctrl + c */
if (shell_sig_func) {
shell_sig_func(SHELL_SIGINT);
if (shell_sig_func == shell_abort_exec) {
SHELL_PRINTF("^C");
data = '\r';
}
}
}
if (data == 0x1b) {
shell->stat = WAIT_SPEC_KEY;
return;
@ -865,3 +886,35 @@ void shell_init(void)
shell_set_print((void (*)(char *fmt, ...))printf);
SHELL_PRINTF(shell_get_prompt());
}
shell_sig_func_ptr shell_signal(int sig, shell_sig_func_ptr func)
{
shell_sig_func_ptr shell_sig_func_prev = shell_sig_func;
if (sig == SHELL_SIGINT) {
if (func == SHELL_SIG_DFL) {
shell_sig_func = shell_abort_exec;
} else if (func == SHELL_SIG_IGN) {
shell_sig_func = NULL;
} else {
shell_sig_func = func;
}
return shell_sig_func_prev;
}
return NULL;
}
__attribute__((weak)) void shell_abort_exec(int sig)
{
(void)sig;
}
__attribute__((weak)) int shell_start_exec(cmd_function_t func, int argc, char *argv[])
{
return func(argc, argv);
}
__attribute__((weak)) void shell_dup_line(char *cmd, uint32_t length)
{
(void)cmd;
(void)length;
}

View file

@ -39,7 +39,7 @@
} while (0)
#define SHELL_PRINTF(fmt, ...) shell_print(0, fmt, ##__VA_ARGS__)
#define SHELL_PROMPT(fmt, ...) shell_print(34, fmt, ##__VA_ARGS__)
#define SHELL_PROMPT(fmt, ...) shell_print(36, fmt, ##__VA_ARGS__)
#define SHELL_DGB(fmt, ...) shell_print(32, fmt, ##__VA_ARGS__)
#define SHELL_CMD(fmt, ...) shell_print(33, fmt, ##__VA_ARGS__)
#define SHELL_E(fmt, ...) shell_print(31, fmt, ##__VA_ARGS__)
@ -55,6 +55,11 @@
#define SHELL_MALLOC malloc
#define SHELL_FREE free
#define SHELL_SIGINT 1
#define SHELL_SIG_DFL ((shell_sig_func_ptr)0) /* Default action */
#define SHELL_SIG_IGN ((shell_sig_func_ptr)1) /* Ignore action */
typedef void (*shell_sig_func_ptr)(int);
typedef int (*syscall_func)(void);
typedef int (*cmd_function_t)(int argc, char **argv);
@ -157,4 +162,5 @@ void shell_handler(uint8_t data);
int shell_set_prompt(const char *prompt);
int shell_set_print(void (*shell_printf)(char *fmt, ...));
void shell_init(void);
shell_sig_func_ptr shell_signal(int sig, shell_sig_func_ptr func);
#endif

View file

@ -36,4 +36,12 @@
#define SHELL_THREAD_PRIO 5
#endif
#ifndef SHELL_EXEC_THREAD_STACK_SIZE
#define SHELL_EXEC_THREAD_STACK_SIZE 1024
#endif
#ifndef SHELL_EXEC_THREAD_PRIO
#define SHELL_EXEC_THREAD_PRIO 4
#endif
#endif

View file

@ -4,6 +4,62 @@
#include "ring_buffer.h"
#include "bflb_uart.h"
static int shell_exec_argc;
static char *shell_exec_argv[SHELL_ARG_NUM];
static char shell_exec_line[SHELL_CMD_SIZE];
static ptrdiff_t shell_exec_line_diff;
TaskHandle_t shell_exec_handle;
static ATTR_NOCACHE_RAM_SECTION volatile bool shell_exec_end = true;
static void shell_exec_task(void *pvParameters)
{
shell_exec_end = false;
__ASM volatile("fence");
((cmd_function_t)(pvParameters))(shell_exec_argc, shell_exec_argv);
shell_exec_end = true;
__ASM volatile("fence");
vTaskDelete(shell_exec_handle);
shell_exec_handle = NULL;
}
void shell_dup_line(char *cmd, uint32_t length)
{
memcpy(shell_exec_line, cmd, length);
shell_exec_line_diff = shell_exec_line - cmd;
}
void shell_abort_exec(int sig)
{
(void)sig;
if (shell_exec_end == false) {
shell_exec_end = true;
__ASM volatile("fence");
vTaskDelete(shell_exec_handle);
shell_exec_handle = NULL;
}
}
int shell_start_exec(cmd_function_t func, int argc, char *argv[])
{
BaseType_t xReturned;
shell_abort_exec(SHELL_SIGINT);
shell_exec_argc = argc;
for (uint8_t i = 0; i < argc; i++) {
shell_exec_argv[i] = argv[i] + shell_exec_line_diff;
}
__ASM volatile("fence");
xReturned = xTaskCreate(shell_exec_task, (char *)"shell_exec_task", SHELL_EXEC_THREAD_STACK_SIZE, func, SHELL_EXEC_THREAD_PRIO, &shell_exec_handle);
if (xReturned == pdPASS) {
return 0;
} else {
shell_exec_end = true;
return -1;
}
}
static TaskHandle_t shell_handle;
SemaphoreHandle_t sem_shell = NULL;

View file

@ -49,7 +49,15 @@ sdk_library_add_sources(class/msc/usbh_msc.c)
sdk_library_add_sources(class/hid/usbh_hid.c)
sdk_library_add_sources(class/hub/usbh_hub.c)
sdk_library_add_sources(class/video/usbh_video.c)
sdk_library_add_sources(class/audio/usbh_audio.c)
sdk_add_link_libraries(-ucdc_acm_class_driver -uhid_class_driver -umsc_class_driver -uvideo_class_ctrl_intf_driver)
sdk_add_link_libraries(
-ucdc_acm_class_driver
-uhid_class_driver
-umsc_class_driver
-uvideo_ctrl_class_driver
-uaudio_ctrl_class_driver)
# sdk_add_static_library(port/ehci/libehci_iso.a)
# add_subdirectory(port/ehci)
endif()

Some files were not shown because too many files have changed in this diff Show more