STM32F407移植TinyUSB

可以使用标准库进行移植,但使用cubemx移植更加方便,我这里就使用stm32cubemx进行移植了,首先新建工程,配置RCC,


配置定时器产生1ms中断个tinyusb使用,

开启更新中断


配置USB为设备模式,但是不要选择类,后续由tinyusb接管

开启中断

修改USB中断优先级


配置系统时钟


点击右上角生成代码


打开工程编译后0报错即可开始下一步

从官网下载tinyusb源码放入工程中,

打开魔法笔勾选GNU extensions


然后新建分组添加源码


然后配置文件路径,再次打开魔法棒选择tinyusb的src路径,根据自己路径来


然后需要移植config文件作为配置文件,我们从官方示例中移植修改,先导航到一个基础示例

我们把这个配置文件放到inc,

然后添加到工程中

打开文件,添加这两行代码,这里是配置哪个板子,配置为设备模式和全速模式

把这个配置从2改为1

修改这个配置

并在结尾之前添加

修改buff大小

删除这三行因为上面已经判断了


然后开始解决编译器问题,要排除armgcc选项,打开这个文件

找到#if defined(GNUC) || defined(ICCARM) || defined(TI_COMPILER_VERSION)改为

复制代码
#if (defined(__GNUC__) && !defined(__CC_ARM)) || defined(__ICCARM__) || defined(__TI_COMPILER_VERSION__)

在#elif defined(CCRX)分支之后,#else之前新增分支,

复制代码
#elif defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000)
  // Keil armcc (AC5): supports GNU-style attributes subset, no __has_attribute/__builtin_bswap*
  #define TU_ATTR_ALIGNED(Bytes)    __attribute__((aligned(Bytes)))
  #define TU_ATTR_SECTION(sec_name) __attribute__((section(#sec_name)))
  #define TU_ATTR_PACKED            __attribute__((packed))
  #define TU_ATTR_WEAK              __attribute__((weak))
  #ifndef TU_ATTR_ALWAYS_INLINE
    #define TU_ATTR_ALWAYS_INLINE
  #endif
  #define TU_ATTR_DEPRECATED(mess)      __attribute__((deprecated))
  #define TU_ATTR_UNUSED                __attribute__((unused))
  #define TU_ATTR_USED                  __attribute__((used))
  #define TU_ATTR_FALLTHROUGH           do {} while (0)

  #define TU_ATTR_PACKED_BEGIN
  #define TU_ATTR_PACKED_END
  #define TU_ATTR_BIT_FIELD_ORDER_BEGIN
  #define TU_ATTR_BIT_FIELD_ORDER_END

  // ARM Cortex-M is little-endian
  #define TU_BYTE_ORDER    TU_LITTLE_ENDIAN
  #define TU_BITFIELD_ORDER TU_BITFIELD_LE

  // Portable C implementation (compiler optimizes to REV/REV16 instructions)
  #define TU_BSWAP16(u16) (uint16_t)(((uint16_t)(u16) >> 8) | ((uint16_t)(u16) << 8))
  #define TU_BSWAP32(u32) ((((uint32_t)(u32) & 0xFF000000u) >> 24) | \
                           (((uint32_t)(u32) & 0x00FF0000u) >> 8)  | \
                           (((uint32_t)(u32) & 0x0000FF00u) << 8)  | \
                           (((uint32_t)(u32) & 0x000000FFu) << 24))

然后需要新建一个usb_descriptors.c文件,位置可以放在之前config的位置,内容如下

复制代码
#include "tusb.h"

#define USB_VID   0xCafe
#define USB_PID   0x4001
#define USB_BCD   0x0200

//--------------------------------------------------------------------+
// Device Descriptor
//--------------------------------------------------------------------+
static tusb_desc_device_t const desc_device = {
    .bLength            = sizeof(tusb_desc_device_t),
    .bDescriptorType    = TUSB_DESC_DEVICE,
    .bcdUSB             = USB_BCD,

    .bDeviceClass       = TUSB_CLASS_MISC,
    .bDeviceSubClass    = MISC_SUBCLASS_COMMON,
    .bDeviceProtocol    = MISC_PROTOCOL_IAD,
    .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,

    .idVendor           = USB_VID,
    .idProduct          = USB_PID,
    .bcdDevice          = 0x0100,

    .iManufacturer      = 0x01,
    .iProduct           = 0x02,
    .iSerialNumber      = 0x03,

    .bNumConfigurations = 0x01
};

