102~202案例迁移vendor

Signed-off-by: shicunyun <shicunyun@openvalley.net>
This commit is contained in:
shicunyun
2023-12-28 19:31:47 +08:00
parent 91726bdecb
commit 15e9e5cbf1
18 changed files with 2 additions and 1739 deletions
+1 -4
View File
@@ -17,10 +17,7 @@ if (ohos_kernel_type == "liteos_m") {
import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
module_group(module_name) {
modules = [
"liteos_m",
"applications",
]
modules = [ "liteos_m" ]
}
group("process_after_build") {
+1 -1
View File
@@ -16,4 +16,4 @@ menuconfig BOARD_NIOBE407
depends on SOC_STM32F407
orsource "liteos_m/hdf_config/Kconfig.liteos_m.board"
orsource "applications/Kconfig.board.applications"
orsource "../../../../vendor/talkweb/niobe407/demo/Kconfig.board.applications"
@@ -1,22 +0,0 @@
# Copyright (c) 2022 Talkweb Co., Ltd.
# Licensed 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.
import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"random_number_example.c",
"rng_init.c",
]
}
@@ -1,34 +0,0 @@
# Niobe407开发板OpenHarmony外设编程开发——RNG
随机数发生器(RNG)是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个 32 位的随机数。
本示例将演示如何在Niobe407开发板上通过rng获取随机数。
## 编译调试
- 进入//kernel/liteos_m目录, 在menuconfig配置中进入如下选项:
`(Top) → Platform → Board Selection → select board niobe407 → use talkweb niobe407 application → niobe407 application choose`
- 选择 `102_peripheral_rng_number`
- 回到sdk根目录,执行`hb build -f`脚本进行编译。
### 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志
```
Generate 32bit Random number is 3939425217
Generate 32bit Random number is 65643907
Generate 32bit Random number is 1996657443
Generate 32bit Random number is 105432700
Generate 32bit Random number is 3489997754
Generate 32bit Random number is 4219107597
Generate 32bit Random number is 2745823547
Generate 32bit Random number is 1101818015
Generate 32bit Random number is 2122724804
Generate 32bit Random number is 2652032502
Generate 32bit Random number is 2661532219
Generate 32bit Random number is 3839864595
Generate 32bit Random number is 2992609050
Generate 32bit Random number is 2483297994
Generate 32bit Random number is 2550058723
```
@@ -1,59 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 <stdio.h>
#include <string.h>
#include <unistd.h>
#include "cmsis_os2.h"
#include "ohos_run.h"
#include "rng_init.h"
#define TASK_DELAY 1000
#define STACK_SIZE 4096
void thread_entry(void)
{
unsigned int rng_num = 0;
RngInit();
while (1) {
if (HAL_OK == HAL_RNG_GenerateRandomNumber(&hrng, &rng_num)) {
printf("Generate 32bit Random number is %u\r\n", rng_num);
} else {
printf("Generate Random Number fail!\r\n");
}
osDelay(TASK_DELAY);
}
}
static void get_random_number_example(void)
{
osThreadAttr_t attr;
attr.name = "thread";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = STACK_SIZE;
attr.priority = osPriorityNormal;
if (osThreadNew((osThreadFunc_t)thread_entry, NULL, &attr) == NULL) {
printf("Failed to create thread!\n");
}
}
OHOS_APP_RUN(get_random_number_example);
@@ -1,40 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 "stm32f4xx_hal.h"
RNG_HandleTypeDef hrng;
void RngInit(void)
{
hrng.Instance = RNG;
if (HAL_RNG_Init(&hrng) != HAL_OK) {
printf("Rng init failed!\n");
}
}
void HAL_RNG_MspInit(RNG_HandleTypeDef* hrng)
{
if (hrng->Instance==RNG) {
__HAL_RCC_RNG_CLK_ENABLE();
}
}
void HAL_RNG_MspDeInit(RNG_HandleTypeDef* hrng)
{
if (hrng->Instance==RNG) {
__HAL_RCC_RNG_CLK_DISABLE();
}
}
@@ -1,31 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 __RNG_INIT_H__
#define __RNG_INIT_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern RNG_HandleTypeDef hrng;
void RngInit(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __RNG_INIT_H__ */
@@ -1,22 +0,0 @@
# Copyright (c) 2022 Talkweb Co., Ltd.
# Licensed 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.
import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"can_example.c",
"can_init.c",
]
}
@@ -1,31 +0,0 @@
# Niobe407开发板OpenHarmony外设编程开发——CAN
CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终成为国际标准(ISO 11898),是国际上应用最广泛的现场总线之一。 在北美和西欧,CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。
本示例将演示如何在Niobe407开发板上通过CAN接口收发数据。
## 编译调试
- 进入//kernel/liteos_m目录, 在menuconfig配置中进入如下选项:
`(Top) → Platform → Board Selection → select board niobe407 → use talkweb niobe407 application → niobe407 application choose`
- 选择 `103_peripheral_can_example`
- 回到sdk根目录,执行`hb build -f`脚本进行编译。
- 准备两块开发板,将固件烧录进去,然后将两块开发板的CAN口对接。(有条件可以直接通过USB转CAN接到电脑上,然后通过上位机调试CAN数据收发)
- 若测试时若无法收发数据,建议检查CAN口是否有终端电阻(使用万用表测量CAN_L与CAN_H直接电阻是否约为120Ω)
### 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志
```
HAL_CAN_Start success!
send can data [0x1234 : 88 77 66 55 44 33 22 11] success! Tx_Mail:1
Recv CANID:0x00000000 Data:88 77 66 55 44 33 22 11
send can data [0x1234 : 88 77 66 55 44 33 22 11] success! Tx_Mail:1
Recv CANID:0x00000000 Data:88 77 66 55 44 33 22 11
send can data [0x1234 : 88 77 66 55 44 33 22 11] success! Tx_Mail:1
Recv CANID:0x00000000 Data:88 77 66 55 44 33 22 11
```
@@ -1,107 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 <stdio.h>
#include <string.h>
#include <unistd.h>
#include "ohos_run.h"
#include "cmsis_os2.h"
#include "stm32f4xx_hal.h"
#include "can_init.h"
CAN_TxHeaderTypeDef TxHeader;
CAN_TxHeaderTypeDef RxHeader;
CAN_FilterTypeDef Filter;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t aRxData[8] = {0};
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, aRxData) == HAL_OK) {
uint32_t canid = (RxHeader.IDE == CAN_ID_STD)?RxHeader.StdId:RxHeader.ExtId;
printf("\nRecv CANID:0x%08X Data:", canid);
for (uint8_t i = 0; i<8; i++)
printf("%02X ", aRxData[i]);
printf("\n");
}
}
void thread_entry(void)
{
uint8_t TxData[8] = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
uint32_t TxMailbox;
uint32_t send_can_id = 0x1234;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.IDE = CAN_ID_EXT;
TxHeader.ExtId = send_can_id;
TxHeader.TransmitGlobalTime = DISABLE;
TxHeader.DLC = 8;
Filter.FilterIdHigh = 0;
Filter.FilterIdLow = 0;
Filter.FilterMaskIdHigh = 0;
Filter.FilterMaskIdLow = 0;
Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
Filter.FilterBank = 0;
Filter.FilterMode = CAN_FILTERMODE_IDMASK;
Filter.FilterScale = CAN_FILTERSCALE_32BIT;
Filter.FilterActivation = ENABLE;
Filter.SlaveStartFilterBank = 0;
HAL_CAN_ConfigFilter(&hcan1, &Filter);
while (HAL_OK != HAL_CAN_Start(&hcan1)) {
printf("HAL_CAN_Start fail! try again!\n");
osDelay(100);
}
printf("HAL_CAN_Start success!\n");
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
while (1) {
uint32_t ret = HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);
if (ret == HAL_OK) {
printf("send can data [0x%04X : %02X %02X %02X %02X %02X %02X %02X %02X] success! Tx_Mail:%u\n", \
send_can_id, TxData[0], TxData[1], TxData[2], TxData[3], TxData[4], TxData[5], TxData[6], \
TxData[7], TxMailbox);
}
else {
printf("send can data fail,ret = %s\n", \
(ret==HAL_ERROR)?"HAL_ERROR":((ret==HAL_BUSY)?"HAL_BUSY":"HAL_TIMEOUT"));
}
osDelay(1000);
}
}
static void can_send_example(void)
{
MX_CAN1_Init();
osThreadAttr_t attr;
attr.name = "thread1";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 4096;
attr.priority = 25;
if (osThreadNew((osThreadFunc_t)thread_entry, NULL, &attr) == NULL) {
printf("Failed to create thread!\n");
}
}
OHOS_APP_RUN(can_send_example);
@@ -1,104 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 <string.h>
#include <stdio.h>
#include <los_interrupt.h>
#include "stm32f4xx_hal.h"
CAN_HandleTypeDef hcan1;
void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 12;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_6TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_7TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK) {
Error_Handler();
}
}
static void can_receive_irq(void)
{
printf("can irq\n");
HAL_CAN_IRQHandler(&hcan1);
}
/**
* @brief CAN MSP Initialization
* This function configures the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (hcan->Instance==CAN1) {
/* Peripheral clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**CAN1 GPIO Configuration
PI9 ------> CAN1_RX
PB9 ------> CAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
LOS_HwiCreate(CAN1_RX0_IRQn, 0, 0, (HWI_PROC_FUNC)can_receive_irq, 0);
}
}
/**
* @brief CAN MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
{
if (hcan->Instance==CAN1) {
/* Peripheral clock disable */
__HAL_RCC_CAN1_CLK_DISABLE();
/**CAN1 GPIO Configuration
PI9 ------> CAN1_RX
PB9 ------> CAN1_TX
*/
HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
}
}
@@ -1,31 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 __CAN_INIT_H__
#define __CAN_INIT_H__
#ifdef __cplusplus
extern "C " {
#endif /* __cplusplus */
extern CAN_HandleTypeDef hcan1;
void MX_CAN1_Init(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __CAN_INIT_H__ */
@@ -1,32 +0,0 @@
# Copyright (c) 2022 Talkweb Co., Ltd.
# Licensed 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.
import("//kernel/liteos_m/liteos.gni")
assert(
defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO),
"Must Config LOSCFG_DRIVERS_HDF_PLATFORM_GPIO in kernel/liteos_m menuconfig!")
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [ "hdf_gpio_test.c" ]
include_dirs = [
".",
"//drivers/hdf_core/framework/include/platform",
"//drivers/hdf_core/framework/include/utils",
"//drivers/hdf_core/adapter/khdf/liteos_m/osal/include",
"//drivers/hdf_core/interfaces/inner_api/osal/shared",
"//drivers/hdf_core/framework/include/osal",
]
}
@@ -1,224 +0,0 @@
# Niobe407开发板OpenHarmony基于HDF驱动框架编程开发——GPIO
本示例将演示如何在Niobe407开发板上通过HDF驱动框架,使用GPIO按键中断。
## 编译调试
- 进入//kernel/liteos_m目录, 在menuconfig配置中进入如下选项:
`(Top) → Platform → Board Selection → select board niobe407 → use talkweb niobe407 application → niobe407 application choose`
- 选择 `201_hdf_gpio_key`
- 在menuconfig的`(Top) → Driver`选项中使能如下配置:
```
[*] Enable Driver
[*] HDF driver framework support
[*] Enable HDF platform driver
[*] Enable HDF platform gpio driver
```
- 回到sdk根目录,执行`hb build -f`脚本进行编译。
### 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志
```
Entering scheduler
[HDF:E/HDF_LOG_TAG]DeviceManagerStart in
[HDF:I/devmgr_service]start svcmgr result 0
[HDF:I/hcs_blob_if]CheckHcsBlobLength: the blobLength: 1884, byteAlign: 1
[HDF:I/device_node]launch devnode HDF_PLATFORM_GPIO
GpioDriverBind
[HDF:I/gpio_manager]GpioManagerAdd: start:0 count:8 added success
[HDF:D/HDF_LOG_TAG]PlatformManagerAddDevice: add dev:(null)(0) to PLATFORM_MODULE_GPIO success
[HDF:D/HDF_LOG_TAG]PlatformDeviceAdd: add dev:(null)(0) success
[HDF:E/HDF_LOG_TAG]HdfDriverManagerGetDriver:driver STM_TW_SPI_MODULE_HDF not found
[HDF:E/devhost_service_clnt]failed to install driver HDF_PLATFORM_SPI_0, ret = -207
hiview init success.
[HDF:E/HDF_LOG_TAG]HdfGpioTestEntry: mode:2
```
当按下开发板上的按钮sw2时,点亮或者点灭, 按下开发板上按钮sw3时, 绿灯点亮或者点灭 ,可通过串口助手查看到如下日志:
```
[HDF:E/HDF_LOG_TAG]TestCaseGpioIrqHandler1: irq triggered! on gpio:2, data=(nil)
[HDF:E/gpio_stm32_c]GpioDevWrite 433 ,write pin num 5
[HDF:E/HDF_LOG_TAG]TestCaseGpioIrqHandler1: irq triggered! on gpio:2, data=(nil)
[HDF:E/gpio_stm32_c]GpioDevWrite 433 ,write pin num 5
[HDF:E/HDF_LOG_TAG]TestCaseGpioIrqHandler2: irq triggered! on gpio:3, data=(nil)
[HDF:E/gpio_stm32_c]GpioDevWrite 433 ,write pin num 6
```
## GPIO HDF hcs配置文件解析
- device_gpio_info 在/device/board/talkweb/niobe407/sdk/hdf_config/device_gpio_info.hcs
```
root {
module = "talkweb,stm32f407";
device_info {
match_attr = "hdf_manager";
template host {
hostName = "";
priority = 100;
template device {
template deviceNode { //gpio信息的模板,集成模板可以缺省
policy = 0;
priority = 100;
preload = 0;
permission = 0664;
moduleName = "";
serviceName = "";
deviceMatchAttr = "";
}
}
}
platform :: host {
hostName = "platform_host";
priority = 50;
device_gpio :: device {
gpio0 :: deviceNode {
policy = 2;
priority = 60; //权限决定加载的顺序
moduleName = "STM_TW_GPIO_MODULE_HDF";
serviceName = "HDF_PLATFORM_GPIO";//驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
deviceMatchAttr = "gpio_config"; // 与hdf_gpio_.hcs中的config匹配
}
}
}
}
}
```
- hdf_gpio.hcs解析 在/device/board/talkweb/niobe407/sdk/hdf_config/目录下,配置具体gpio引脚的信息
```
#include "device_gpio_info.hcs" // 包含具体的device_info文件
root {
platform {
gpio_config {
match_attr = "gpio_config"; // 与device_gpio_info.hcs中的deviceMatchAttr对应
pin = [0, 1, 2, 3]; // 框架注册pin号,在使用接口时用作GPIO号来使用
realPin = [5, 6, 0, 1]; // 与pin对应的真实的在stm32中真实的引脚编号(0-15)开发板,此示例为 led2 pe5, led3 pe6, key1按键终端 pe0,sw2, key2按键终端pe1,sw3
group = [4, 4, 4, 4]; // gpio引脚所属的group 0到8 分别对应GPIOA~GPIOI,此例4个gpio属于GPIOE
mode = [1, 1, 0, 0]; // 0: input 1: output 2:alternate 3:analog
speed = [0, 0, 0, 0]; // 0: low 1: middle 2:high 3:very_high
pull = [0, 0, 0, 0]; // 0: nopull 1:up 2:down
pinNum = 4; //总注册gpio个数 如果发现因为加载的gpio个数过多导致无法申请到锁资源,可修改target_config.h中的LOSCFG_BASE_IPC_MUX_LIMIT 增大锁的数量限制
output = [0, 0, 0, 0]; // 0:pushpull 1:opendrain
alternate = [0, 0, 0, 0]; // 对应的stm32的管脚复用功能gpio作为每种外设都对应一种复用功能(0-15,具体参考编程手册)
}
}
}
```
## 接口说明
```
1.读写GPIO管脚, 如果要读取一个GPIO管脚电平,通过以下函数完成:
int32_t GpioRead(uint16_t gpio, uint16_t *val);
参数说明:
gpio: 对应hcs文件中的pin号
val: 存储读取的值
返回值:
0: 读取成功
负数:读取失败
2.如果要向GPIO管脚写入电平值,通过以下函数完成:
int32_t GpioWrite(uint16_t gpio, uint16_t val);
参数说明:
gpio: 对应hcs文件中的pin号
val: 需要设置的电平值
返回值:
0: 设置成功
负数:设置失败
3.如果要为一个GPIO管脚设置中断响应程序,使用如下函数:
int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);
参数说明:
gpio: 对应hcs文件中的pin号
mode: 中断触发模式
func: 中断回调函数
arg: 回调函数参数
返回值:
0: 设置成功
负数:设置失败
4.当不再需要响应中断服务函数时,使用如下函数取消中断设置:
int32_t GpioUnSetIrq(uint16_t gpio);
参数说明:
gpio: 对应hcs文件中的pin号
返回值:
0: 设置成功
负数:设置失败
5.在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断:
int32_t GpioEnableIrq(uint16_t gpio);
参数说明:
gpio: 对应hcs文件中的pin号
返回值:
0: 使能成功
负数: 使能失败
6.如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断
int32_t GpioDisableIrq(uint16_t gpio);
参数说明:
gpio: 对应hcs文件中的pin号
返回值:
0: 禁止成功
负数: 禁止失败
```
## 示例代码
``` c
/* 中断服务函数*/
static int32_t TestCaseGpioIrqHandler1(uint16_t gpio, void *data) // pin2 回调函数
{
HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data);
uint16_t val = 0;
GpioRead(0, &val); // 读取pin0 的电平值,中断产生则设置相反的电平
if (val) {
GpioWrite(0, 0);
} else {
GpioWrite(0, 1);
}
}
static int32_t TestCaseGpioIrqHandler2(uint16_t gpio, void *data) // pin3 回调函数
{
HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data);
uint16_t val = 0;
GpioRead(1, &val); // 读取pin1 的电平值,中断产生则设置相反的电平
if (val) {
GpioWrite(1, 0);
} else {
GpioWrite(1, 1);
}
}
static void* HdfGpioTestEntry(void* arg)
{
int32_t ret;
uint16_t valRead;
uint16_t mode;
uint16_t gpio0 = 0; // hcs 中对应的pin值
uint16_t gpio1 = 1;
uint16_t gpio2 = 2;
uint16_t gpio3 = 3;
uint32_t timeout;
mode = OSAL_IRQF_TRIGGER_FALLING;
HDF_LOGE("%s: mode:%0x\n", __func__, mode);
ret = GpioSetIrq(gpio2, mode, TestCaseGpioIrqHandler1, NULL); // 设置中断函数
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret);
return ret;
}
ret = GpioSetIrq(gpio3, mode, TestCaseGpioIrqHandler2, NULL); // 设置中断函数
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret);
return ret;
}
ret = GpioEnableIrq(gpio2); // 使能中断
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret);
return ret;
}
ret = GpioEnableIrq(gpio3); // 使能中断
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret);
return ret;
}
}
```
@@ -1,119 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 <stdio.h>
#include "ohos_run.h"
#include "osal_irq.h"
#include "osal_time.h"
#include "ohos_run.h"
#include "cmsis_os2.h"
#ifdef LOSCFG_DRIVERS_HDF_PLATFORM_GPIO
#include "hdf_log.h"
#include "gpio_if.h"
#endif
#define HDF_GPIO_STACK_SIZE 0x1000
#define HDF_GPIO_TASK_NAME "hdf_gpio_test_task"
#define HDF_GPIO_TASK_PRIORITY 25
#ifdef LOSCFG_DRIVERS_HDF_PLATFORM_GPIO
static int32_t TestCaseGpioIrqHandler1(uint16_t gpio, void *data)
{
HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data);
uint16_t val = 0;
GpioRead(0, &val);
if (val) {
GpioWrite(0, 0);
} else {
GpioWrite(0, 1);
}
}
static int32_t TestCaseGpioIrqHandler2(uint16_t gpio, void *data)
{
HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data);
uint16_t val = 0;
GpioRead(1, &val);
if (val) {
GpioWrite(1, 0);
} else {
GpioWrite(1, 1);
}
}
static void* HdfGpioTestEntry(void* arg)
{
(void)arg;
int32_t ret;
uint16_t mode;
uint16_t gpio2 = 2;
uint16_t gpio3 = 3;
mode = OSAL_IRQF_TRIGGER_FALLING;
HDF_LOGE("%s: mode:%0x\n", __func__, mode);
ret = GpioSetIrq(gpio2, mode, TestCaseGpioIrqHandler1, NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret);
return NULL;
}
ret = GpioSetIrq(gpio3, mode, TestCaseGpioIrqHandler2, NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret);
return NULL;
}
ret = GpioEnableIrq(gpio2);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret);
return NULL;
}
ret = GpioEnableIrq(gpio3);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret);
return NULL;
}
}
void StartHdfGpioTest(void)
{
osThreadAttr_t attr;
attr.name = HDF_GPIO_TASK_NAME;
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = HDF_GPIO_STACK_SIZE;
attr.priority = HDF_GPIO_TASK_PRIORITY;
if (osThreadNew((osThreadFunc_t)HdfGpioTestEntry, NULL, &attr) == NULL) {
printf("Failed to create thread1!\n");
}
}
#else
void StartHdfGpioTest(void)
{
printf("StartHdfGpioTest fail!\n");
printf("You should open LOSCFG_DRIVERS_HDF_PLATFORM_GPIO support in kernel/liteos_m menuconfig.\n");
}
#endif
OHOS_APP_RUN(StartHdfGpioTest);
@@ -1,32 +0,0 @@
# Copyright (c) 2022 Talkweb Co., Ltd.
# Licensed 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.
import("//kernel/liteos_m/liteos.gni")
assert(
defined(LOSCFG_DRIVERS_HDF_PLATFORM_SPI),
"Must Config LOSCFG_DRIVERS_HDF_PLATFORM_SPI in kernel/liteos_m menuconfig!")
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [ "hdf_spi_test.c" ]
include_dirs = [
".",
"//drivers/hdf_core/framework/include/platform",
"//drivers/hdf_core/framework/include/utils",
"//drivers/hdf_core/adapter/khdf/liteos_m/osal/include",
"//drivers/hdf_core/interfaces/inner_api/osal/shared",
"//drivers/hdf_core/framework/include/osal",
]
}
@@ -1,362 +0,0 @@
# Niobe407开发板OpenHarmony基于HDF驱动框架编程开发——SPI
本示例将演示如何在Niobe407开发板上通过HDF驱动框架,使用SPI接口读写外部SPI-FLASH。
## 编译调试
- 进入//kernel/liteos_m目录, 在menuconfig配置中进入如下选项:
`(Top) → Platform → Board Selection → select board niobe407 → use talkweb niobe407 application → niobe407 application choose`
- 选择 `202_hdf_spi_flash`
- 在menuconfig的`(Top) → Driver`选项中使能如下配置:
```
[*] Enable Driver
[*] HDF driver framework support
[*] Enable HDF platform driver
[*] Enable HDF platform spi driver
```
- 回到sdk根目录,执行`hb build -f`脚本进行编译。
### 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志
```
[HDF:I/HDF_LOG_TAG]spi 0 open success 0x40003800
[HDF:I/HDF_LOG_TAG]read device id is 0x17
[HDF:I/HDF_LOG_TAG]read flash id is 0x4018
[HDF:I/HDF_LOG_TAG]send buffer is welcome to OpenHarmony
[HDF:I/HDF_LOG_TAG]recv send buffer is welcome to OpenHarmony
[HDF:I/HDF_LOG_TAG]hdf spi write read flash success
[HDF:I/HDF_LOG_TAG]spi 0 close success 0x40003800
```
## SPI HDF HCS配置文件解析
- device_spi_info.hcs 在/device/board/talkweb/niobe407/sdk/hdf_config/device_spi_info.hcs
```
root {
module = "talkweb,stm32f407";
device_info {
match_attr = "hdf_manager";
template host {
hostName = "";
priority = 100;
template device {
template deviceNode {
policy = 0;
priority = 100;
preload = 0;
permission = 0664;
moduleName = "";
serviceName = "";
deviceMatchAttr = "";
}
}
}
platform :: host {
hostName = "platform_host";
device_spi :: device {
spi0 :: deviceNode {
policy = 2;
priority = 100; // 因为spi的gpio引脚要在spi初始化之前初始化,所以优先级比gpio的hdf优先级低
moduleName = "STM_TW_SPI_MODULE_HDF"; //驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
serviceName = "HDF_PLATFORM_SPI_0";
deviceMatchAttr = "spi_w25q_config"; // 对应hdf_spi.hcs中的config
}
}
}
}
}
```
- hdf_spi.hcs在在/device/board/talkweb/niobe407/sdk/hdf_config/hdf_spi.hcs,主要包括spi设置的信息的配置
```
#include "device_spi_info.hcs"
root {
platform {
spi1_config {
spi1_gpio {
// 要配置的引脚个数,接下来的引脚名必须定义成gpio_num_1, gpio_num_2, gpio_num_3...
gpio_num_max = 4;
// port, pin, mode, speed, outputType, pull, alternate
gpio_num_1 = [0, 5, 2, 3, 0, 0, 5]; // clk pa5
gpio_num_2 = [1, 5, 2, 3, 0, 0, 5]; // mosi pb5
gpio_num_3 = [1, 4, 2, 3, 0, 0, 5]; // miso pb4
gpio_num_4 = [0, 15, 1, 3, 0, 0 ,0]; // cs pa15
}
spi_config : spi1_gpio {
match_attr = "spi_w25q_config";
busNum = 0; // 注册的总线号
csNum = 0; // 片选号
transDir = 0; // 0: TW_HAL_SPI_FULL_DUPLEX 1: TW_HAL_SPI_SIMPLEX_RX 2: TW_HAL_SPI_HALF_DUPLEX_RX 3: TW_HAL_SPI_HALF_DUPLEX_TX
transMode = 1; // 1: normal 0:dma
smMode = 1; // 0: slave 1: master
dataWidth = 0; // 0:8bit 1:16bit
clkMode = 0; // 0: cpol 0 cpha 0 1:CPOL = 1; CPHA = 0 2:CPOL = 0; CPHA = 1 3:CPOL = 1; CPHA = 1
nss = 0; // 0:NSS SOFT 1: NSS HARDWARE INPUT 2: NSS HARDWARE OUTPUT
baudRate = 1; // 0:div2 1:div4 2:div8 3:div16 4:div32 5:div64 6:div128 6:div256
bitOrder = 0; // 0: MSB first 1: LSB first
crcEnable = 0; // 0: crc disable 1: crc enable
crcPoly = 10; // Min_Data = 0x00 and Max_Data = 0xFFFF
spix = 0; // 0: spi1 1: spi2 2:spi3 本例程使用SPI1作为示例
csPin = 15; // cs pin
csGpiox = 0; // cs pin group
standard = 0; // 0:motorola 1: ti
dummyByte = 255;
}
}
}
}
```
## 接口解析
```
1.在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。
DevHandle SpiOpen(const struct SpiDevInfo *info);
参数说明:
info: SPI设备描述符, 设置了总线号和片选号
返回值:
NULL: 打开失败
设备句柄:打开成功
2.在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示:
int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg);
参数说明:
handle: 设备句柄
cfg: 设置的spi的设置
返回值:
0: 设置成功
负数:设置失败
3.如果需要发起一次自定义传输,则可以通过以下函数完成:
int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count);
参数说明:
handle: 设备句柄
msgs: 待传输数据的数组
count: 待传输的数组的长度
返回值:
0: 执行成功
负数:执行失败
4.SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示:
void SpiClose(DevHandle handle);
参数说明:
handle: 设备句柄
```
### 示例代码解析
- 开启spi,参数获取和设置示例
``` c
static void* HdfSpiTestEntry(void* arg)
{
int32_t ret;
uint16_t flashId = 0;
uint16_t deviceId = 0;
struct SpiCfg cfg; /* SPI配置信息 */
struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */
DevHandle spiHandle = NULL; /* SPI设备句柄 */
spiDevinfo.busNum = 0; /* SPI设备总线号 */
spiDevinfo.csNum = 0; /* SPI设备片选号 */
spiHandle = SpiOpen(&spiDevinfo); /* 根据spiDevinfo获取SPI设备句柄 */
if (spiHandle == NULL) {
HDF_LOGE("SpiOpen: failed\n");
return;
}
/* 获取SPI设备属性 */
ret = SpiGetCfg(spiHandle, &cfg);
if (ret != 0) {
HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret);
goto err;
}
HDF_LOGI("speed:%d, bitper:%d, mode:%d, transMode:%d\n", cfg.maxSpeedHz, cfg.bitsPerWord, cfg.mode, cfg.transferMode);
cfg.maxSpeedHz = 1; /* spi2spi3 最大频率为42M, spi1 频率为84M 此处的值为分频系数,0:1/2 1:1/4 2:1/8 . */
/* 3: 1/16, 4: 1/32 5:1/64, 6:1/128 7:1/256 */
cfg.bitsPerWord = 8; /* 传输位宽改为8比特 */
cfg.mode = 0;
cfg.transferMode = 1; /* 0:dma 1:normal */
/* 配置SPI设备属性 */
ret = SpiSetCfg(spiHandle, &cfg);
if (ret != 0) {
HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret);
goto err;
}
SpiClose(spiHandle);
```
- spi消息传输示例使用SpiTransfer
``` c
static uint16_t ReadDeviceId(DevHandle spiHandle)
{
struct SpiMsg msg; /* 自定义传输的消息 */
uint16_t deviceId = 0;
uint8_t rbuff[5] = { 0 };
uint8_t wbuff[5] = { 0xAB, 0xFF, 0xFF, 0xFF, 0xFF }; // oxab为读DeviceId 指令,其他为dummyData
int32_t ret = 0;
msg.wbuf = wbuff; /* 写入的数据 */
msg.rbuf = rbuff; /* 读取的数据 */
msg.len = 5; /* 读取写入数据的长度为4 */
msg.keepCs = 0; /* 进行下一次传输前关闭片选 */
msg.delayUs = 0; /* 进行下一次传输前不进行延时 */
//msg.speed = 115200; /* 本次传输的速度 */
/* 进行一次自定义传输,传输的msg个数为1 */
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
} else {
deviceId = rbuff[4]; // 最后一次发送oxff返回deviceid
}
return deviceId;
}
static void BufferWrite(DevHandle spiHandle, const uint8_t* buf, uint32_t size)
{
WriteEnable(spiHandle); //使能spi写
uint8_t wbuf[4] = {0x02, 0x00, 0x00, 0x00}; // 0x02 写指令write buf头,0x00, 0x00, 0x00 三个为6位写的地址
uint8_t rbuf[4] = {0};
uint8_t *rbuf1 = NULL;
int32_t ret = 0;
struct SpiMsg msg = {0};
msg.wbuf = wbuf;
msg.rbuf = rbuf;
msg.len = 4;
msg.keepCs = 1; // 写指令发送后不关闭片选
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
rbuf1 = (uint8_t*)OsalMemAlloc(size);
memset_s(rbuf1, size, 0, size);
msg.wbuf = buf;
msg.rbuf = rbuf1;
msg.len = size;
msg.keepCs = 0; // 写完内容后关闭片选
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1); //传输真正书写的内容
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
WaitForWriteEnd(spiHandle); // 等待书写完成
if (rbuf1!= NULL) {
OsalMemFree(rbuf1);
}
}
static void BufferRead(DevHandle spiHandle, uint8_t* buf, uint32_t size)
{
int32_t ret = 0;
uint8_t wbuf[4] = {0x03, 0x00, 0x00, 0x00}; // 0x03 读指令, 后三个0x00 为地址
uint8_t rbuf[4] = {0};
struct SpiMsg msg = {0};
msg.wbuf = wbuf;
msg.rbuf = rbuf;
msg.len = 4;
msg.keepCs = 1; // 写使能不关闭片选
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
return;
}
uint8_t *wbuf1 = NULL;
wbuf1 = (uint8_t*)OsalMemAlloc(size);
memset_s(wbuf1, size, 0xff, size);
msg.wbuf = wbuf1;
msg.rbuf = buf;
msg.len = size;
msg.keepCs = 0;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1); // 读取spi flash中存储的值
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
return;
}
if (wbuf1!= NULL) {
OsalMemFree(wbuf1);
}
}
```
- 使用SpiWrite, SpiRead通信,由于使用这两个接口无法制定是否关闭片选,因此在写或者读得buf第一个字节为自定义关闭片选信号,0不关闭片选, 1关闭片选,读取内容时要注意去掉第一个字节
``` c
static uint16_t ReadDeviceId(DevHandle spiHandle)
{
struct SpiMsg msg; /* 自定义传输的消息 */
uint16_t deviceId = 0;
uint8_t rbuff1[2] = { 0 };
uint8_t wbuff1[5] = {0x00, 0xAB, 0xff,0xff, 0xff}; //0x00 不关闭片选,0xab读取设备指令,0xff为dummydata
int32_t ret = 0;
/* 发送命令:读取芯片型号ID */
ret =SpiWrite(spiHandle, wbuff1, 5);
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
rbuff1[0] = 0x01; //关闭片选
ret = SpiRead(spiHandle, rbuff1, 2);
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
deviceId = rbuff1[1];
return deviceId;
}
static void BufferWrite(DevHandle spiHandle, const uint8_t* buf, uint32_t size)
{
WriteEnable(spiHandle);
uint8_t wbuf[5] = {0x01, 0x02, 0x00, 0x00, 0x00};// 0x01 关闭片选, 0x02写指令,后面3个0x00为地址
uint8_t rbuf[4] = {0};
uint8_t *wbuf1 = NULL;
int32_t ret = 0;
wbuf1 = (uint8_t*)OsalMemAlloc(size + sizeof(wbuf));
strncpy_s(wbuf1, size + sizeof(wbuf), wbuf, sizeof(wbuf));
strncpy_s(wbuf1 + sizeof(wbuf), size, buf, size);
ret = SpiWrite(spiHandle, wbuf1, size + sizeof(wbuf)); //将写写指令和内容一起写入spi flash
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
WaitForWriteEnd(spiHandle);
if (wbuf1!= NULL) {
OsalMemFree(wbuf1);
}
}
static void BufferRead(DevHandle spiHandle, uint8_t* buf, uint32_t size)
{
WriteEnable(spiHandle);
uint8_t wbuf[5] = {0x00, 0x03, 0x00, 0x00, 0x00};// 0x00 不关闭片选, 0x03读指令,后面3个0x00为地址
uint8_t *rbuf = NULL;
int32_t ret = 0;
rbuf = (uint8_t*)OsalMemAlloc(size + 1);
ret = SpiWrite(spiHandle, wbuf, 5);// 先写读指令和地址
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
rbuf[0] = 0x01; // 读完关闭片选
ret = SpiRead(spiHandle, rbuf, size + 1); // 读取内容
if (ret != 0) {
HDF_LOGE("SpiRead: failed, ret %d\n", ret);
}
strncpy_s(buf, size, rbuf + 1, size);
if (rbuf!= NULL) {
OsalMemFree(rbuf);
}
return;
```
@@ -1,484 +0,0 @@
/*
* Copyright (c) 2022 Talkweb Co., Ltd.
* Licensed 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 <stdio.h>
#include "hdf_log.h"
#include "spi_if.h"
#include "cmsis_os2.h"
#include "samgr_lite.h"
#include "ohos_run.h"
#define HDF_SPI_STACK_SIZE 0x1000
#define HDF_SPI_TASK_NAME "hdf_spi_test_task"
#define HDF_SPI_TASK_PRIORITY 25
uint8_t txBuffer[] = "welcome to OpenHarmony\n";
#define WIP_FLAG 0x01
#define SPI_FLASH_IDx 0x4018
#define Countof(a) (sizeof(a)/sizeof(*(a)))
#define bufferSize (Countof(txBuffer) - 1)
uint8_t rxBuffer[bufferSize] = {0};
#define USE_TRANSFER_API 1
static uint8_t BufferCmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while (BufferLength--) {
if (*pBuffer1 != *pBuffer2) {
return 0;
}
pBuffer1++;
pBuffer2++;
}
return 1;
}
#if (USE_TRANSFER_API == 1)
static uint16_t ReadDeviceId(DevHandle spiHandle)
{
struct SpiMsg msg;
uint16_t deviceId = 0;
uint8_t rbuff[5] = { 0 };
uint8_t wbuff[5] = { 0xAB, 0xFF, 0xFF, 0xFF, 0xFF };
int32_t ret = 0;
msg.wbuf = wbuff;
msg.rbuf = rbuff;
msg.len = sizeof(wbuff);
msg.keepCs = 0;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
} else {
deviceId = rbuff[4];
}
return deviceId;
}
static uint16_t ReadFlashId(DevHandle spiHandle)
{
int32_t ret = 0;
uint16_t flashId = 0;
uint8_t rbuff1[4] = { 0 };
uint8_t wbuff1[4] = { 0x9f, 0xFF, 0xFF, 0xFF };
struct SpiMsg msg1 = {0};
msg1.wbuf = wbuff1;
msg1.rbuf = rbuff1;
msg1.len = sizeof(wbuff1);
msg1.keepCs = 0;
msg1.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg1, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
} else {
flashId = (msg1.rbuf[2]<<8)|msg1.rbuf[3];
}
return flashId;
}
static void WaitForWriteEnd(DevHandle spiHandle)
{
uint8_t FLASH_Status = 0;
/* Send "Read Status Register" instruction */
uint8_t wbuf[1] = {0x05};
uint8_t wbuf1[1] = {0xff};
uint8_t rbuf[1] = {0};
struct SpiMsg msg = {0};
msg.wbuf = wbuf;
msg.rbuf = rbuf;
msg.len = sizeof(wbuf);
msg.keepCs = 1;
msg.delayUs = 0;
int32_t ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
/* Loop as long as the memory is busy with a write cycle */
do {
msg.wbuf = wbuf1;
msg.rbuf = rbuf;
msg.len = sizeof(wbuf1);
msg.keepCs = 1;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
FLASH_Status = rbuf[0];
}
while ((FLASH_Status & WIP_FLAG) == 1); /* Write in progress */
msg.wbuf = wbuf1;
msg.rbuf = rbuf;
msg.len = sizeof(wbuf1);
msg.keepCs = 0;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
}
static void WriteEnable(DevHandle spiHandle)
{
uint8_t wbuf[1] = {0x06};
uint8_t rbuf[1] = {0};
struct SpiMsg msg = {0};
msg.wbuf = wbuf;
msg.rbuf = rbuf;
msg.len = sizeof(wbuf);
msg.keepCs = 0;
msg.delayUs = 0;
int32_t ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
}
static void BufferWrite(DevHandle spiHandle, const uint8_t* buf, uint32_t size)
{
WriteEnable(spiHandle);
uint8_t wbuf[4] = {0x02, 0x00, 0x00, 0x00};
uint8_t rbuf[4] = {0};
uint8_t *rbuf1 = NULL;
int32_t ret = 0;
struct SpiMsg msg = {0};
msg.wbuf = wbuf;
msg.rbuf = rbuf;
msg.len = sizeof(wbuf);
msg.keepCs = 1;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
rbuf1 = (uint8_t*)OsalMemAlloc(size);
if (rbuf1 == NULL) {
HDF_LOGE("OsalMemAlloc failed.\n");
return;
}
memset_s(rbuf1, size, 0, size);
msg.wbuf = buf;
msg.rbuf = rbuf1;
msg.len = size;
msg.keepCs = 0;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
}
WaitForWriteEnd(spiHandle);
OsalMemFree(rbuf1);
}
static void BufferRead(DevHandle spiHandle, uint8_t* buf, uint32_t size)
{
int32_t ret = 0;
uint8_t wbuf[4] = {0x03, 0x00, 0x00, 0x00};
uint8_t rbuf[4] = {0};
struct SpiMsg msg = {0};
msg.wbuf = wbuf;
msg.rbuf = rbuf;
msg.len = sizeof(wbuf);
msg.keepCs = 1;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
return;
}
uint8_t *wbuf1 = (uint8_t*)OsalMemAlloc(size);
if (wbuf1 == NULL) {
HDF_LOGE("OsalMemAlloc failed.\n");
return;
}
memset_s(wbuf1, size, 0xff, size);
msg.wbuf = wbuf1;
msg.rbuf = buf;
msg.len = size;
msg.keepCs = 0;
msg.delayUs = 0;
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
return;
}
OsalMemFree(wbuf1);
}
static void SectorErase(DevHandle spiHandle)
{
WriteEnable(spiHandle);
WaitForWriteEnd(spiHandle);
uint8_t wbuf[4] = {0x20, 0x00, 0x00, 0x00};
uint8_t rbuf[4] = {0};
struct SpiMsg msg = {0};
msg.wbuf = wbuf;
msg.rbuf = rbuf;
msg.len = sizeof(wbuf);
msg.keepCs = 0;
msg.delayUs = 0;
int32_t ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
return;
}
WaitForWriteEnd(spiHandle);
}
#else
static uint16_t ReadDeviceId(DevHandle spiHandle)
{
struct SpiMsg msg;
uint16_t deviceId = 0;
uint8_t rbuff1[2] = { 0 };
uint8_t wbuff1[5] = {0x00, 0xAB, 0xff, 0xff, 0xff};
int32_t ret = 0;
ret =SpiWrite(spiHandle, wbuff1, 5);
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
rbuff1[0] = 0x01;
ret = SpiRead(spiHandle, rbuff1, 2);
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
deviceId = rbuff1[1];
return deviceId;
}
static uint16_t ReadFlashId(DevHandle spiHandle)
{
int32_t ret = 0;
uint16_t flashId = 0;
uint8_t wbuff[2] = {0x00, 0x9f};
uint8_t rbuff[4] = {0};
ret =SpiWrite(spiHandle, wbuff, sizeof(wbuff));
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
rbuff[0] = 0x01;
ret = SpiRead(spiHandle, rbuff, 4);
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
flashId = (rbuff[2] << 8)|rbuff[3];
return flashId;
}
static void WaitForWriteEnd(DevHandle spiHandle)
{
uint8_t FLASH_Status = 0;
int32_t ret = 0;
uint8_t wbuff[2] = {0x00, 0x05};
uint8_t rbuff[2] = {0};
ret =SpiWrite(spiHandle, wbuff, sizeof(wbuff));
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
do {
rbuff[0] = 0;
ret = SpiRead(spiHandle, rbuff, 2);
if (ret != 0) {
HDF_LOGE("SpiRead: failed, ret %d\n", ret);
}
FLASH_Status = rbuff[1];
} while ((FLASH_Status & WIP_FLAG) == 1); /* Write in progress */
uint8_t wbuff1[1] = {0x01};
ret =SpiWrite(spiHandle, wbuff1, sizeof(wbuff1));
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
}
static void WriteEnable(DevHandle spiHandle)
{
uint8_t FLASH_Status = 0;
int32_t ret = 0;
uint8_t wbuff[2] = {0x01, 0x06};
ret =SpiWrite(spiHandle, wbuff, sizeof(wbuff));
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
return;
}
static void BufferWrite(DevHandle spiHandle, const uint8_t* buf, uint32_t size)
{
WriteEnable(spiHandle);
uint8_t wbuf[5] = {0x01, 0x02, 0x00, 0x00, 0x00};
uint8_t rbuf[4] = {0};
uint8_t *wbuf1 = NULL;
int32_t ret = 0;
wbuf1 = (uint8_t*)OsalMemAlloc(size + sizeof(wbuf));
ret = strncpy_s(wbuf1, size + sizeof(wbuf), wbuf, sizeof(wbuf));
if (ret < 0) {
HDF_LOGE("strncpy wbuf failed, ret %d\n", ret);
}
ret = strncpy_s(wbuf1 + sizeof(wbuf), size, buf, size);
if (ret < 0) {
HDF_LOGE("strncpy buf failed, ret %d\n", ret);
}
ret = SpiWrite(spiHandle, wbuf1, size + sizeof(wbuf));
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
WaitForWriteEnd(spiHandle);
if (wbuf1!= NULL) {
OsalMemFree(wbuf1);
}
}
static void BufferRead(DevHandle spiHandle, uint8_t* buf, uint32_t size)
{
WriteEnable(spiHandle);
uint8_t wbuf[5] = {0x00, 0x03, 0x00, 0x00, 0x00};
uint8_t *rbuf = NULL;
int32_t ret = 0;
rbuf = (uint8_t*)OsalMemAlloc(size + 1);
ret = SpiWrite(spiHandle, wbuf, sizeof(wbuf));
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
rbuf[0] = 0x01;
ret = SpiRead(spiHandle, rbuf, size + 1);
if (ret != 0) {
HDF_LOGE("SpiRead: failed, ret %d\n", ret);
}
strncpy_s(buf, size, rbuf + 1, size);
if (rbuf!= NULL) {
OsalMemFree(rbuf);
}
return;
}
static void SectorErase(DevHandle spiHandle)
{
WriteEnable(spiHandle);
WaitForWriteEnd(spiHandle);
uint8_t wbuf[5] = {0x01, 0x20, 0x00, 0x00, 0x00};
uint8_t rbuf[5] = {0};
int32_t ret = 0;
ret = SpiWrite(spiHandle, wbuf, sizeof(wbuf));
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
}
WaitForWriteEnd(spiHandle);
}
#endif
static void* HdfSpiTestEntry(void* arg)
{
(void)arg;
#ifdef USE_SET_CFG
int32_t ret;
struct SpiCfg cfg;
#endif
uint16_t flashId = 0;
uint16_t deviceId = 0;
struct SpiDevInfo spiDevinfo;
DevHandle spiHandle;
spiDevinfo.busNum = 0;
spiDevinfo.csNum = 0;
spiHandle = SpiOpen(&spiDevinfo);
if (spiHandle == NULL) {
HDF_LOGE("SpiOpen: failed\n");
return NULL;
}
#ifdef USE_SET_CFG
ret = SpiGetCfg(spiHandle, &cfg);
if (ret != 0) {
HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret);
goto err;
}
HDF_LOGI("speed:%d, bitper:%d, mode:%d, transMode:%d\n", cfg.maxSpeedHz, cfg.bitsPerWord, cfg.mode, \
cfg.transferMode);
cfg.maxSpeedHz = 1;
cfg.bitsPerWord = 8;
cfg.mode = 0;
cfg.transferMode = 1;
ret = SpiSetCfg(spiHandle, &cfg);
if (ret != 0) {
HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret);
goto err;
}
SpiClose(spiHandle);
spiHandle = SpiOpen(&spiDevinfo);
if (spiHandle == NULL) {
HDF_LOGE("SpiOpen: failed\n");
return NULL;
}
#endif
deviceId = ReadDeviceId(spiHandle);
HDF_LOGI("read device id is 0x%02x\n", deviceId);
flashId = ReadFlashId(spiHandle);
HDF_LOGI("read flash id is 0x%02x\n", flashId);
if (flashId == SPI_FLASH_IDx) {
SectorErase(spiHandle);
BufferWrite(spiHandle, txBuffer, bufferSize);
HDF_LOGI("send buffer is %s\n", txBuffer);
BufferRead(spiHandle, rxBuffer, bufferSize);
HDF_LOGI("recv send buffer is %s\n", rxBuffer);
if (BufferCmp(txBuffer, rxBuffer, bufferSize)) {
HDF_LOGI("hdf spi write read flash success\n");
} else {
HDF_LOGI("hdf spi write read flash failed\n");
}
}
#ifdef USE_SET_CFG
err:
#endif
SpiClose(spiHandle);
return NULL;
}
void StartHdfSpiTest(void)
{
osThreadAttr_t attr;
attr.name = HDF_SPI_TASK_NAME;
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = HDF_SPI_STACK_SIZE;
attr.priority = HDF_SPI_TASK_PRIORITY;
if (osThreadNew((osThreadFunc_t)HdfSpiTestEntry, NULL, &attr) == NULL) {
printf("Failed to create thread1!\n");
}
}
OHOS_APP_RUN(StartHdfSpiTest);