hpm使用笔记————使用usb作为从机接收来自上位机的数据然后通过spi主机发送给spi从机
历程整合
- 环境
- 要求
- 任务需求
- 任务实现
- 代码实现
- 任务测试
- 功能测试
- 结束
环境
- hpm_sdk v 1.7.0
- ses v8.10
要求
例程demo USB-CDC 作为从机接收,然后把接收到的数据转发给SPI,SPI传输出去
任务需求
-
USB使用cherry协议栈进行开发
-
作为device设备(从机)
-
CDC–> 虚拟串口 然后通过spi 协议 去发送
-
spi 主机\从机—>进行发送
任务实现
-
cherryusb CDC 虚拟串口
-
确定使用cherryusb协议栈进行开发(轻量化)
从sdk中构建usb cdc 虚拟串口历程
串口13接收数据然后发送给spi spi 主机转发,从机接收
-
SPI \主机\从机
-
使用历程中的spi协议进行测试
发送/接收
代码实现
main.c
/*
* Copyright (c) 2022 HPMicro
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdio.h>
#include "board.h"
#include "hpm_debug_console.h"
#include "usb_config.h"
#include "hpm_spi_drv.h"
#include "hpm_clock_drv.h"
#define LED_FLASH_PERIOD_IN_MS 300
extern volatile bool dtr_enable;
extern void cdc_acm_init(uint8_t busid, uint32_t reg_base);
extern void cdc_acm_data_send_with_dtr_test(uint8_t busid);
extern uint8_t read_buffer[512]; /* vcom接收的数组 */
/**************************************************************/
spi_timing_config_t timing_config = {0};
spi_format_config_t format_config = {0};
spi_control_config_t control_config = {0};
hpm_stat_t stat;
uint8_t wbuff[10] ;//= {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9};
uint8_t rbuff[10] = {0};
void spi_init(void){
uint32_t spi_clcok;
spi_clcok = board_init_spi_clock(BOARD_APP_SPI_BASE);
board_init_spi_pins(BOARD_APP_SPI_BASE);
printf("SPI-Master Polling Transfer Example\n");
/* set SPI sclk frequency for master */
spi_master_get_default_timing_config(&timing_config);
timing_config.master_config.clk_src_freq_in_hz = spi_clcok;
timing_config.master_config.sclk_freq_in_hz = BOARD_APP_SPI_SCLK_FREQ;
if (status_success != spi_master_timing_init(BOARD_APP_SPI_BASE, &timing_config)) {
printf("SPI master timming init failed\n");
while (1) {
}
}
/* set SPI format config for master */
spi_master_get_default_format_config(&format_config);
format_config.common_config.data_len_in_bits = BOARD_APP_SPI_DATA_LEN_IN_BITS;
format_config.common_config.mode = spi_master_mode;
format_config.common_config.cpol = spi_sclk_high_idle;
format_config.common_config.cpha = spi_sclk_sampling_even_clk_edges;
spi_format_init(BOARD_APP_SPI_BASE, &format_config);
printf("SPI-Master transfer format is configured.\n");
/* set SPI control config for master */
spi_master_get_default_control_config(&control_config);
control_config.master_config.cmd_enable = false; /* cmd phase control for master */
control_config.master_config.addr_enable = false; /* address phase control for master */
control_config.common_config.trans_mode = spi_trans_write_read_together;
}
extern uint8_t read_buffer[512];
void func_spi_write_data(uint8_t *data_Array,uint32_t bytes){
#if 1
stat = spi_transfer(BOARD_APP_SPI_BASE,
&control_config,
NULL, NULL,
(uint8_t *)read_buffer, 10, (uint8_t *)rbuff, ARRAY_SIZE(rbuff));
#else
stat = spi_transfer(BOARD_APP_SPI_BASE,
&control_config,
NULL, NULL,
(uint8_t * )data_Array, bytes, NULL,NULL);
for(int i = 0 ;i< sizeof(data_Array); i++)
{
printf("%d\n",data_Array[i]);
}
#endif /* 0 */
}
int main(void)
{
board_init();
spi_init();
board_init_led_pins();
board_init_usb_pins();
intc_set_irq_priority(CONFIG_HPM_USBD_IRQn, 2);
board_timer_create(LED_FLASH_PERIOD_IN_MS, board_led_toggle);
printf("cherry usb cdc_acm device sample.\n");
cdc_acm_init(0, CONFIG_HPM_USBD_BASE);
while(1) {
}
return 0;
}
/**************************************************************/
cherryusb_cdc.c
/*
* Copyright (c) 2022-2023 HPMicro
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x01
#define CDC_INT_EP 0x83
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor_hs[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_HS, 0x02),
};
static const uint8_t config_descriptor_fs[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_FS, 0x02),
};
static const uint8_t device_quality_descriptor[] = {
USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, 0x01),
};
static const uint8_t other_speed_config_descriptor_hs[] = {
USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_FS, 0x02),
};
static const uint8_t other_speed_config_descriptor_fs[] = {
USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_HS, 0x02),
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"HPMicro", /* Manufacturer */
"HPMicro CDC DEMO", /* Product */
"2024051702", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
(void)speed;
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
if (speed == USB_SPEED_HIGH) {
return config_descriptor_hs;
} else if (speed == USB_SPEED_FULL) {
return config_descriptor_fs;
} else {
return NULL;
}
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
(void)speed;
return device_quality_descriptor;
}
static const uint8_t *other_speed_config_descriptor_callback(uint8_t speed)
{
if (speed == USB_SPEED_HIGH) {
return other_speed_config_descriptor_hs;
} else if (speed == USB_SPEED_FULL) {
return other_speed_config_descriptor_fs;
} else {
return NULL;
}
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
(void)speed;
if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.other_speed_descriptor_callback = other_speed_config_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback,
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[512];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
volatile bool dtr_enable;
volatile bool ep_tx_busy_flag;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, &read_buffer[0], usbd_get_ep_mps(busid, CDC_OUT_EP));
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
extern void func_spi_write_data(uint8_t *data_Array, uint32_t bytes);
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(busid, ep, &read_buffer[0], usbd_get_ep_mps(busid, ep));
func_spi_write_data(read_buffer, nbytes);
usbd_ep_start_write(busid, CDC_IN_EP, &read_buffer[0], nbytes);
}
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, ep, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
}
/*!< endpoint call back */
struct usbd_endpoint cdc_out_ep = {
.ep_addr = CDC_OUT_EP,
.ep_cb = usbd_cdc_acm_bulk_out
};
struct usbd_endpoint cdc_in_ep = {
.ep_addr = CDC_IN_EP,
.ep_cb = usbd_cdc_acm_bulk_in
};
static struct usbd_interface intf0;
static struct usbd_interface intf1;
/* function ------------------------------------------------------------------*/
void cdc_acm_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(busid, &cdc_descriptor);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
(void)busid;
(void)intf;
if (dtr) {
dtr_enable = 1;
}
}
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
ep_tx_busy_flag = true;
write_buffer[0] = 'h';
write_buffer[1] = 'p';
write_buffer[2] = 'm';
write_buffer[3] = 'i';
write_buffer[4] = 'c';
write_buffer[5] = 'r';
write_buffer[6] = 'o';
write_buffer[7] = 0x0D;
write_buffer[8] = 0x0A;
memset(&write_buffer[9], 'a', 2037);
write_buffer[2046] = 0x0D;
write_buffer[2047] = 0x0A;
usbd_ep_start_write(busid, CDC_IN_EP, &write_buffer[0], 2048);
while (ep_tx_busy_flag) {
}
}
任务测试
功能测试
-
cherryusb 虚拟串口测试
- 虚拟串口收发数据
-
hpm_spi主机从机收发测试
- 主机给从机发送数据,从机可以接收到数据
-
整合工程,通过usb虚拟的串口接收来自上位机的数据,然后通过spi主机发送给spi从机
- 测试🆗