uint8_t const *tud_descriptor_device_cb(void) {
    return (uint8_t const *) &desc_device;
}

//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
enum {
    ITF_NUM_CDC = 0,
    ITF_NUM_CDC_DATA,
    ITF_NUM_TOTAL
};

#define EPNUM_CDC_NOTIF   0x81
#define EPNUM_CDC_OUT     0x02
#define EPNUM_CDC_IN      0x82

#define CONFIG_TOTAL_LEN  (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)

static uint8_t const desc_fs_configuration[] = {
    TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
    TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
};

uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
    (void) index;
    return desc_fs_configuration;
}

//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
static char const *string_desc_arr[] = {
    (const char[]) { 0x09, 0x04 },  // 0: English (0x0409)
    "TinyUSB",                       // 1: Manufacturer
    "STM32F407 CDC",                 // 2: Product
    "1234567890ABCDEF",              // 3: Serial
    "TinyUSB CDC",                   // 4: CDC Interface
};

static uint16_t _desc_str[32 + 1];

uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
    (void) langid;
    size_t chr_count;

    switch (index) {
        case 0:
            memcpy(&_desc_str[1], string_desc_arr[0], 2);
            chr_count = 1;
            break;

        default:
            if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) {
                return NULL;
            }
            const char *str = string_desc_arr[index];
            chr_count = strlen(str);
            size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1;
            if (chr_count > max_count) chr_count = max_count;
            for (size_t i = 0; i < chr_count; i++) {
                _desc_str[1 + i] = str[i];
            }
            break;
    }

    _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
    return _desc_str;
}

然后开始修改main.c,首先添加头文件

复制代码
#include "tusb.h"
#include <stdio.h>
#include <stdarg.h>

添加全局变量volatile uint32_t g_usb_millis = 0;

然后启动定时器并对tinyusb进行初始化

复制代码
  HAL_TIM_Base_Start_IT(&htim1);  // start TIM1 1ms time base before tusb_init
  tusb_rhport_init_t dev_init = { .role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_FULL };
  tusb_init(BOARD_TUD_RHPORT, &dev_init);

然后在底部实现

复制代码
uint32_t tusb_time_millis_api(void) {
  return g_usb_millis;
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
  if (htim->Instance == TIM1) {
    g_usb_millis++;
  }
}

main的while调用

复制代码
    tud_task();
    uint8_t b; while (tud_cdc_available()) { tud_cdc_read(&b, 1); tud_cdc_write_char(b); } tud_cdc_write_flush();
相关推荐
Dlrb12111 小时前
Linux驱动---Linux 中断系统及其上与下半部的介绍与阻塞IO实现按键检测
linux·嵌入式硬件·imx6ull·中断·阻塞io
国产HT1621B2 小时前
YL4056 NTC 外围电阻 R3/R4 计算:从公式推导到工程选型
科技·单片机·嵌入式硬件
czhaii3 小时前
STC32G144K246 Ai8052单片机外设和功能
单片机·硬件工程
唔好理总之好犀利4 小时前
TVS管分析:MKS烧保险丝异常分析
stm32·单片机·嵌入式硬件
Dr.kangder5 小时前
嵌入式处理器虚拟化仿真技术(九)——SimpleScalar原理与应用
嵌入式硬件·架构·嵌入式·虚拟化·仿真
芯片设计-曾工14 小时前
当精准脉冲遇上清晰视界——CH2205E模块与YL1621的“黄金搭档“
驱动开发·stm32·单片机·51单片机·硬件工程
LCG元19 小时前
STM32 硬件 SPI + DMA 驱动 OLED 显示屏(SSD1306):从原理到 112fps 高速刷新全流程
stm32·单片机·嵌入式硬件
天吾cc20 小时前
RTT-ADC
单片机·嵌入式硬件·学习
qq_4480111620 小时前
C语言中的野指针和空指针
c语言·开发语言·单片机