Compare commits
47 Commits
master
...
OpenHarmon
Author | SHA1 | Date |
---|---|---|
openharmony_ci | 5b44332cff | |
wanghao-free | 0d50fad855 | |
openharmony_ci | a37c850d1b | |
wanghao-free | 1eca7a502a | |
openharmony_ci | 80e24fa9db | |
wanghao-free | 15bded54c9 | |
openharmony_ci | 2a0db42072 | |
openharmony_ci | de82bf893a | |
openharmony_ci | a0bb06189d | |
openharmony_ci | a8513ae614 | |
wanghao-free | 0c203c1e57 | |
gao-rongxin | 93658ba478 | |
liu-zhanwei | 58aea01f5a | |
dong-yiqun | d39ed70c65 | |
openharmony_ci | 3e6bab5158 | |
wanghao-free | 672cff7ee5 | |
openharmony_ci | 3ad07bc40f | |
xukunrui | 1e8d5baf8c | |
openharmony_ci | b744cfa164 | |
YOUR_NAME | 51a24eaeb2 | |
openharmony_ci | 07fb6c150e | |
openharmony_ci | 7ceaf68832 | |
YOUR_NAME | 309e7569f8 | |
openharmony_ci | e42cb26b14 | |
Guangyao Ma | 8ab4c9a6bc | |
Guangyao Ma | a40dc411b2 | |
openharmony_ci | ebe33aa2f6 | |
YOUR_NAME | ece0e8ae06 | |
openharmony_ci | c059be5ec8 | |
YOUR_NAME | 723b3ff8e2 | |
openharmony_ci | 7cf342c29f | |
YOUR_NAME | 3b9ccc839e | |
openharmony_ci | 4f1e1619a5 | |
openharmony_ci | 6523c496c8 | |
zhushengle | 7648648887 | |
zhushengle | 1c0bbb66de | |
zhushengle | d44f3904cf | |
openharmony_ci | 5cbb83dc6e | |
mamingshuai | 13fa3d4403 | |
openharmony_ci | e9522d44bf | |
x_xiny | f30790c5c8 | |
openharmony_ci | a0bb801f67 | |
Far | 170aa8ba6f | |
openharmony_ci | 83b0e8f867 | |
YOUR_NAME | 6b5d6be42d | |
openharmony_ci | 8b27064848 | |
openharmony_ci | 1ad74ab8e4 |
|
@ -0,0 +1,11 @@
|
||||||
|
### 该问题是怎么引起的?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 重现步骤
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 报错信息
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
### 相关的Issue
|
||||||
|
|
||||||
|
|
||||||
|
### 原因(目的、解决的问题等)
|
||||||
|
|
||||||
|
|
||||||
|
### 描述(做了什么,变更了什么)
|
||||||
|
|
||||||
|
|
||||||
|
### 测试用例(新增、改动、可能影响的功能)
|
||||||
|
|
||||||
|
|
24
README.md
24
README.md
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
## Introduction<a name="section11660541593"></a>
|
## Introduction<a name="section11660541593"></a>
|
||||||
|
|
||||||
The OpenHarmony LiteOS Cortex-A is a new-generation kernel developed based on the Huawei LiteOS kernel. Huawei LiteOS is a lightweight operating system \(OS\) built for the Internet of Things \(IoT\) field. With the rapid development of the IoT industry, OpenHarmony LiteOS Cortex-A brings small-sized, low-power, and high-performance experience and builds a unified and open ecosystem for developers. In addition, it provides rich kernel mechanisms, more comprehensive Portable Operating System Interface \(POSIX\), and a unified driver framework, Hardware Driver Foundation \(HDF\), which offers unified access for device developers and friendly development experience for application developers. [Figure1](#fig27311582210) shows the architecture of the OpenHarmony LiteOS Cortex-A kernel.
|
The OpenHarmony LiteOS Cortex-A is a new-generation kernel developed based on the Huawei LiteOS kernel. Huawei LiteOS is a lightweight operating system \(OS\) built for the Internet of Things \(IoT\) field. With the rapid development of the IoT industry, OpenHarmony LiteOS Cortex-A brings small-sized, low-power, and high-performance experience and builds a unified and open ecosystem for developers. In addition, it provides rich kernel mechanisms, more comprehensive Portable Operating System Interface \(POSIX\), and a unified driver framework, Hardware Driver Foundation \(HDF\), which offers unified access for device developers and friendly development experience for application developers. [Figure 1](#fig27311582210) shows the architecture of the OpenHarmony LiteOS Cortex-A kernel.
|
||||||
|
|
||||||
**Figure 1** Architecture of the OpenHarmony LiteOS Cortex-A kernel<a name="fig27311582210"></a>
|
**Figure 1** Architecture of the OpenHarmony LiteOS Cortex-A kernel<a name="fig27311582210"></a>
|
||||||
![](figures/architecture-of-the-openharmony-liteos-cortex-a-kernel.png "architecture-of-the-openharmony-liteos-cortex-a-kernel")
|
![](figures/architecture-of-the-openharmony-liteos-cortex-a-kernel.png "architecture-of-the-openharmony-liteos-cortex-a-kernel")
|
||||||
|
@ -27,7 +27,7 @@ The OpenHarmony LiteOS Cortex-A is a new-generation kernel developed based on th
|
||||||
├── bsd # Code of the driver and adaptation layer module related to the FreeBSD, such as the USB module
|
├── bsd # Code of the driver and adaptation layer module related to the FreeBSD, such as the USB module
|
||||||
├── compat # Kernel API compatibility
|
├── compat # Kernel API compatibility
|
||||||
│ └── posix # POSIX APIs
|
│ └── posix # POSIX APIs
|
||||||
├── drivers # Kernel driver
|
├── drivers # Kernel drivers
|
||||||
│ └── char # Character device
|
│ └── char # Character device
|
||||||
│ ├── mem # Driver for accessing physical input/output (I/O) devices
|
│ ├── mem # Driver for accessing physical input/output (I/O) devices
|
||||||
│ ├── quickstart # APIs for quick start of the system
|
│ ├── quickstart # APIs for quick start of the system
|
||||||
|
@ -50,7 +50,7 @@ The OpenHarmony LiteOS Cortex-A is a new-generation kernel developed based on th
|
||||||
├── lib # Kernel library
|
├── lib # Kernel library
|
||||||
├── net # Network module, which mainly derives from the lwIP open-source project
|
├── net # Network module, which mainly derives from the lwIP open-source project
|
||||||
├── platform # Code for supporting different systems on a chip (SOCs), such as Hi3516D V300
|
├── platform # Code for supporting different systems on a chip (SOCs), such as Hi3516D V300
|
||||||
│ ├── hw # Logic code related to clocks and interupts
|
│ ├── hw # Logic code related to clocks and interrupts
|
||||||
│ ├── include # Header files exposed externally
|
│ ├── include # Header files exposed externally
|
||||||
│ └── uart # Logic code related to the serial port
|
│ └── uart # Logic code related to the serial port
|
||||||
├── platform # Code for supporting different systems on a chip (SOCs), such as Hi3516D V300
|
├── platform # Code for supporting different systems on a chip (SOCs), such as Hi3516D V300
|
||||||
|
@ -67,30 +67,32 @@ The OpenHarmony LiteOS Cortex-A is a new-generation kernel developed based on th
|
||||||
|
|
||||||
## Usage<a name="section741617511812"></a>
|
## Usage<a name="section741617511812"></a>
|
||||||
|
|
||||||
OpenHarmony LiteOS Cortex-A supports the [Hi3518E V300](https://gitee.com/openharmony/docs/blob/master/docs-en/quick-start/introduction-to-the-hi3518-development-board.md) and [Hi3516D V300](https://gitee.com/openharmony/docs/blob/master/docs-en/quick-start/introduction-to-the-hi3516-development-board.md). You can develop and run your applications based on both development boards.
|
OpenHarmony LiteOS Cortex-A supports the [Hi3518E V300](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/introduction-to-the-hi3518-development-board.md) and [Hi3516D V300](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/introduction-to-the-hi3516-development-board.md). You can develop and run your applications based on both development boards.
|
||||||
|
|
||||||
### Preparations<a name="section1579912573329"></a>
|
### Preparations<a name="section1579912573329"></a>
|
||||||
|
|
||||||
You need to set up the compilation environment on Linux.
|
You need to set up the compilation environment on Linux.
|
||||||
|
|
||||||
- For Hi3518E V300, see [Setting Up the Hi3518 Development Environment](https://gitee.com/openharmony/docs/blob/master/docs-en/quick-start/setting-up-the-hi3518-development-environment.md).
|
- For Hi3518E V300, see [Setting Up the Hi3518 Development Environment](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/setting-up-the-hi3518-development-environment.md).
|
||||||
- For Hi3516D V300, see [Setting Up the Hi3516 Development Environment](https://gitee.com/openharmony/docs/blob/master/docs-en/quick-start/setting-up-the-hi3516-development-environment.md).
|
- For Hi3516D V300, see [Setting Up the Hi3516 Development Environment](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/setting-up-the-hi3516-development-environment.md).
|
||||||
|
|
||||||
### Source Code Acquisition<a name="section11443189655"></a>
|
### Source Code Acquisition<a name="section11443189655"></a>
|
||||||
|
|
||||||
Download and decompress a set of source code on a Linux server to acquire the [source code](https://repo.huaweicloud.com/harmonyos/os/1.0/code-1.0.tar.gz). For more acquisition methods, see [Source Code Acquisition](https://gitee.com/openharmony/docs/blob/master/docs-en/get-code/source-code-acquisition.md).
|
Download and decompress a set of source code on a Linux server to acquire the [source code](https://repo.huaweicloud.com/harmonyos/os/1.0.1/code-1.0.1.tar.gz). For more acquisition methods, see [Source Code Acquisition](https://gitee.com/openharmony/docs/blob/master/en/device-dev/get-code/source-code-acquisition.md).
|
||||||
|
|
||||||
### Compilation and Building<a name="section2081013992812"></a>
|
### Compilation and Building<a name="section2081013992812"></a>
|
||||||
|
|
||||||
For details about how to develop the first application, see:
|
For details about how to develop the first application, see:
|
||||||
|
|
||||||
- [Developing the First Example Program Running on Hi3518](https://gitee.com/openharmony/docs/blob/master/docs-en/quick-start/developing-the-first-example-program-running-on-hi3518.md)
|
- [Developing the First Example Program Running on Hi3518](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/developing-the-first-example-program-running-on-hi3518.md)
|
||||||
|
|
||||||
- [Developing the First Example Program Running on Hi3516](https://gitee.com/openharmony/docs/blob/master/docs-en/quick-start/developing-the-first-example-program-running-on-hi3516.md)
|
- [Developing the First Example Program Running on Hi3516](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/developing-the-first-example-program-running-on-hi3516.md)
|
||||||
|
|
||||||
## Repositories Involved<a name="section1371113476307"></a>
|
## Repositories Involved<a name="section1371113476307"></a>
|
||||||
|
|
||||||
[drivers\_liteos](https://gitee.com/openharmony/drivers_liteos)
|
[Kernel subsystem](https://gitee.com/openharmony/docs/blob/master/en/readme/kernel.md)
|
||||||
|
|
||||||
**[kernel\_liteos\_a](https://gitee.com/openharmony/kernel_liteos_a)**
|
[drivers\_liteos](https://gitee.com/openharmony/drivers_liteos/blob/master/README.md)
|
||||||
|
|
||||||
|
**kernel\_liteos\_a**
|
||||||
|
|
||||||
|
|
18
README_zh.md
18
README_zh.md
|
@ -67,30 +67,32 @@ OpenHarmony LiteOS-A内核是基于Huawei LiteOS内核演进发展的新一代
|
||||||
|
|
||||||
## 使用说明<a name="section741617511812"></a>
|
## 使用说明<a name="section741617511812"></a>
|
||||||
|
|
||||||
OpenHarmony LiteOS-A内核支持Hi3518EV300([介绍](https://gitee.com/openharmony/docs/blob/master/quick-start/Hi3518%E5%BC%80%E5%8F%91%E6%9D%BF%E4%BB%8B%E7%BB%8D.md))、Hi3516DV300([介绍](https://gitee.com/openharmony/docs/blob/master/quick-start/Hi3516%E5%BC%80%E5%8F%91%E6%9D%BF%E4%BB%8B%E7%BB%8D.md))单板,开发者可基于两种单板开发运行自己的应用程序。
|
OpenHarmony LiteOS-A内核支持Hi3518EV300([介绍](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/Hi3518%E5%BC%80%E5%8F%91%E6%9D%BF%E4%BB%8B%E7%BB%8D.md))、Hi3516DV300([介绍](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/Hi3516%E5%BC%80%E5%8F%91%E6%9D%BF%E4%BB%8B%E7%BB%8D.md))单板,开发者可基于两种单板开发运行自己的应用程序。
|
||||||
|
|
||||||
### 准备<a name="section1579912573329"></a>
|
### 准备<a name="section1579912573329"></a>
|
||||||
|
|
||||||
开发者需要在Linux上搭建编译环境:
|
开发者需要在Linux上搭建编译环境:
|
||||||
|
|
||||||
- Hi3518EV300单板:参考[环境搭建](https://gitee.com/openharmony/docs/blob/master/quick-start/Hi3518%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83.md);
|
- Hi3518EV300单板:参考[环境搭建](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83.md);
|
||||||
- Hi3516DV300单板:参考[环境搭建](https://gitee.com/openharmony/docs/blob/master/quick-start/Hi3516%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83.md)。
|
- Hi3516DV300单板:参考[环境搭建](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/Hi3516%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83.md)。
|
||||||
|
|
||||||
### 获取源码<a name="section11443189655"></a>
|
### 获取源码<a name="section11443189655"></a>
|
||||||
|
|
||||||
在Linux服务器上下载并解压一套源代码,获取源码([下载链接](https://repo.huaweicloud.com/harmonyos/os/1.0/code-1.0.tar.gz))。更多源码获取方式,参考[源码获取](https://gitee.com/openharmony/docs/blob/master/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.md)。
|
在Linux服务器上下载并解压一套源代码,获取源码([下载链接](https://repo.huaweicloud.com/harmonyos/os/1.0.1/code-1.0.1.tar.gz))。更多源码获取方式,参考[源码获取](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.md)。
|
||||||
|
|
||||||
### 编译构建<a name="section2081013992812"></a>
|
### 编译构建<a name="section2081013992812"></a>
|
||||||
|
|
||||||
开发者开发第一个应用程序可参考:
|
开发者开发第一个应用程序可参考:
|
||||||
|
|
||||||
- [helloworld for Hi3518EV300](https://gitee.com/openharmony/docs/blob/master/quick-start/%E5%BC%80%E5%8F%91Hi3518%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%A4%BA%E4%BE%8B%E7%A8%8B%E5%BA%8F.md);
|
- [helloworld for Hi3518EV300](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/%E5%BC%80%E5%8F%91Hi3518%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%A4%BA%E4%BE%8B%E7%A8%8B%E5%BA%8F.md);
|
||||||
|
|
||||||
- [helloworld for Hi3516DV300](https://gitee.com/openharmony/docs/blob/master/quick-start/%E5%BC%80%E5%8F%91Hi3516%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%A4%BA%E4%BE%8B.md)。
|
- [helloworld for Hi3516DV300](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/%E5%BC%80%E5%8F%91Hi3516%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%A4%BA%E4%BE%8B.md)。
|
||||||
|
|
||||||
## 相关仓<a name="section1371113476307"></a>
|
## 相关仓<a name="section1371113476307"></a>
|
||||||
|
|
||||||
[drivers\_liteos](https://gitee.com/openharmony/drivers_liteos)
|
[内核子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%86%85%E6%A0%B8%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
|
||||||
|
|
||||||
**[kernel\_liteos\_a](https://gitee.com/openharmony/kernel_liteos_a)**
|
[drivers\_liteos](https://gitee.com/openharmony/drivers_liteos/blob/master/README_zh.md)
|
||||||
|
|
||||||
|
**kernel\_liteos\_a**
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ LIBSOUT := $(OBJOUT)/libs
|
||||||
IMGOUT := $(OUT)
|
IMGOUT := $(OUT)
|
||||||
|
|
||||||
# common flags config
|
# common flags config
|
||||||
BASE_OPTS := -ffunction-sections -fdata-sections -fno-omit-frame-pointer -D_GNU_SOURCE \
|
BASE_OPTS := -ffunction-sections -fdata-sections -fno-omit-frame-pointer -fno-common -fno-strict-aliasing -D_GNU_SOURCE \
|
||||||
$(LITEOS_SSP) $(LITEOS_CORE_COPTS) $(WARNING_AS_ERROR) $(LLVM_EXTRA_OPTS) $(LITEOS_GCOV_OPTS)
|
$(LITEOS_SSP) $(LITEOS_CORE_COPTS) $(WARNING_AS_ERROR) $(LLVM_EXTRA_OPTS) $(LITEOS_GCOV_OPTS)
|
||||||
|
|
||||||
CFLAGS := -std=c99 -fno-exceptions $(BASE_OPTS) $(LITEOS_COPTS_OPTMIZE)
|
CFLAGS := -std=c99 -fno-exceptions $(BASE_OPTS) $(LITEOS_COPTS_OPTMIZE)
|
||||||
|
|
|
@ -669,12 +669,21 @@ VOID BackTraceSub(UINTPTR regFP)
|
||||||
|
|
||||||
while (IsValidFP(backFP, stackStart, stackEnd, &kvaddr) == TRUE) {
|
while (IsValidFP(backFP, stackStart, stackEnd, &kvaddr) == TRUE) {
|
||||||
tmpFP = backFP;
|
tmpFP = backFP;
|
||||||
|
#ifdef LOSCFG_COMPILER_CLANG_LLVM
|
||||||
|
backFP = *(UINTPTR *)(UINTPTR)kvaddr;
|
||||||
|
if (IsValidFP(tmpFP + POINTER_SIZE, stackStart, stackEnd, &kvaddr) == FALSE) {
|
||||||
|
PrintExcInfo("traceback backLR check failed, backLP: 0x%x\n", tmpFP + POINTER_SIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
backLR = *(UINTPTR *)(UINTPTR)kvaddr;
|
||||||
|
#else
|
||||||
backLR = *(UINTPTR *)(UINTPTR)kvaddr;
|
backLR = *(UINTPTR *)(UINTPTR)kvaddr;
|
||||||
if (IsValidFP(tmpFP - POINTER_SIZE, stackStart, stackEnd, &kvaddr) == FALSE) {
|
if (IsValidFP(tmpFP - POINTER_SIZE, stackStart, stackEnd, &kvaddr) == FALSE) {
|
||||||
PrintExcInfo("traceback backFP check failed, backFP: 0x%x\n", tmpFP - POINTER_SIZE);
|
PrintExcInfo("traceback backFP check failed, backFP: 0x%x\n", tmpFP - POINTER_SIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backFP = *(UINTPTR *)(UINTPTR)kvaddr;
|
backFP = *(UINTPTR *)(UINTPTR)kvaddr;
|
||||||
|
#endif
|
||||||
if (LOS_IsUserAddress((VADDR_T)backLR) == TRUE) {
|
if (LOS_IsUserAddress((VADDR_T)backLR) == TRUE) {
|
||||||
region = LOS_RegionFind(OsCurrProcessGet()->vmSpace, (VADDR_T)backLR);
|
region = LOS_RegionFind(OsCurrProcessGet()->vmSpace, (VADDR_T)backLR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,9 @@
|
||||||
|
|
||||||
.equ MPIDR_CPUID_MASK, 0xffU
|
.equ MPIDR_CPUID_MASK, 0xffU
|
||||||
|
|
||||||
.fpu vfpv4
|
.fpu neon-vfpv4
|
||||||
|
.syntax unified
|
||||||
|
.arch armv7-a
|
||||||
.arm
|
.arm
|
||||||
|
|
||||||
/* param0 is stack bottom, param1 is stack size, r12 hold cpu id */
|
/* param0 is stack bottom, param1 is stack size, r12 hold cpu id */
|
||||||
|
@ -187,7 +189,7 @@ reloc_img_to_bottom_done:
|
||||||
mov r0, r4
|
mov r0, r4
|
||||||
mov r1, #0
|
mov r1, #0
|
||||||
mov r2, #MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS
|
mov r2, #MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS
|
||||||
bl memset
|
bl memset_optimized /* optimized memset since r0 is 64-byte aligned */
|
||||||
|
|
||||||
PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
|
PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
|
||||||
PAGE_TABLE_SET SYS_MEM_BASE, UNCACHED_VMM_BASE, UNCACHED_VMM_SIZE, MMU_INITIAL_MAP_NORMAL_NOCACHE
|
PAGE_TABLE_SET SYS_MEM_BASE, UNCACHED_VMM_BASE, UNCACHED_VMM_SIZE, MMU_INITIAL_MAP_NORMAL_NOCACHE
|
||||||
|
@ -463,6 +465,18 @@ _bootaddr_setup:
|
||||||
|
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
|
memset_optimized:
|
||||||
|
mov r3, r0
|
||||||
|
vdup.8 q0, r1
|
||||||
|
vmov q1, q0
|
||||||
|
vmov q2, q0
|
||||||
|
vmov q3, q0
|
||||||
|
memset_optimized_loop:
|
||||||
|
subs r2, #64
|
||||||
|
vstmia r3!, {d0 - d7}
|
||||||
|
bge memset_optimized_loop
|
||||||
|
bx lr
|
||||||
|
|
||||||
init_done:
|
init_done:
|
||||||
.long 0xDEADB00B
|
.long 0xDEADB00B
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,9 @@
|
||||||
|
|
||||||
.equ MPIDR_CPUID_MASK, 0xffU
|
.equ MPIDR_CPUID_MASK, 0xffU
|
||||||
|
|
||||||
.fpu vfpv4
|
.fpu neon-vfpv4
|
||||||
|
.syntax unified
|
||||||
|
.arch armv7-a
|
||||||
.arm
|
.arm
|
||||||
|
|
||||||
/* param0 is stack bottom, param1 is stack size, r11 hold cpu id */
|
/* param0 is stack bottom, param1 is stack size, r11 hold cpu id */
|
||||||
|
@ -164,7 +166,7 @@ reloc_img_to_bottom_done:
|
||||||
mov r0, r4
|
mov r0, r4
|
||||||
mov r1, #0
|
mov r1, #0
|
||||||
mov r2, #MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS
|
mov r2, #MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS
|
||||||
bl memset
|
bl memset_optimized /* optimized memset since r0 is 64-byte aligned */
|
||||||
|
|
||||||
|
|
||||||
PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
|
PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
|
||||||
|
@ -431,6 +433,18 @@ _bootaddr_setup:
|
||||||
|
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
|
memset_optimized:
|
||||||
|
mov r3, r0
|
||||||
|
vdup.8 q0, r1
|
||||||
|
vmov q1, q0
|
||||||
|
vmov q2, q0
|
||||||
|
vmov q3, q0
|
||||||
|
memset_optimized_loop:
|
||||||
|
subs r2, #64
|
||||||
|
vstmia r3!, {d0 - d7}
|
||||||
|
bge memset_optimized_loop
|
||||||
|
bx lr
|
||||||
|
|
||||||
init_done:
|
init_done:
|
||||||
.long 0xDEADB00B
|
.long 0xDEADB00B
|
||||||
|
|
||||||
|
|
20
build.sh
20
build.sh
|
@ -32,24 +32,29 @@ set -e
|
||||||
|
|
||||||
echo "sh param:$1,$2,$3,$4,$5,$6,$7"
|
echo "sh param:$1,$2,$3,$4,$5,$6,$7"
|
||||||
destination=".config"
|
destination=".config"
|
||||||
|
config_file=""
|
||||||
tee=""
|
tee=""
|
||||||
outdir="../..$3/test_info/gen/kernel/test"
|
outdir="../..$3/test_info/gen/kernel/test"
|
||||||
if [ "$5" = "tee" ]; then
|
if [ "$5" = "tee" ]; then
|
||||||
tee="_tee"
|
tee="_tee"
|
||||||
fi
|
fi
|
||||||
productName="$(basename $7)"
|
product_name="$(basename $7)"
|
||||||
source="tools/build/config/${productName}_release.config"
|
source="tools/build/config/${product_name}_release.config"
|
||||||
if [ "$2" = "clang" ]; then
|
if [ "$2" = "clang" ]; then
|
||||||
if [ "$4" = "debug" ]; then
|
if [ "$4" = "debug" ]; then
|
||||||
source="tools/build/config/debug/${productName}_$2$tee.config"
|
config_file="${product_name}_$2$tee.config"
|
||||||
|
source="tools/build/config/debug/$config_file"
|
||||||
else
|
else
|
||||||
source="tools/build/config/${productName}_$2_release$tee.config"
|
config_file="${product_name}_$2_release$tee.config"
|
||||||
|
source="tools/build/config/$config_file"
|
||||||
fi
|
fi
|
||||||
elif [ "$2" = "gcc" ]; then
|
elif [ "$2" = "gcc" ]; then
|
||||||
if [ "$4" = "debug" ]; then
|
if [ "$4" = "debug" ]; then
|
||||||
source="tools/build/config/${productName}_debug_shell$tee.config"
|
config_file="${product_name}_debug_shell$tee.config"
|
||||||
|
source="tools/build/config/$config_file"
|
||||||
else
|
else
|
||||||
source="tools/build/config/${productName}_release$tee.config"
|
config_file="${product_name}_release$tee.config"
|
||||||
|
source="tools/build/config/$config_file"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ -d "./out" ]; then
|
if [ -d "./out" ]; then
|
||||||
|
@ -58,6 +63,9 @@ fi
|
||||||
if [ -f "$destination" ]; then
|
if [ -f "$destination" ]; then
|
||||||
rm -rf $destination
|
rm -rf $destination
|
||||||
fi
|
fi
|
||||||
|
if [ ! -f "$source" ]; then
|
||||||
|
source="$7/config/sys/$config_file"
|
||||||
|
fi
|
||||||
cp $source $destination
|
cp $source $destination
|
||||||
|
|
||||||
mkdir -p $outdir
|
mkdir -p $outdir
|
||||||
|
|
|
@ -586,6 +586,7 @@ typedef struct {
|
||||||
|
|
||||||
static VOID SwtmrProc(UINTPTR tmrArg)
|
static VOID SwtmrProc(UINTPTR tmrArg)
|
||||||
{
|
{
|
||||||
|
unsigned int intSave;
|
||||||
int sig;
|
int sig;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
|
@ -610,7 +611,10 @@ static VOID SwtmrProc(UINTPTR tmrArg)
|
||||||
info.si_value.sival_ptr = arg->sigev_value.sival_ptr;
|
info.si_value.sival_ptr = arg->sigev_value.sival_ptr;
|
||||||
|
|
||||||
/* Send the signal */
|
/* Send the signal */
|
||||||
|
SCHEDULER_LOCK(intSave);
|
||||||
OsDispatch(pid, &info, OS_USER_KILL_PERMISSION);
|
OsDispatch(pid, &info, OS_USER_KILL_PERMISSION);
|
||||||
|
SCHEDULER_UNLOCK(intSave);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,8 +887,10 @@ clock_t times(struct tms *buf)
|
||||||
|
|
||||||
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
|
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
|
||||||
{
|
{
|
||||||
|
UINT32 intSave;
|
||||||
LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
|
LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
|
||||||
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
|
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
|
||||||
|
timer_t timerID = 0;
|
||||||
struct itimerspec spec;
|
struct itimerspec spec;
|
||||||
struct itimerspec ospec;
|
struct itimerspec ospec;
|
||||||
int ret = LOS_OK;
|
int ret = LOS_OK;
|
||||||
|
@ -894,15 +900,27 @@ int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue
|
||||||
set_errno(EINVAL);
|
set_errno(EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
LOS_TaskLock();
|
|
||||||
if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
|
if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
|
||||||
ret = timer_create(CLOCK_REALTIME, NULL, &processCB->timerID);
|
ret = timer_create(CLOCK_REALTIME, NULL, &timerID);
|
||||||
if (ret != LOS_OK) {
|
if (ret != LOS_OK) {
|
||||||
LOS_TaskUnlock();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOS_TaskUnlock();
|
|
||||||
|
/* The initialization of this global timer must be in spinlock
|
||||||
|
* timer_create cannot be located in spinlock.
|
||||||
|
*/
|
||||||
|
SCHEDULER_LOCK(intSave);
|
||||||
|
if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
|
||||||
|
processCB->timerID = timerID;
|
||||||
|
SCHEDULER_UNLOCK(intSave);
|
||||||
|
} else {
|
||||||
|
SCHEDULER_UNLOCK(intSave);
|
||||||
|
if (timerID) {
|
||||||
|
timer_delete(timerID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ValidTimeval(&value->it_value) || !ValidTimeval(&value->it_interval)) {
|
if (!ValidTimeval(&value->it_value) || !ValidTimeval(&value->it_interval)) {
|
||||||
set_errno(EINVAL);
|
set_errno(EINVAL);
|
||||||
|
|
|
@ -700,6 +700,8 @@ INT32 los_alloc_diskid_byname(const CHAR *diskName);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
INT32 los_get_diskid_byname(const CHAR *diskName);
|
INT32 los_get_diskid_byname(const CHAR *diskName);
|
||||||
|
INT32 DiskEventRead(void);
|
||||||
|
INT32 DiskEventInit(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
|
|
@ -58,6 +58,10 @@ spinlock_t g_diskFatBlockSpinlock;
|
||||||
|
|
||||||
UINT32 g_usbMode = 0;
|
UINT32 g_usbMode = 0;
|
||||||
|
|
||||||
|
#ifdef LOSCFG_STORAGE_EMMC
|
||||||
|
static struct tagEvent g_diskInitEvent;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MEM_ADDR_ALIGN_BYTE 64
|
#define MEM_ADDR_ALIGN_BYTE 64
|
||||||
#define RWE_RW_RW 0755
|
#define RWE_RW_RW 0755
|
||||||
|
|
||||||
|
@ -1275,20 +1279,20 @@ static INT32 DiskDeinit(los_disk *disk)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
disk->dev = NULL;
|
disk->dev = NULL;
|
||||||
DISK_UNLOCK(&disk->disk_mutex);
|
|
||||||
(VOID)unregister_blockdriver(disk->disk_name);
|
(VOID)unregister_blockdriver(disk->disk_name);
|
||||||
if (disk->disk_name != NULL) {
|
if (disk->disk_name != NULL) {
|
||||||
LOS_MemFree(m_aucSysMem0, disk->disk_name);
|
LOS_MemFree(m_aucSysMem0, disk->disk_name);
|
||||||
disk->disk_name = NULL;
|
disk->disk_name = NULL;
|
||||||
}
|
}
|
||||||
|
DISK_UNLOCK(&disk->disk_mutex);
|
||||||
|
disk->disk_status = STAT_UNUSED;
|
||||||
ret = pthread_mutex_destroy(&disk->disk_mutex);
|
ret = pthread_mutex_destroy(&disk->disk_mutex);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
PRINT_ERR("%s %d, mutex destroy failed, ret = %d\n", __FUNCTION__, __LINE__, ret);
|
PRINT_ERR("%s %d, mutex destroy failed, ret = %d\n", __FUNCTION__, __LINE__, ret);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
disk->disk_status = STAT_UNUSED;
|
|
||||||
|
|
||||||
return ENOERR;
|
return ENOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1360,6 +1364,16 @@ INT32 los_disk_init(const CHAR *diskName, const struct block_operations *bops,
|
||||||
} else {
|
} else {
|
||||||
disk->type = OTHERS;
|
disk->type = OTHERS;
|
||||||
}
|
}
|
||||||
|
#ifdef LOSCFG_STORAGE_EMMC
|
||||||
|
ret = LOS_EventWrite(&g_diskInitEvent, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
PRINT_ERR("Disk initialization event write fail \n");
|
||||||
|
(void)unregister_blockdriver(diskName);
|
||||||
|
disk->disk_status = STAT_UNUSED;
|
||||||
|
return VFS_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return ENOERR;
|
return ENOERR;
|
||||||
|
|
||||||
DISK_BLKDRIVER_ERROR:
|
DISK_BLKDRIVER_ERROR:
|
||||||
|
@ -1370,6 +1384,24 @@ DISK_FIND_ERROR:
|
||||||
return VFS_ERROR;
|
return VFS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INT32 DiskEventInit(void)
|
||||||
|
{
|
||||||
|
#ifdef LOSCFG_STORAGE_EMMC
|
||||||
|
return LOS_EventInit(&g_diskInitEvent);
|
||||||
|
#else
|
||||||
|
return LOS_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
INT32 DiskEventRead(void)
|
||||||
|
{
|
||||||
|
#ifdef LOSCFG_STORAGE_EMMC
|
||||||
|
return LOS_EventRead(&g_diskInitEvent, 1, LOS_WAITMODE_OR, LOS_WAIT_FOREVER);
|
||||||
|
#else
|
||||||
|
return LOS_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
INT32 los_disk_deinit(INT32 diskID)
|
INT32 los_disk_deinit(INT32 diskID)
|
||||||
{
|
{
|
||||||
los_disk *disk = get_disk(diskID);
|
los_disk *disk = get_disk(diskID);
|
||||||
|
|
|
@ -526,16 +526,74 @@ static void PrintFileInfo(const struct stat *statInfo, const char *name)
|
||||||
str[0], str[1], str[UGO_NUMS - 1], statInfo->st_size, statInfo->st_uid, statInfo->st_gid, name);
|
str[0], str[1], str[UGO_NUMS - 1], statInfo->st_size, statInfo->st_uid, statInfo->st_gid, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ls(const char *pathname)
|
int LsFile(const char *path)
|
||||||
{
|
{
|
||||||
struct stat64 stat64_info;
|
struct stat64 stat64Info;
|
||||||
struct stat stat_info;
|
struct stat statInfo;
|
||||||
struct dirent *pdirent = NULL;
|
|
||||||
char *path = NULL;
|
if (stat64(path, &stat64Info) == 0) {
|
||||||
|
PrintFileInfo64(&stat64Info, path);
|
||||||
|
} else if (stat(path, &statInfo) == 0) {
|
||||||
|
PrintFileInfo(&statInfo, path);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LsDir(const char *path)
|
||||||
|
{
|
||||||
|
struct stat statInfo = { 0 };
|
||||||
|
struct stat64 stat64Info = { 0 };
|
||||||
|
DIR *d = NULL;
|
||||||
char *fullpath = NULL;
|
char *fullpath = NULL;
|
||||||
char *fullpath_bak = NULL;
|
char *fullpath_bak = NULL;
|
||||||
|
struct dirent *pdirent = NULL;
|
||||||
|
|
||||||
|
d = opendir(path);
|
||||||
|
if (d == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINTK("Directory %s:\n", path);
|
||||||
|
do {
|
||||||
|
pdirent = readdir(d);
|
||||||
|
if (pdirent == NULL) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (!strcmp(pdirent->d_name, ".") || !strcmp(pdirent->d_name, "..")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void)memset_s(&statInfo, sizeof(struct stat), 0, sizeof(struct stat));
|
||||||
|
(void)memset_s(&stat64Info, sizeof(struct stat), 0, sizeof(struct stat));
|
||||||
|
fullpath = ls_get_fullpath(path, pdirent);
|
||||||
|
if (fullpath == NULL) {
|
||||||
|
(void)closedir(d);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fullpath_bak = fullpath;
|
||||||
|
if (stat64(fullpath, &stat64Info) == 0) {
|
||||||
|
PrintFileInfo64(&stat64Info, pdirent->d_name);
|
||||||
|
} else if (stat(fullpath, &statInfo) == 0) {
|
||||||
|
PrintFileInfo(&statInfo, pdirent->d_name);
|
||||||
|
} else {
|
||||||
|
PRINTK("BAD file: %s\n", pdirent->d_name);
|
||||||
|
}
|
||||||
|
free(fullpath_bak);
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
(void)closedir(d);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ls(const char *pathname)
|
||||||
|
{
|
||||||
|
struct stat statInfo = { 0 };
|
||||||
|
char *path = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
DIR *d = NULL;
|
|
||||||
|
|
||||||
if (pathname == NULL) {
|
if (pathname == NULL) {
|
||||||
#ifdef VFS_USING_WORKDIR
|
#ifdef VFS_USING_WORKDIR
|
||||||
|
@ -561,45 +619,23 @@ void ls(const char *pathname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* list all directory and file*/
|
ret = stat(path, &statInfo);
|
||||||
|
if (ret < 0) {
|
||||||
d = opendir(path);
|
|
||||||
if (d == NULL) {
|
|
||||||
perror("ls error");
|
perror("ls error");
|
||||||
} else {
|
free(path);
|
||||||
PRINTK("Directory %s:\n", path);
|
return;
|
||||||
do {
|
|
||||||
pdirent = readdir(d);
|
|
||||||
if (pdirent == NULL) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (!strcmp(pdirent->d_name, ".") || !strcmp(pdirent->d_name, "..")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
(void)memset_s(&stat_info, sizeof(struct stat), 0, sizeof(struct stat));
|
|
||||||
fullpath = ls_get_fullpath(path, pdirent);
|
|
||||||
if (fullpath == NULL) {
|
|
||||||
free(path);
|
|
||||||
(void)closedir(d);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullpath_bak = fullpath;
|
|
||||||
|
|
||||||
if (stat64(fullpath, &stat64_info) == 0) {
|
|
||||||
PrintFileInfo64(&stat64_info, pdirent->d_name);
|
|
||||||
} else if (stat(fullpath, &stat_info) == 0) {
|
|
||||||
PrintFileInfo(&stat_info, pdirent->d_name);
|
|
||||||
} else
|
|
||||||
PRINTK("BAD file: %s\n", pdirent->d_name);
|
|
||||||
free(fullpath_bak);
|
|
||||||
}
|
|
||||||
} while (1);
|
|
||||||
|
|
||||||
(void)closedir(d);
|
|
||||||
}
|
}
|
||||||
free(path);
|
|
||||||
|
|
||||||
|
if (statInfo.st_mode & S_IFDIR) { /* list all directory and file */
|
||||||
|
ret = LsDir((pathname == NULL) ? path : pathname);
|
||||||
|
} else { /* show the file infomation */
|
||||||
|
ret = LsFile(path);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
perror("ls error");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -838,6 +838,10 @@ static int os_shell_cmd_do_rmdir(const char *pathname)
|
||||||
return remove(pathname);
|
return remove(pathname);
|
||||||
}
|
}
|
||||||
d = opendir(pathname);
|
d = opendir(pathname);
|
||||||
|
if (d == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
dirent = readdir(d);
|
dirent = readdir(d);
|
||||||
|
|
|
@ -510,7 +510,6 @@ int OsSigSuspend(const sigset_t *set)
|
||||||
{
|
{
|
||||||
unsigned int intSave;
|
unsigned int intSave;
|
||||||
LosTaskCB *rtcb = NULL;
|
LosTaskCB *rtcb = NULL;
|
||||||
unsigned int sigTempProcMask;
|
|
||||||
sigset_t setSuspend;
|
sigset_t setSuspend;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -519,7 +518,6 @@ int OsSigSuspend(const sigset_t *set)
|
||||||
}
|
}
|
||||||
SCHEDULER_LOCK(intSave);
|
SCHEDULER_LOCK(intSave);
|
||||||
rtcb = OsCurrTaskGet();
|
rtcb = OsCurrTaskGet();
|
||||||
sigTempProcMask = rtcb->sig.sigprocmask;
|
|
||||||
|
|
||||||
/* Wait signal calc */
|
/* Wait signal calc */
|
||||||
setSuspend = FULL_SIGNAL_SET & (~(*set));
|
setSuspend = FULL_SIGNAL_SET & (~(*set));
|
||||||
|
@ -530,8 +528,6 @@ int OsSigSuspend(const sigset_t *set)
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
|
PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
|
||||||
}
|
}
|
||||||
/* Restore old sigprocmask */
|
|
||||||
OsSigMaskSwitch(rtcb, sigTempProcMask);
|
|
||||||
|
|
||||||
SCHEDULER_UNLOCK(intSave);
|
SCHEDULER_UNLOCK(intSave);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
|
|
|
@ -44,6 +44,8 @@ extern "C" {
|
||||||
|
|
||||||
#if (LOSCFG_KERNEL_SMP_LOCKDEP == YES)
|
#if (LOSCFG_KERNEL_SMP_LOCKDEP == YES)
|
||||||
|
|
||||||
|
#define PRINT_BUF_SIZE 256
|
||||||
|
|
||||||
#define LOCKDEP_GET_NAME(lockDep, index) (((SPIN_LOCK_S *)((lockDep)->heldLocks[(index)].lockPtr))->name)
|
#define LOCKDEP_GET_NAME(lockDep, index) (((SPIN_LOCK_S *)((lockDep)->heldLocks[(index)].lockPtr))->name)
|
||||||
#define LOCKDEP_GET_ADDR(lockDep, index) ((lockDep)->heldLocks[(index)].lockAddr)
|
#define LOCKDEP_GET_ADDR(lockDep, index) ((lockDep)->heldLocks[(index)].lockAddr)
|
||||||
|
|
||||||
|
@ -107,6 +109,31 @@ WEAK VOID OsLockDepPanic(enum LockDepErrType errType)
|
||||||
while (1) {}
|
while (1) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC VOID OsLockDepPrint(const CHAR *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
UINT32 len;
|
||||||
|
CHAR buf[PRINT_BUF_SIZE] = {0};
|
||||||
|
|
||||||
|
len = vsnprintf_s(buf, PRINT_BUF_SIZE, PRINT_BUF_SIZE - 1, fmt, ap);
|
||||||
|
if ((len == -1) && (*buf == '\0')) {
|
||||||
|
/* parameter is illegal or some features in fmt dont support */
|
||||||
|
UartPuts("OsLockDepPrint is error\n", strlen("OsLockDepPrint is error\n") + 1, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(buf + len) = '\0';
|
||||||
|
|
||||||
|
UartPuts(buf, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC VOID OsPrintLockDepInfo(const CHAR *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
OsLockDepPrint(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
STATIC VOID OsLockDepDumpLock(const LosTaskCB *task, const SPIN_LOCK_S *lock,
|
STATIC VOID OsLockDepDumpLock(const LosTaskCB *task, const SPIN_LOCK_S *lock,
|
||||||
const VOID *requestAddr, enum LockDepErrType errType)
|
const VOID *requestAddr, enum LockDepErrType errType)
|
||||||
{
|
{
|
||||||
|
@ -114,24 +141,24 @@ STATIC VOID OsLockDepDumpLock(const LosTaskCB *task, const SPIN_LOCK_S *lock,
|
||||||
const LockDep *lockDep = &task->lockDep;
|
const LockDep *lockDep = &task->lockDep;
|
||||||
const LosTaskCB *temp = task;
|
const LosTaskCB *temp = task;
|
||||||
|
|
||||||
PrintExcInfo("lockdep check failed\n");
|
OsPrintLockDepInfo("lockdep check failed\n");
|
||||||
PrintExcInfo("error type : %s\n", OsLockDepErrorStringGet(errType));
|
OsPrintLockDepInfo("error type : %s\n", OsLockDepErrorStringGet(errType));
|
||||||
PrintExcInfo("request addr : 0x%x\n", requestAddr);
|
OsPrintLockDepInfo("request addr : 0x%x\n", requestAddr);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
PrintExcInfo("task name : %s\n", temp->taskName);
|
OsPrintLockDepInfo("task name : %s\n", temp->taskName);
|
||||||
PrintExcInfo("task id : %u\n", temp->taskID);
|
OsPrintLockDepInfo("task id : %u\n", temp->taskID);
|
||||||
PrintExcInfo("cpu num : %u\n", temp->currCpu);
|
OsPrintLockDepInfo("cpu num : %u\n", temp->currCpu);
|
||||||
PrintExcInfo("start dumping lockdep infomation\n");
|
OsPrintLockDepInfo("start dumping lockdep infomation\n");
|
||||||
for (i = 0; i < lockDep->lockDepth; i++) {
|
for (i = 0; i < lockDep->lockDepth; i++) {
|
||||||
if (lockDep->heldLocks[i].lockPtr == lock) {
|
if (lockDep->heldLocks[i].lockPtr == lock) {
|
||||||
PrintExcInfo("[%d] %s <-- addr:0x%x\n", i, LOCKDEP_GET_NAME(lockDep, i),
|
OsPrintLockDepInfo("[%d] %s <-- addr:0x%x\n", i, LOCKDEP_GET_NAME(lockDep, i),
|
||||||
LOCKDEP_GET_ADDR(lockDep, i));
|
LOCKDEP_GET_ADDR(lockDep, i));
|
||||||
} else {
|
} else {
|
||||||
PrintExcInfo("[%d] %s \n", i, LOCKDEP_GET_NAME(lockDep, i));
|
OsPrintLockDepInfo("[%d] %s \n", i, LOCKDEP_GET_NAME(lockDep, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintExcInfo("[%d] %s <-- now\n", i, lock->name);
|
OsPrintLockDepInfo("[%d] %s <-- now\n", i, lock->name);
|
||||||
|
|
||||||
if (errType == LOCKDEP_ERR_DEAD_LOCK) {
|
if (errType == LOCKDEP_ERR_DEAD_LOCK) {
|
||||||
temp = lock->owner;
|
temp = lock->owner;
|
||||||
|
@ -144,7 +171,6 @@ STATIC VOID OsLockDepDumpLock(const LosTaskCB *task, const SPIN_LOCK_S *lock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OsLockDepPanic(errType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC BOOL OsLockDepCheckDependancy(const LosTaskCB *current, LosTaskCB *lockOwner)
|
STATIC BOOL OsLockDepCheckDependancy(const LosTaskCB *current, LosTaskCB *lockOwner)
|
||||||
|
@ -172,7 +198,7 @@ VOID OsLockDepCheckIn(SPIN_LOCK_S *lock)
|
||||||
{
|
{
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
enum LockDepErrType checkResult = LOCKDEP_SUCEESS;
|
enum LockDepErrType checkResult = LOCKDEP_SUCEESS;
|
||||||
VOID *requestAddr = (VOID *)__builtin_return_address(0);
|
VOID *requestAddr = (VOID *)__builtin_return_address(1);
|
||||||
LosTaskCB *current = OsCurrTaskGet();
|
LosTaskCB *current = OsCurrTaskGet();
|
||||||
LockDep *lockDep = ¤t->lockDep;
|
LockDep *lockDep = ¤t->lockDep;
|
||||||
LosTaskCB *lockOwner = NULL;
|
LosTaskCB *lockOwner = NULL;
|
||||||
|
@ -211,11 +237,12 @@ OUT:
|
||||||
lockDep->waitLock = lock;
|
lockDep->waitLock = lock;
|
||||||
lockDep->heldLocks[lockDep->lockDepth].lockAddr = requestAddr;
|
lockDep->heldLocks[lockDep->lockDepth].lockAddr = requestAddr;
|
||||||
lockDep->heldLocks[lockDep->lockDepth].waitTime = OsLockDepGetCycles(); /* start time */
|
lockDep->heldLocks[lockDep->lockDepth].waitTime = OsLockDepGetCycles(); /* start time */
|
||||||
} else {
|
OsLockDepRelease(intSave);
|
||||||
OsLockDepDumpLock(current, lock, requestAddr, checkResult);
|
return;
|
||||||
}
|
}
|
||||||
|
OsLockDepDumpLock(current, lock, requestAddr, checkResult);
|
||||||
OsLockDepRelease(intSave);
|
OsLockDepRelease(intSave);
|
||||||
|
OsLockDepPanic(checkResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID OsLockDepRecord(SPIN_LOCK_S *lock)
|
VOID OsLockDepRecord(SPIN_LOCK_S *lock)
|
||||||
|
@ -253,7 +280,7 @@ VOID OsLockDepCheckOut(SPIN_LOCK_S *lock)
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
INT32 depth;
|
INT32 depth;
|
||||||
enum LockDepErrType checkResult = LOCKDEP_SUCEESS;
|
enum LockDepErrType checkResult = LOCKDEP_SUCEESS;
|
||||||
VOID *requestAddr = (VOID *)__builtin_return_address(0);
|
VOID *requestAddr = (VOID *)__builtin_return_address(1);
|
||||||
LosTaskCB *current = OsCurrTaskGet();
|
LosTaskCB *current = OsCurrTaskGet();
|
||||||
LosTaskCB *owner = NULL;
|
LosTaskCB *owner = NULL;
|
||||||
LockDep *lockDep = NULL;
|
LockDep *lockDep = NULL;
|
||||||
|
@ -265,7 +292,8 @@ VOID OsLockDepCheckOut(SPIN_LOCK_S *lock)
|
||||||
if (owner == SPINLOCK_OWNER_INIT) {
|
if (owner == SPINLOCK_OWNER_INIT) {
|
||||||
checkResult = LOCKDEP_ERR_UNLOCK_WITOUT_LOCK;
|
checkResult = LOCKDEP_ERR_UNLOCK_WITOUT_LOCK;
|
||||||
OsLockDepDumpLock(current, lock, requestAddr, checkResult);
|
OsLockDepDumpLock(current, lock, requestAddr, checkResult);
|
||||||
goto OUT;
|
OsLockDepRelease(intSave);
|
||||||
|
OsLockDepPanic(checkResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
lockDep = &owner->lockDep;
|
lockDep = &owner->lockDep;
|
||||||
|
@ -294,7 +322,6 @@ VOID OsLockDepCheckOut(SPIN_LOCK_S *lock)
|
||||||
lock->cpuid = (UINT32)(-1);
|
lock->cpuid = (UINT32)(-1);
|
||||||
lock->owner = SPINLOCK_OWNER_INIT;
|
lock->owner = SPINLOCK_OWNER_INIT;
|
||||||
|
|
||||||
OUT:
|
|
||||||
OsLockDepRelease(intSave);
|
OsLockDepRelease(intSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ extern "C" {
|
||||||
#define OS_SCHED_TIME_SLICES_MAX ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE)
|
#define OS_SCHED_TIME_SLICES_MAX ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE)
|
||||||
#define OS_SCHED_TIME_SLICES_DIFF (OS_SCHED_TIME_SLICES_MAX - OS_SCHED_TIME_SLICES_MIN)
|
#define OS_SCHED_TIME_SLICES_DIFF (OS_SCHED_TIME_SLICES_MAX - OS_SCHED_TIME_SLICES_MIN)
|
||||||
#define OS_SCHED_READY_MAX 30
|
#define OS_SCHED_READY_MAX 30
|
||||||
#define OS_TIME_SLICE_MIN ((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */
|
#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */
|
||||||
#define OS_SCHED_MAX_RESPONSE_TIME (UINT64)(OS_64BIT_MAX - 1U)
|
#define OS_SCHED_MAX_RESPONSE_TIME (UINT64)(OS_64BIT_MAX - 1U)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -98,7 +98,7 @@ STATIC VOID ConsoleOutput(const CHAR *str, UINT32 len)
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cnt = write(STDOUT_FILENO, str + writen, (size_t)toWrite);
|
cnt = write(STDOUT_FILENO, str + writen, (size_t)toWrite);
|
||||||
if ((cnt < 0) || (toWrite == cnt)) {
|
if ((cnt < 0) || ((cnt == 0) && OS_INT_ACTIVE) || (toWrite == cnt)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
writen += cnt;
|
writen += cnt;
|
||||||
|
|
|
@ -246,6 +246,7 @@ STATIC INT32 GetArgs(CHAR **args)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOSCFG_STORAGE_EMMC
|
#ifdef LOSCFG_STORAGE_EMMC
|
||||||
|
(void)DiskEventRead();
|
||||||
g_emmcDisk = GetMmcDisk(EMMC);
|
g_emmcDisk = GetMmcDisk(EMMC);
|
||||||
if (g_emmcDisk == NULL) {
|
if (g_emmcDisk == NULL) {
|
||||||
PRINT_ERR("Get EMMC disk failed!\n");
|
PRINT_ERR("Get EMMC disk failed!\n");
|
||||||
|
|
|
@ -37,7 +37,8 @@ VDSO_INCLUDE := -I $(LITEOSTOPDIR)/kernel/extended/vdso/include \
|
||||||
-I $(LITEOSTOPDIR)/kernel/common \
|
-I $(LITEOSTOPDIR)/kernel/common \
|
||||||
-I $(LITEOSTOPDIR)/bsd/compat/linuxkpi/include
|
-I $(LITEOSTOPDIR)/bsd/compat/linuxkpi/include
|
||||||
|
|
||||||
VDSO_CCFLAGS := -nostdlib -fPIC $(LITEOS_SSP) $(LITEOS_CORE_COPTS) $(WARNING_AS_ERROR) $(LITEOS_COPTS_OPTMIZE)
|
VDSO_CCFLAGS := -nostdlib -fPIC -fno-common -fno-strict-aliasing \
|
||||||
|
$(LITEOS_SSP) $(LITEOS_CORE_COPTS) $(WARNING_AS_ERROR) $(LITEOS_COPTS_OPTMIZE)
|
||||||
ifeq ($(LOSCFG_COMPILER_CLANG_LLVM), y)
|
ifeq ($(LOSCFG_COMPILER_CLANG_LLVM), y)
|
||||||
VDSO_CCFLAGS += $(LLVM_EXTRA_OPTS) --sysroot=$(LITEOSTOPDIR)/../../prebuilts/lite/sysroot/
|
VDSO_CCFLAGS += $(LLVM_EXTRA_OPTS) --sysroot=$(LITEOSTOPDIR)/../../prebuilts/lite/sysroot/
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1468,6 +1468,51 @@ static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call)
|
||||||
|
|
||||||
#include "los_vm_map.h"
|
#include "los_vm_map.h"
|
||||||
#include "user_copy.h"
|
#include "user_copy.h"
|
||||||
|
static int do_ioctl_SIOCGIFCONF(int sockfd, long cmd, void *argp)
|
||||||
|
{
|
||||||
|
int nbytes;
|
||||||
|
struct ifconf ifc;
|
||||||
|
char *buf_bak = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (LOS_ArchCopyFromUser(&ifc, argp, sizeof(struct ifconf)) != 0) {
|
||||||
|
set_errno(EFAULT);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nbytes = ifc.ifc_len;
|
||||||
|
if (nbytes < 0) {
|
||||||
|
set_errno(EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
buf_bak = ifc.ifc_buf;
|
||||||
|
if (!LOS_IsUserAddress((VADDR_T)(uintptr_t)buf_bak)) {
|
||||||
|
set_errno(EFAULT);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ifc.ifc_buf = malloc(nbytes);
|
||||||
|
if (ifc.ifc_buf == NULL) {
|
||||||
|
set_errno(ENOMEM);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
(void)memset_s(ifc.ifc_buf, nbytes, 0, nbytes);
|
||||||
|
|
||||||
|
ret = lwip_ioctl(sockfd, cmd, &ifc);
|
||||||
|
if (ret == 0) {
|
||||||
|
if (LOS_ArchCopyToUser(buf_bak, ifc.ifc_buf, nbytes) != 0) {
|
||||||
|
set_errno(EFAULT);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ifc.ifc_buf);
|
||||||
|
ifc.ifc_buf = buf_bak;
|
||||||
|
if (LOS_ArchCopyToUser(argp, &ifc, sizeof(struct ifconf)) != 0) {
|
||||||
|
set_errno(EFAULT);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int socks_ioctl(int sockfd, long cmd, void *argp)
|
int socks_ioctl(int sockfd, long cmd, void *argp)
|
||||||
{
|
{
|
||||||
void *argpbak = argp;
|
void *argpbak = argp;
|
||||||
|
@ -1483,11 +1528,12 @@ int socks_ioctl(int sockfd, long cmd, void *argp)
|
||||||
case SIOCADDRT:
|
case SIOCADDRT:
|
||||||
nbytes = sizeof(struct rtentry);
|
nbytes = sizeof(struct rtentry);
|
||||||
break;
|
break;
|
||||||
|
case SIOCGIFCONF:
|
||||||
|
return do_ioctl_SIOCGIFCONF(sockfd, cmd, argp);
|
||||||
case SIOCSIPV6DAD:
|
case SIOCSIPV6DAD:
|
||||||
case SIOCGIPV6DAD:
|
case SIOCGIPV6DAD:
|
||||||
case SIOCSIPV6DPCTD:
|
case SIOCSIPV6DPCTD:
|
||||||
case SIOCGIPV6DPCTD:
|
case SIOCGIPV6DPCTD:
|
||||||
case SIOCGIFCONF:
|
|
||||||
case SIOCGIFADDR:
|
case SIOCGIFADDR:
|
||||||
case SIOCSIFADDR:
|
case SIOCSIFADDR:
|
||||||
case SIOCDIFADDR:
|
case SIOCDIFADDR:
|
||||||
|
|
|
@ -5,7 +5,7 @@ config PLATFORM
|
||||||
default "virt" if PLATFORM_QEMU_ARM_VIRT_CA7
|
default "virt" if PLATFORM_QEMU_ARM_VIRT_CA7
|
||||||
|
|
||||||
config PRODUCT_NAME
|
config PRODUCT_NAME
|
||||||
string
|
string "unknown"
|
||||||
default "ipcamera_hi3516dv300_liteos" if PRODUCT_IPCAMERA_HI3516DV300_LITEOS
|
default "ipcamera_hi3516dv300_liteos" if PRODUCT_IPCAMERA_HI3516DV300_LITEOS
|
||||||
default "ipcamera_hi3518ev300_liteos" if PRODUCT_IPCAMERA_HI3518EV300_LITEOS
|
default "ipcamera_hi3518ev300_liteos" if PRODUCT_IPCAMERA_HI3518EV300_LITEOS
|
||||||
default "hispark_taurus" if PRODUCT_HISPARK_TAURUS
|
default "hispark_taurus" if PRODUCT_HISPARK_TAURUS
|
||||||
|
@ -13,7 +13,7 @@ config PRODUCT_NAME
|
||||||
default "arm_virt" if PRODUCT_QEMU_ARM
|
default "arm_virt" if PRODUCT_QEMU_ARM
|
||||||
|
|
||||||
config DEVICE_COMPANY
|
config DEVICE_COMPANY
|
||||||
string
|
string "unknown"
|
||||||
default "hisilicon" if PLATFORM_HI3516DV300
|
default "hisilicon" if PLATFORM_HI3516DV300
|
||||||
default "hisilicon" if PLATFORM_HI3518EV300
|
default "hisilicon" if PLATFORM_HI3518EV300
|
||||||
default "qemu" if PLATFORM_QEMU_ARM_VIRT_CA7
|
default "qemu" if PLATFORM_QEMU_ARM_VIRT_CA7
|
||||||
|
|
|
@ -157,6 +157,12 @@ INT32 OsShellDeinit(INT32 consoleId)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(LOSCFG_PLATFORM_ROOTFS)
|
||||||
|
if (consoleId == CONSOLE_SERIAL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
(VOID)LOS_TaskDelete(shellCB->shellEntryHandle);
|
(VOID)LOS_TaskDelete(shellCB->shellEntryHandle);
|
||||||
(VOID)LOS_EventWrite(&shellCB->shellEvent, CONSOLE_SHELL_KEY_EVENT);
|
(VOID)LOS_EventWrite(&shellCB->shellEvent, CONSOLE_SHELL_KEY_EVENT);
|
||||||
|
|
||||||
|
|
|
@ -355,13 +355,18 @@ int SysNanoSleep(const struct timespec *rqtp, struct timespec *rmtp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct timespec srqtp;
|
struct timespec srqtp;
|
||||||
struct timespec srmtp = { 0 };
|
struct timespec srmtp;
|
||||||
|
|
||||||
if (!rqtp || LOS_ArchCopyFromUser(&srqtp, rqtp, sizeof(struct timespec))) {
|
if (!rqtp || LOS_ArchCopyFromUser(&srqtp, rqtp, sizeof(struct timespec))) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rmtp && LOS_ArchCopyFromUser(&srmtp, rmtp, sizeof(struct timespec))) {
|
||||||
|
errno = EFAULT;
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
ret = nanosleep(&srqtp, rmtp ? &srmtp : NULL);
|
ret = nanosleep(&srqtp, rmtp ? &srmtp : NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -get_errno();
|
return -get_errno();
|
||||||
|
|
|
@ -359,13 +359,13 @@ ifeq ($(LOSCFG_NET_LWIP_SACK_2_1), y)
|
||||||
|
|
||||||
LITEOS_CMACRO += $(LWIP_MACROS)
|
LITEOS_CMACRO += $(LWIP_MACROS)
|
||||||
else ifeq ($(LOSCFG_NET_LWIP_SACK_2_0), y)
|
else ifeq ($(LOSCFG_NET_LWIP_SACK_2_0), y)
|
||||||
LWIPDIR := $(LITEOSTHIRDPARTY)/lwip_enhanced
|
LWIPDIR := $(LITEOSTHIRDPARTY)/lwip_enhanced/src
|
||||||
LITEOS_BASELIB += -llwip
|
LITEOS_BASELIB += -llwip
|
||||||
LIB_SUBDIRS += $(LWIPDIR)
|
LIB_SUBDIRS += $(LWIPDIR)
|
||||||
LITEOS_LWIP_SACK_INCLUDE += \
|
LITEOS_LWIP_SACK_INCLUDE += \
|
||||||
-I $(LWIPDIR)/include \
|
-I $(LWIPDIR)/include \
|
||||||
-I $(LITEOSTOPDIR)/net/mac
|
-I $(LITEOSTOPDIR)/net/mac
|
||||||
LWIP_MACROS += -DLWIP_CONFIG_FILE=\"lwip/lwipopts.h\"
|
LWIP_MACROS += -DLWIP_CONFIG_FILE=\"lwip/lwipopts.h\" -DLWIP_LITEOS_A_COMPAT
|
||||||
LITEOS_CMACRO += $(LWIP_MACROS)
|
LITEOS_CMACRO += $(LWIP_MACROS)
|
||||||
else
|
else
|
||||||
$(error "unknown lwip version")
|
$(error "unknown lwip version")
|
||||||
|
|
Loading…
Reference in New Issue