================================================
FILE: examples/device/webusb_serial/website/serial.js
================================================
'use strict';
/// Web Serial API Implementation
/// https://developer.mozilla.org/en-US/docs/Web/API/SerialPort
class SerialPort {
constructor(port) {
this._port = port;
this._readLoopPromise = null;
this._reader = null;
this._writer = null;
this._initialized = false;
this._keepReading = true;
this.isConnected = false;
}
/// Connect and start reading loop
async connect(options = { baudRate: 9600 }) {
if (this._initialized) {
try {
await this.disconnect();
} catch (error) {
console.error('Error disconnecting previous port:', error);
}
if (this._readLoopPromise) {
try {
await this._readLoopPromise;
} catch (error) {
console.error('Error in read loop:', error);
}
}
this._readLoopPromise = null;
}
this._initialized = true;
this.isConnected = true;
this._keepReading = true;
try {
await this._port.open(options);
} catch (error) {
this.isConnected = false;
throw error;
}
this._readLoopPromise = this._readLoop();
}
/// Internal continuous read loop
async _readLoop() {
try {
while (this._port.readable && this._keepReading) {
this._reader = this._port.readable.getReader();
try {
while (true) {
const { value, done } = await this._reader.read();
if (done) {
// |reader| has been canceled.
break;
}
if (this.onReceive) {
this.onReceive(value);
}
}
} catch (error) {
if (this.onReceiveError) this.onReceiveError(error);
} finally {
this._reader.releaseLock();
}
}
} finally {
this.isConnected = false;
await this._port.close();
}
}
/// Stop reading and release port
async disconnect() {
this._keepReading = false;
if (this._reader) {
try {
await this._reader.cancel();
} catch (error) {
console.error('Error cancelling reader:', error);
}
this._reader.releaseLock();
}
if (this._writer) {
try {
await this._writer.abort();
} catch (error) {
console.error('Error closing writer:', error);
}
this._writer.releaseLock();
}
try {
await this._port.close();
} catch (error) {
console.error('Error closing port:', error);
}
if (this._readLoopPromise) {
try {
await this._readLoopPromise;
} catch (error) {
console.error('Error in read loop:', error);
}
}
}
/// Send data to port
send(data) {
if (!this._port.writable) {
throw new Error('Port is not writable');
}
this._writer = this._port.writable.getWriter();
if (!this._writer) {
throw new Error('Failed to get writer from port');
}
try {
return this._writer.write(data);
} finally {
this._writer.releaseLock();
}
}
async forgetDevice() {}
}
/// WebUSB Implementation
class WebUsbSerialPort {
constructor(device) {
this._device = device;
this._interfaceNumber = 0;
this._endpointIn = 0;
this._endpointOut = 0;
this.isConnected = false;
this._readLoopPromise = null;
this._initialized = false;
this._keepReading = true;
this._vendorId = device.vendorId;
this._productId = device.productId;
}
_isSameWebUsbSerialPort(webUsbSerialPort) {
return this._vendorId === webUsbSerialPort._vendorId && this._productId === webUsbSerialPort._productId;
}
/// Connect and start reading loop
async connect() {
if (this._initialized) {
try {
await this.disconnect();
} catch (error) {
console.error('Error disconnecting previous device:', error);
}
const webUsbSerialPorts = await serial.getWebUsbSerialPorts();
const webUsbSerialPort = webUsbSerialPorts.find(serialPort => this._isSameWebUsbSerialPort(serialPort));
this._device = webUsbSerialPort ? webUsbSerialPort._device : this._device;
}
this._initialized = true;
this.isConnected = true;
this._keepReading = true;
try {
await this._device.open();
if (!this._device.configuration) {
await this._device.selectConfiguration(1);
}
// Find interface with vendor-specific class (0xFF) and endpoints
for (const iface of this._device.configuration.interfaces) {
for (const alternate of iface.alternates) {
if (alternate.interfaceClass === 0xff) {
this._interfaceNumber = iface.interfaceNumber;
for (const endpoint of alternate.endpoints) {
if (endpoint.direction === 'out') this._endpointOut = endpoint.endpointNumber;
else if (endpoint.direction === 'in') this._endpointIn = endpoint.endpointNumber;
}
}
}
}
if (this._interfaceNumber === undefined) {
throw new Error('No suitable interface found.');
}
await this._device.claimInterface(this._interfaceNumber);
await this._device.selectAlternateInterface(this._interfaceNumber, 0);
// Set device to ENABLE (0x22 = SET_CONTROL_LINE_STATE, value 0x01 = activate)
await this._device.controlTransferOut({
requestType: 'class',
recipient: 'interface',
request: 0x22,
value: 0x01,
index: this._interfaceNumber,
});
} catch (error) {
this.isConnected = false;
throw error;
}
this._readLoopPromise = this._readLoop();
}
/// Internal continuous read loop
async _readLoop() {
try {
while (this._keepReading && this.isConnected) {
try {
const result = await this._device.transferIn(this._endpointIn, 16384);
if (result.data && this.onReceive) {
this.onReceive(result.data);
}
} catch (error) {
this.isConnected = false;
if (this.onReceiveError) {
this.onReceiveError(error);
}
}
}
} finally {
this.isConnected = false;
await this._device.close();
}
}
/// Stop reading and release device
async disconnect() {
this._keepReading = false;
try {
await this._device.controlTransferOut({
requestType: 'class',
recipient: 'interface',
request: 0x22,
value: 0x00,
index: this._interfaceNumber,
});
} catch (error) {
console.error('Error sending control transfer:', error);
}
await this._device.releaseInterface(this._interfaceNumber);
if (this._readLoopPromise) {
try {
await this._readLoopPromise;
} catch (error) {
console.error('Error in read loop:', error);
}
}
}
/// Send data to device
send(data) {
return this._device.transferOut(this._endpointOut, data);
}
async forgetDevice() {
await this.disconnect();
await this._device.forget();
}
}
// Utility Functions
const serial = {
isWebSerialSupported: () => 'serial' in navigator,
isWebUsbSupported: () => 'usb' in navigator,
async getSerialPorts() {
if (!this.isWebSerialSupported()) return [];
const ports = await navigator.serial.getPorts();
return ports.map(port => new SerialPort(port));
},
async getWebUsbSerialPorts() {
if (!this.isWebUsbSupported()) return [];
const devices = await navigator.usb.getDevices();
return devices.map(device => new WebUsbSerialPort(device));
},
async requestSerialPort() {
const port = await navigator.serial.requestPort();
return new SerialPort(port);
},
async requestWebUsbSerialPort() {
const filters = [
{ vendorId: 0xcafe }, // TinyUSB
{ vendorId: 0x239a }, // Adafruit
{ vendorId: 0x2e8a }, // Raspberry Pi
{ vendorId: 0x303a }, // Espressif
{ vendorId: 0x2341 }, // Arduino
];
const device = await navigator.usb.requestDevice({ filters });
return new WebUsbSerialPort(device);
}
};
================================================
FILE: examples/device/webusb_serial/website/style.css
================================================
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* Reset default margins and make html, body full height */
html,
body {
height: 100%;
font-family: sans-serif;
background: #f5f5f5;
color: #333;
}
body {
display: flex;
flex-direction: column;
height: 100vh;
}
/* Header row styling */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5em 1em;
gap: 1em;
flex-shrink: 0;
}
h1,
h2 {
margin: 0;
}
.app-title {
flex-grow: 1;
}
.btn-theme {
background-color: #6b6b6b;
color: #fff;
}
.github-link {
font-weight: 600;
}
/* Main is flex column */
main {
display: flex;
flex-direction: column;
flex: 1;
width: 100%;
}
/* Controls top row in main*/
.controls-section,
.status-section {
padding: 1rem;
flex-shrink: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 0.5rem;
}
/* Container for the two columns */
.io-container {
display: flex;
flex: 1;
/* fill remaining vertical space */
width: 100%;
overflow: hidden;
}
/* Both columns flex equally and full height */
.column {
flex: 1;
padding: 1rem;
display: flex;
flex-direction: column;
}
.heading-with-controls {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.command-history-entry {
all: unset;
display: flex;
flex-direction: row;
gap: 0.5rem;
background: none;
border: none;
border-bottom: 1px solid #ccc;
/* light gray line */
padding: 0.5rem 1rem;
margin: 0;
text-align: left;
cursor: pointer;
}
.command-history-entry:hover {
background-color: #f0f0f0;
}
.monospaced {
font-family: 'Courier New', Courier, monospace;
font-size: 1rem;
color: #333;
}
.scrollbox-wrapper {
position: relative;
padding: 0.5rem;
flex: 1;
display: block;
overflow: hidden;
}
.scrollbox {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow-y: auto;
overflow-x: auto;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
background-color: #fff;
border-radius: 0.5rem;
white-space: nowrap;
display: flex;
flex-direction: column;
align-items: stretch;
}
.send-container {
display: flex;
flex-direction: row;
gap: 0.5rem;
}
.send-mode-command {
background-color: lightgray;
/* light-gray */
}
.send-mode-instant {
background-color: blue;
}
.btn {
padding: 0.5rem 1rem;
font-size: 1rem;
border: none;
border-radius: 0.3rem;
cursor: pointer;
}
.good {
background-color: #2ecc71;
/* green */
color: #fff;
}
.danger {
background-color: #e74c3c;
/* red */
color: #fff;
}
.input {
width: 100%;
padding: 12px 16px;
font-size: 1rem;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
border: 2px solid #ddd;
border-radius: 8px;
background-color: #fafafa;
color: #333;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
outline: none;
box-sizing: border-box;
}
.input::placeholder {
color: #aaa;
font-style: italic;
}
.input:focus {
border-color: #0078d7;
box-shadow: 0 0 6px rgba(0, 120, 215, 0.5);
background-color: #fff;
}
.resizer {
width: 5px;
background-color: #ccc;
cursor: col-resize;
height: 100%;
}
/*
================================
Togglable Dark Mode
================================
*/
/* This class will be added to the body element by JavaScript */
body.dark-mode {
/* Invert base background and text colors */
background: #1e1e1e;
color: #d4d4d4;
}
body.dark-mode input[type="checkbox"] {
border-color: #888;
accent-color: #2e2e2e;
opacity: 0.8;
}
body.dark-mode .btn-theme {
background-color: #b0b0b0;
color: #000;
}
body.dark-mode .github-link {
color: #58a6ff;
}
body.dark-mode .resizer {
background-color: #444;
}
body.dark-mode .input {
background-color: #3c3c3c;
color: #f0f0f0;
border: 2px solid #555;
}
body.dark-mode .input::placeholder {
color: #888;
}
body.dark-mode .input:focus {
background-color: #2a2d2e;
border-color: #0078d7;
}
body.dark-mode .scrollbox {
background-color: #252526;
scrollbar-color: #555 #2e2e2e;
border: 1px solid #444;
}
body.dark-mode .monospaced {
color: #d4d4d4;
}
body.dark-mode .command-history-entry {
border-bottom: 1px solid #444;
}
body.dark-mode .command-history-entry:hover {
background-color: #3c3c3c;
}
body.dark-mode .send-mode-command {
background-color: #555;
color: #f5f5f5;
}
body.dark-mode select {
background-color: #3c3c3c;
color: #f0f0f0;
border: 2px solid #555;
}
body.dark-mode select:focus {
background-color: #2a2d2e;
border-color: #0078d7;
outline: none;
}
body.dark-mode option {
background-color: #3c3c3c;
color: #f0f0f0;
}
================================================
FILE: examples/dual/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
project(tinyusb_dual_examples C CXX ASM)
family_initialize_project(tinyusb_dual_examples ${CMAKE_CURRENT_LIST_DIR})
if (FAMILY STREQUAL "rp2040" AND NOT TARGET tinyusb_pico_pio_usb)
message("Skipping dual host/device mode examples as Pico-PIO-USB is not available")
else ()
# family_add_subdirectory will filter what to actually add based on selected FAMILY
set(EXAMPLE_LIST
host_hid_to_device_cdc
host_info_to_device_cdc
dynamic_switch
)
foreach (example ${EXAMPLE_LIST})
family_add_subdirectory(${example})
endforeach ()
endif ()
================================================
FILE: examples/dual/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/dual/dynamic_switch/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(dynamic_switch C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_dual_usb_example(${PROJECT_NAME} noos)
================================================
FILE: examples/dual/dynamic_switch/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/dual/dynamic_switch/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += $(wildcard src/*.c)
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
# Include device and host stack
SRC_C += \
src/class/cdc/cdc_device.c \
src/host/hub.c \
src/host/usbh.c
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/dual/dynamic_switch/README.md
================================================
# Dynamic Switch Example
This example demonstrates TinyUSB's dual-role capability by allowing runtime switching between USB device and host modes.
## Features
- **Button-triggered mode switching**: Press the board button to switch between device and host modes
- **Device Mode**: Acts as a USB CDC (Virtual Serial Port) that echoes all received data
- **Host Mode**: Enumerates connected USB devices and prints device information
- **Dynamic switching**: Deinitializes the current stack and reinitializes in the new mode
## Usage
1. **Build and flash** the example to your board
2. **Default behavior**: The board starts in **Device mode**
3. **Device mode**:
- Connect the board to a PC
- Open a serial terminal (e.g., `screen /dev/ttyACM0` or PuTTY)
- Type characters - they will be echoed back to you
4. **Switch to Host mode**:
- Press the board button
- Connect a USB device to the board
- The board will enumerate the device and print its descriptors to the debug console
5. **Switch back to Device mode**: Press the button again
## LED Patterns
The onboard LED indicates the USB connection status:
- **Fast blink (250ms)**: Not mounted/connected
- **Slow blink (1000ms)**: Successfully mounted/connected
- **Very slow blink (2500ms)**: Suspended (device mode only)
## Serial Output
The example prints status messages to the debug UART:
```
======================================
TinyUSB Dynamic Switch Example
Press button to switch between device and host modes
Starting in DEVICE mode...
======================================
[DEVICE] Mounted
--- Switching USB mode ---
Stopping DEVICE mode...
Starting HOST mode...
Mode switch complete!
[HOST] Device attached, address = 1
Device 1: ID 1234:5678 SN ABC123
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 0200
bDeviceClass 239
...
```
================================================
FILE: examples/dual/dynamic_switch/only.txt
================================================
family:espressif
mcu:LPC43XX
mcu:MIMXRT1XXX
mcu:STM32C0
mcu:STM32G0
mcu:STM32H5
mcu:STM32F2
mcu:STM32F4
mcu:STM32U5
mcu:STM32F7
mcu:STM32H7
mcu:STM32H7RS
================================================
FILE: examples/dual/dynamic_switch/src/CMakeLists.txt
================================================
# This file is for ESP-IDF only
idf_component_register(SRCS "main.c" "usb_descriptors.c"
INCLUDE_DIRS "."
REQUIRES boards tinyusb_src)
================================================
FILE: examples/dual/dynamic_switch/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/* This example demonstrates dynamic switching between device and host modes:
* - Press button to switch between device and host modes
* - Device mode: CDC echo (echoes input back to output)
* - Host mode: Prints connected device information
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
#if CFG_TUSB_OS == OPT_OS_FREERTOS
#ifdef ESP_PLATFORM
#define USBD_STACK_SIZE 4096
#define USBH_STACK_SIZE 4096
#else
// Increase stack size when debug log is enabled
#define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
#define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
#endif
#define CDC_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1))
#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
#endif
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
// English
#define LANGUAGE_ID 0x0409
/* Blink pattern
* - 250 ms : not mounted
* - 1000 ms : mounted
* - 2500 ms : suspended
*/
enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
};
#if CFG_TUSB_OS == OPT_OS_FREERTOS
// static task for FreeRTOS
#if configSUPPORT_STATIC_ALLOCATION
StackType_t blinky_stack[BLINKY_STACK_SIZE];
StaticTask_t blinky_taskdef;
StackType_t usb_stack[USBD_STACK_SIZE > USBH_STACK_SIZE ? USBD_STACK_SIZE : USBH_STACK_SIZE];
StaticTask_t usb_taskdef;
StackType_t cdc_stack[CDC_STACK_SIZE];
StaticTask_t cdc_taskdef;
#endif
#endif
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
static tusb_role_t current_role = TUSB_ROLE_DEVICE;
#if CFG_TUSB_OS == OPT_OS_FREERTOS
static void usb_task(void *param);
void led_blinking_task(void *param);
void cdc_task(void *params);
#else
void led_blinking_task(void);
void cdc_task(void);
#endif
void usb_mode_switch(void);
static void print_device_info(uint8_t daddr);
static void print_utf16(uint16_t* temp_buf, size_t buf_len);
// Declare buffer for USB transfer
CFG_TUH_MEM_SECTION struct {
TUH_EPBUF_TYPE_DEF(tusb_desc_device_t, device);
TUH_EPBUF_DEF(serial, 64*sizeof(uint16_t));
TUH_EPBUF_DEF(buf, 128*sizeof(uint16_t));
} desc;
//--------------------------------------------------------------------+
// Main
//--------------------------------------------------------------------+
int main(void) {
board_init();
printf("\r\n======================================\r\n");
printf("TinyUSB Dynamic Switch Example\r\n");
printf("Press button to switch between device and host modes\r\n");
printf("Starting in DEVICE mode...\r\n");
printf("======================================\r\n\r\n");
#if CFG_TUSB_OS == OPT_OS_FREERTOS
// Create FreeRTOS tasks
#if configSUPPORT_STATIC_ALLOCATION
xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef);
xTaskCreateStatic(usb_task, "usb", USBD_STACK_SIZE > USBH_STACK_SIZE ? USBD_STACK_SIZE : USBH_STACK_SIZE,
NULL, configMAX_PRIORITIES-1, usb_stack, &usb_taskdef);
xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, cdc_stack, &cdc_taskdef);
#else
xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(usb_task, "usb", USBD_STACK_SIZE > USBH_STACK_SIZE ? USBD_STACK_SIZE : USBH_STACK_SIZE,
NULL, configMAX_PRIORITIES - 1, NULL);
xTaskCreate(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL);
#endif
#ifndef ESP_PLATFORM
// only start scheduler for non-espressif mcu
vTaskStartScheduler();
#endif
#else
// Initialize in device mode by default
tusb_rhport_init_t dev_init = {
.role = TUSB_ROLE_DEVICE,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_RHPORT, &dev_init);
current_role = TUSB_ROLE_DEVICE;
board_init_after_tusb();
while (1) {
// Check for button press to switch modes
static bool pending_switch = false;
if (board_button_read()) {
if (!pending_switch) {
pending_switch = true;
usb_mode_switch();
}
} else {
pending_switch = false;
}
// Process USB tasks based on current mode
if (current_role == TUSB_ROLE_DEVICE) {
tud_task();
cdc_task();
} else {
tuh_task();
}
led_blinking_task();
}
#endif
}
#ifdef ESP_PLATFORM
void app_main(void) {
main();
}
#endif
#if CFG_TUSB_OS == OPT_OS_FREERTOS
// USB Task for FreeRTOS
// This top level thread processes all usb events and mode switching
static void usb_task(void *param) {
(void) param;
// init device stack on configured roothub port
// This should be called after scheduler/kernel is started.
// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API.
tusb_rhport_init_t dev_init = {
.role = TUSB_ROLE_DEVICE,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_RHPORT, &dev_init);
current_role = TUSB_ROLE_DEVICE;
board_init_after_tusb();
// RTOS forever loop
while (1) {
// Check for button press to switch modes
static bool pending_switch = false;
if (board_button_read()) {
if (!pending_switch) {
pending_switch = true;
usb_mode_switch();
}
} else {
pending_switch = false;
}
// Process USB tasks based on current mode
// Use _ext version to allow return and read button state
if (current_role == TUSB_ROLE_DEVICE) {
tud_task_ext(10, false);
} else {
tuh_task_ext(10, false);
}
}
}
#endif
//--------------------------------------------------------------------+
// Mode Switching
//--------------------------------------------------------------------+
void usb_mode_switch(void) {
printf("\r\n--- Switching USB mode ---\r\n");
// Deinitialize current mode
if (current_role == TUSB_ROLE_DEVICE) {
printf("Stopping DEVICE mode...\r\n");
tusb_deinit(BOARD_RHPORT);
} else {
printf("Stopping HOST mode...\r\n");
tusb_deinit(BOARD_RHPORT);
}
#if CFG_TUSB_OS == OPT_OS_FREERTOS
vTaskDelay(pdMS_TO_TICKS(100)); // Small delay for clean transition
#else
tusb_time_delay_ms_api(100); // Small delay for clean transition
#endif // Switch to the other mode
if (current_role == TUSB_ROLE_DEVICE) {
printf("Starting HOST mode...\r\n");
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_RHPORT, &host_init);
current_role = TUSB_ROLE_HOST;
} else {
printf("Starting DEVICE mode...\r\n");
tusb_rhport_init_t dev_init = {
.role = TUSB_ROLE_DEVICE,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_RHPORT, &dev_init);
current_role = TUSB_ROLE_DEVICE;
}
blink_interval_ms = BLINK_NOT_MOUNTED;
printf("Mode switch complete!\r\n\r\n");
}
//--------------------------------------------------------------------+
// Device Mode: CDC Task
//--------------------------------------------------------------------+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
void cdc_task(void *params) {
(void) params;
// RTOS forever loop
while (1) {
// Only process CDC when in device mode
if (current_role == TUSB_ROLE_DEVICE) {
// Connected and there are data available
while (tud_cdc_available()) {
uint8_t buf[64];
// Read data
uint32_t count = tud_cdc_read(buf, sizeof(buf));
// Echo back
tud_cdc_write(buf, count);
// Add newline for carriage return
for (uint32_t i = 0; i < count; i++) {
if (buf[i] == '\r') {
tud_cdc_write_char('\n');
break;
}
}
}
tud_cdc_write_flush();
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
#else
void cdc_task(void) {
// Connected and there are data available
if (tud_cdc_available()) {
uint8_t buf[64];
// Read data
uint32_t count = tud_cdc_read(buf, sizeof(buf));
// Echo back
for (uint32_t i = 0; i < count; i++) {
tud_cdc_write_char(buf[i]);
if (buf[i] == '\r') {
tud_cdc_write_char('\n');
}
}
tud_cdc_write_flush();
}
}
#endif
//--------------------------------------------------------------------+
// Device Callbacks
//--------------------------------------------------------------------+
// Invoked when device is mounted
void tud_mount_cb(void) {
printf("[DEVICE] Mounted\r\n");
blink_interval_ms = BLINK_MOUNTED;
}
// Invoked when device is unmounted
void tud_umount_cb(void) {
printf("[DEVICE] Unmounted\r\n");
blink_interval_ms = BLINK_NOT_MOUNTED;
}
// Invoked when usb bus is suspended
void tud_suspend_cb(bool remote_wakeup_en) {
(void) remote_wakeup_en;
printf("[DEVICE] Suspended\r\n");
blink_interval_ms = BLINK_SUSPENDED;
}
// Invoked when usb bus is resumed
void tud_resume_cb(void) {
printf("[DEVICE] Resumed\r\n");
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
// Host Callbacks
//--------------------------------------------------------------------+
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
printf("[HOST] Device attached, address = %d\r\n", daddr);
blink_interval_ms = BLINK_MOUNTED;
print_device_info(daddr);
}
// Invoked when device is unmounted (unplugged)
void tuh_umount_cb(uint8_t daddr) {
printf("[HOST] Device removed, address = %d\r\n", daddr);
blink_interval_ms = BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
// Host Device Info
//--------------------------------------------------------------------+
static void print_device_info(uint8_t daddr) {
// Get Device Descriptor
uint8_t xfer_result = tuh_descriptor_get_device_sync(daddr, &desc.device, 18);
if (XFER_RESULT_SUCCESS != xfer_result) {
printf("Failed to get device descriptor\r\n");
return;
}
printf("Device %u: ID %04x:%04x SN ", daddr, desc.device.idVendor, desc.device.idProduct);
xfer_result = XFER_RESULT_FAILED;
if (desc.device.iSerialNumber != 0) {
xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial));
}
if (XFER_RESULT_SUCCESS != xfer_result) {
uint16_t* serial = (uint16_t*)(uintptr_t) desc.serial;
serial[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * 3 + 2));
serial[1] = 'n';
serial[2] = '/';
serial[3] = 'a';
serial[4] = 0;
}
print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2);
printf("\r\n");
printf("Device Descriptor:\r\n");
printf(" bLength %u\r\n", desc.device.bLength);
printf(" bDescriptorType %u\r\n", desc.device.bDescriptorType);
printf(" bcdUSB %04x\r\n", desc.device.bcdUSB);
printf(" bDeviceClass %u\r\n", desc.device.bDeviceClass);
printf(" bDeviceSubClass %u\r\n", desc.device.bDeviceSubClass);
printf(" bDeviceProtocol %u\r\n", desc.device.bDeviceProtocol);
printf(" bMaxPacketSize0 %u\r\n", desc.device.bMaxPacketSize0);
printf(" idVendor 0x%04x\r\n", desc.device.idVendor);
printf(" idProduct 0x%04x\r\n", desc.device.idProduct);
printf(" bcdDevice %04x\r\n", desc.device.bcdDevice);
// Get Manufacturer string
if (desc.device.iManufacturer) {
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf))) {
printf(" iManufacturer %u ", desc.device.iManufacturer);
print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
printf("\r\n");
}
}
// Get Product string
if (desc.device.iProduct) {
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf))) {
printf(" iProduct %u ", desc.device.iProduct);
print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
printf("\r\n");
}
}
// Get Serial string
if (desc.device.iSerialNumber) {
printf(" iSerialNumber %u ", desc.device.iSerialNumber);
print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2);
printf("\r\n");
} else {
printf(" iSerialNumber 0\r\n");
}
printf(" bNumConfigurations %u\r\n", desc.device.bNumConfigurations);
printf("\r\n");
}
static void print_utf16(uint16_t* temp_buf, size_t buf_len) {
if (temp_buf[0] == 0 || (temp_buf[0] >> 8) != TUSB_DESC_STRING) {
printf("(invalid)");
return;
}
size_t chr_count = (temp_buf[0] & 0xff) / 2 - 1;
if (chr_count > buf_len - 1) {
chr_count = buf_len - 1;
}
for (size_t i = 0; i < chr_count; i++) {
uint16_t ch = temp_buf[1 + i];
if (ch <= 0x7F) {
putchar((char) ch);
} else {
// TODO support UTF16 to UTF8 conversion
putchar('?');
}
}
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
void led_blinking_task(void *param) {
(void) param;
static bool led_state = false;
// RTOS forever loop
while (1) {
board_led_write(led_state);
led_state = 1 - led_state; // toggle
vTaskDelay(pdMS_TO_TICKS(blink_interval_ms));
}
}
#else
void led_blinking_task(void) {
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if (tusb_time_millis_api() - start_ms < blink_interval_ms) {
return; // not enough time
}
start_ms += blink_interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
#endif
================================================
FILE: examples/dual/dynamic_switch/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef _TUSB_CONFIG_H_
#define _TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// Board Specific Configuration
//--------------------------------------------------------------------+
// RHPort number used can be defined by board.mk, default to port 0
#ifndef BOARD_RHPORT
#if defined(BOARD_TUD_RHPORT)
#define BOARD_RHPORT BOARD_TUD_RHPORT
#else
#define BOARD_RHPORT 0
#define BOARD_TUD_RHPORT 0
#endif
#endif
#if defined(BOARD_TUH_RHPORT)
#if BOARD_TUH_RHPORT != BOARD_RHPORT
#undef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT BOARD_RHPORT
#endif
#else
#define BOARD_TUH_RHPORT BOARD_RHPORT
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_MAX_SPEED
#if defined(BOARD_TUD_MAX_SPEED)
#define BOARD_MAX_SPEED BOARD_TUD_MAX_SPEED
#else
#define BOARD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
#endif
//--------------------------------------------------------------------
// COMMON CONFIGURATION
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
// Enable Device and Host stacks (dual role)
#define CFG_TUD_ENABLED 1
#define CFG_TUH_ENABLED 1
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUD_MAX_SPEED BOARD_MAX_SPEED
#define CFG_TUH_MAX_SPEED BOARD_MAX_SPEED
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUD_MEM_SECTION
#define CFG_TUD_MEM_SECTION
#endif
#ifndef CFG_TUD_MEM_ALIGN
#define CFG_TUD_MEM_ALIGN __attribute__((aligned(4)))
#endif
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION CFG_TUD_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN CFG_TUD_MEM_ALIGN
#endif
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 0
#define CFG_TUD_HID 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
//--------------------------------------------------------------------
// HOST CONFIGURATION
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 1
// max device support (excluding hub device)
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
#define CFG_TUH_CDC 0
#define CFG_TUH_HID 0
#define CFG_TUH_MSC 0
#define CFG_TUH_VENDOR 0
// max endpoint pair supported by each device
#define CFG_TUH_ENDPOINT_MAX 16
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_CONFIG_H_ */
================================================
FILE: examples/dual/dynamic_switch/src/usb_descriptors.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB]
*/
#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0)
#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \
PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4))
#define USB_VID 0xCafe
#define USB_BCD 0x0200
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
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
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
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
};
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
#elif defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY)
// MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x83
#else
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
#endif
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
static uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
};
#if TUD_OPT_HIGH_SPEED
static uint8_t const desc_hs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
};
#endif
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
#if TUD_OPT_HIGH_SPEED
// Although we are highspeed, host may be fullspeed.
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
#else
return desc_fs_configuration;
#endif
}
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
// String Descriptor Index
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
};
// array of pointer to string descriptors
static char const *string_desc_arr[] = {
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
NULL, // 3: Serials, will use unique ID if possible
"TinyUSB CDC", // 4: CDC Interface
};
static uint16_t _desc_str[32 + 1];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
(void) langid;
size_t chr_count;
switch (index) {
case STRID_LANGID:
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
break;
case STRID_SERIAL:
chr_count = board_usb_get_serial(_desc_str + 1, 32);
break;
default:
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { return NULL; }
const char *str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
if (chr_count > max_count) { chr_count = max_count; }
// Convert ASCII string into UTF-16
for (size_t i = 0; i < chr_count; i++) {
_desc_str[1 + i] = str[i];
}
break;
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
================================================
FILE: examples/dual/host_hid_to_device_cdc/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(host_hid_to_device_cdc C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_dual_usb_example(${PROJECT_NAME} noos)
# due to warnings from Pico-PIO-USB
if (FAMILY STREQUAL rp2040)
target_compile_options(${PROJECT_NAME} PUBLIC
-Wno-error=shadow
-Wno-error=cast-align
-Wno-error=cast-qual
-Wno-error=redundant-decls
-Wno-error=sign-conversion
-Wno-error=conversion
-Wno-error=sign-compare
-Wno-error=unused-function
)
endif ()
================================================
FILE: examples/dual/host_hid_to_device_cdc/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/dual/host_hid_to_device_cdc/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += $(wildcard src/*.c)
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference
SRC_C += \
src/class/hid/hid_host.c \
src/host/hub.c \
src/host/usbh.c
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/dual/host_hid_to_device_cdc/only.txt
================================================
board:mimxrt1060_evk
board:mimxrt1064_evk
board:mcb1800
mcu:CH32V20X
mcu:RP2040
mcu:ra6m5
mcu:MAX3421
mcu:STM32F4
mcu:STM32F7
mcu:STM32H7
================================================
FILE: examples/dual/host_hid_to_device_cdc/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
// This example runs both host and device concurrently. The USB host receive
// reports from HID device and print it out over USB Device CDC interface.
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
// uncomment if you are using colemak layout
// #define KEYBOARD_COLEMAK
#ifdef KEYBOARD_COLEMAK
const uint8_t colemak[128] = {
0 , 0, 0, 0, 0, 0, 0, 22,
9 , 23, 7, 0, 24, 17, 8, 12,
0 , 14, 28, 51, 0, 19, 21, 10,
15 , 0, 0, 0, 13, 0, 0, 0,
0 , 0, 0, 0, 0, 0, 0, 0,
0 , 0, 0, 0, 0, 0, 0, 0,
0 , 0, 0, 18, 0, 0, 0, 0,
0 , 0, 0, 0, 0, 0, 0, 0,
0 , 0, 0, 0, 0, 0, 0, 0,
0 , 0, 0, 0, 0, 0, 0, 0
};
#endif
static uint8_t const keycode2ascii[128][2] = {HID_KEYCODE_TO_ASCII};
/* Blink pattern
* - 250 ms : device not mounted
* - 1000 ms : device mounted
* - 2500 ms : device is suspended
*/
enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
};
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
void led_blinking_task(void);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Host HID <-> Device CDC Example\r\n");
// init device and host stack on configured roothub port
tusb_rhport_init_t dev_init = {
.role = TUSB_ROLE_DEVICE,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUD_RHPORT, &dev_init);
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
board_init_after_tusb();
while (1) {
tud_task(); // tinyusb device task
tuh_task(); // tinyusb host task
led_blinking_task();
}
}
//--------------------------------------------------------------------+
// Device CDC
//--------------------------------------------------------------------+
// Invoked when device is mounted
void tud_mount_cb(void) {
blink_interval_ms = BLINK_MOUNTED;
}
// Invoked when device is unmounted
void tud_umount_cb(void) {
blink_interval_ms = BLINK_NOT_MOUNTED;
}
// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en) {
(void) remote_wakeup_en;
blink_interval_ms = BLINK_SUSPENDED;
}
// Invoked when usb bus is resumed
void tud_resume_cb(void) {
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
// Invoked when CDC interface received data from host
void tud_cdc_rx_cb(uint8_t itf) {
(void) itf;
char buf[64];
uint32_t count = tud_cdc_read(buf, sizeof(buf));
// TODO control LED on keyboard of host stack
(void) count;
}
//--------------------------------------------------------------------+
// Host HID
//--------------------------------------------------------------------+
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) {
(void) desc_report;
(void) desc_len;
// Interface protocol (hid_interface_protocol_enum_t)
const char* protocol_str[] = {"None", "Keyboard", "Mouse"};
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
char tempbuf[256];
int count = sprintf(
tempbuf, "[%04x:%04x][%u] HID Interface%u, Protocol = %s\r\n", vid, pid, dev_addr, instance,
protocol_str[itf_protocol]);
tud_cdc_write(tempbuf, (uint32_t) count);
tud_cdc_write_flush();
// Receive report from boot keyboard & mouse only
// tuh_hid_report_received_cb() will be invoked when report is available
if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD || itf_protocol == HID_ITF_PROTOCOL_MOUSE) {
if (!tuh_hid_receive_report(dev_addr, instance)) {
tud_cdc_write_str("Error: cannot request report\r\n");
}
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
char tempbuf[256];
int count = sprintf(tempbuf, "[%u] HID Interface%u is unmounted\r\n", dev_addr, instance);
tud_cdc_write(tempbuf, (uint32_t) count);
tud_cdc_write_flush();
}
// look up new key in previous keys
static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) {
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i] == keycode) {
return true;
}
}
return false;
}
// convert hid keycode to ascii and print via usb device CDC (ignore non-printable)
static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const* report) {
(void) dev_addr;
static hid_keyboard_report_t prev_report = {0, 0, {0}}; // previous report to check key released
bool flush = false;
for (uint8_t i = 0; i < 6; i++) {
uint8_t keycode = report->keycode[i];
if (keycode) {
if (find_key_in_report(&prev_report, keycode)) {
// exist in previous report means the current key is holding
} else {
// not existed in previous report means the current key is pressed
// remap the key code for Colemak layout
#ifdef KEYBOARD_COLEMAK
uint8_t colemak_key_code = colemak[keycode];
if (colemak_key_code != 0) keycode = colemak_key_code;
#endif
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
uint8_t ch = keycode2ascii[keycode][is_shift ? 1 : 0];
if (ch) {
if (ch == '\n') tud_cdc_write("\r", 1);
tud_cdc_write(&ch, 1);
flush = true;
}
}
}
// TODO example skips key released
}
if (flush) {
tud_cdc_write_flush();
}
prev_report = *report;
}
// send mouse report to usb device CDC
static void process_mouse_report(uint8_t dev_addr, hid_mouse_report_t const* report) {
//------------- button state -------------//
//uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
char l = report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-';
char m = report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-';
char r = report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-';
char tempbuf[32];
int count = sprintf(tempbuf, "[%u] %c%c%c %d %d %d\r\n", dev_addr, l, m, r, report->x, report->y, report->wheel);
tud_cdc_write(tempbuf, (uint32_t) count);
tud_cdc_write_flush();
}
// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
(void) len;
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
process_kbd_report(dev_addr, (hid_keyboard_report_t const*) report);
break;
case HID_ITF_PROTOCOL_MOUSE:
process_mouse_report(dev_addr, (hid_mouse_report_t const*) report);
break;
default:
break;
}
// continue to request to receive report
if (!tuh_hid_receive_report(dev_addr, instance)) {
tud_cdc_write_str("Error: cannot request report\r\n");
}
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void) {
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time
start_ms += blink_interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
================================================
FILE: examples/dual/host_hid_to_device_cdc/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// Board Specific Configuration
//--------------------------------------------------------------------+
// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUD_MAX_SPEED
#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
// RHPort number used for host can be defined by board.mk, default to port 1
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 1
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// COMMON CONFIGURATION
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
// Enable Device stack, Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUD_ENABLED 1
#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED
// Enable Host stack, Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_ENABLED 1
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// Use pico-pio-usb as host controller for raspberry rp2040
#define CFG_TUH_RPI_PIO_USB 1
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUD_MEM_SECTION
#define CFG_TUD_MEM_SECTION
#endif
#ifndef CFG_TUD_MEM_ALIGN
#define CFG_TUD_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
#define CFG_TUD_CDC 1
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
//--------------------------------------------------------------------
// HOST CONFIGURATION
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
#define CFG_TUH_HUB 1
// max device support (excluding hub device)
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX)
#define CFG_TUH_HID_EPIN_BUFSIZE 64
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
*/
#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0)
#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \
PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) )
#define USB_VID 0xCafe
#define USB_BCD 0x0200
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
static tusb_desc_device_t const desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = USB_BCD,
// Use Interface Association Descriptor (IAD) for CDC
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
.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
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
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
};
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x83
#elif CFG_TUSB_MCU == OPT_MCU_CXD56
// CXD56 doesn't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
// CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number
// 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN)
#define EPNUM_CDC_NOTIF 0x83
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x81
#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
// FT9XX doesn't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x83
#else
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
#endif
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
// full speed configuration
static uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
};
#if TUD_OPT_HIGH_SPEED
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
// high speed configuration
static uint8_t const desc_hs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
};
// other speed configuration
static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
static tusb_desc_device_qualifier_t const desc_device_qualifier = {
.bLength = sizeof(tusb_desc_device_qualifier_t),
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
.bcdUSB = USB_BCD,
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.bNumConfigurations = 0x01,
.bReserved = 0x00
};
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
// device_qualifier descriptor describes information about a high-speed capable device that would
// change if the device were operating at the other speed. If not highspeed capable stall this request.
uint8_t const* tud_descriptor_device_qualifier_cb(void) {
return (uint8_t const*) &desc_device_qualifier;
}
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
// if link speed is high return fullspeed config, and vice versa
// Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG
memcpy(desc_other_speed_config,
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
CONFIG_TOTAL_LEN);
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
return desc_other_speed_config;
}
#endif // highspeed
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const* tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
#if TUD_OPT_HIGH_SPEED
// Although we are highspeed, host may be fullspeed.
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
#else
return desc_fs_configuration;
#endif
}
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
// String Descriptor Index
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
};
// array of pointer to string descriptors
char const* string_desc_arr[] = {
(const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
NULL, // 3: Serials will use unique ID if possible
"TinyUSB CDC", // 4: CDC Interface
};
static uint16_t _desc_str[32 + 1];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
(void) langid;
size_t chr_count;
switch (index) {
case STRID_LANGID:
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
break;
case STRID_SERIAL:
chr_count = board_usb_get_serial(_desc_str + 1, 32);
break;
default:
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) return NULL;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
if (chr_count > max_count) chr_count = max_count;
// Convert ASCII string into UTF-16
for (size_t i = 0; i < chr_count; i++) {
_desc_str[1 + i] = str[i];
}
break;
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
================================================
FILE: examples/dual/host_info_to_device_cdc/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(host_info_to_device_cdc C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_dual_usb_example(${PROJECT_NAME} ${RTOS})
# due to warnings from Pico-PIO-USB
if (FAMILY STREQUAL rp2040)
target_compile_options(${PROJECT_NAME} PUBLIC
-Wno-error=shadow
-Wno-error=cast-align
-Wno-error=cast-qual
-Wno-error=redundant-decls
-Wno-error=sign-conversion
-Wno-error=conversion
-Wno-error=sign-compare
-Wno-error=unused-function
)
endif ()
================================================
FILE: examples/dual/host_info_to_device_cdc/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/dual/host_info_to_device_cdc/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += $(wildcard src/*.c)
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference
SRC_C += \
src/host/hub.c \
src/host/usbh.c
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/dual/host_info_to_device_cdc/only.txt
================================================
board:mimxrt1060_evk
board:mimxrt1064_evk
board:mcb1800
mcu:CH32V20X
mcu:RP2040
mcu:ra6m5
mcu:MAX3421
mcu:STM32F4
mcu:STM32F7
mcu:STM32H7
mcu:ESP32P4
================================================
FILE: examples/dual/host_info_to_device_cdc/src/CMakeLists.txt
================================================
# This file is for ESP-IDF only
idf_component_register(SRCS "main.c" "usb_descriptors.c"
INCLUDE_DIRS "."
REQUIRES boards tinyusb_src)
================================================
FILE: examples/dual/host_info_to_device_cdc/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/* Host example will get device descriptors of attached devices and print it out via device cdc as follows:
* Device 1: ID 046d:c52f SN 11223344
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 0200
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x046d
idProduct 0xc52f
bcdDevice 2200
iManufacturer 1 Logitech
iProduct 2 USB Receiver
iSerialNumber 0
bNumConfigurations 1
*
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
// Language ID: English
#define LANGUAGE_ID 0x0409
/* Blink pattern
* - 250 ms : device not mounted
* - 1000 ms : device mounted
* - 2500 ms : device is suspended
*/
enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
};
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
static bool is_printable[CFG_TUH_DEVICE_MAX + 1] = {0};
static tusb_desc_device_t descriptor_device[CFG_TUH_DEVICE_MAX+1];
static void print_utf16(uint16_t *temp_buf, size_t buf_len);
static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device);
static void led_blinking_task(void);
static void cdc_task(void);
#if CFG_TUSB_OS == OPT_OS_FREERTOS
static void freertos_init(void);
#endif
#define cdc_printf(...) \
do { \
char _tempbuf[256]; \
char* _bufptr = _tempbuf; \
uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \
while (count > 0) { \
uint32_t wr_count = tud_cdc_write(_bufptr, count); \
count -= wr_count; \
_bufptr += wr_count; \
if (count > 0){ \
tud_task(); \
tud_cdc_write_flush(); \
} \
} \
} while(0)
static void usb_device_init(void) {
// init device and host stack on configured roothub port
tusb_rhport_init_t dev_init = {
.role = TUSB_ROLE_DEVICE,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUD_RHPORT, &dev_init);
board_init_after_tusb();
}
static void usb_host_init(void) {
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
board_init_after_tusb();
}
//--------------------------------------------------------------------+
// Main
//--------------------------------------------------------------------+
static void main_task(void* param) {
(void) param;
while (1) {
cdc_task();
led_blinking_task();
// preempted RTOS run device/host stack in its own task
#if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO
tud_task(); // tinyusb device task
tuh_task(); // tinyusb host task
#endif
}
}
int main(void) {
board_init();
#if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO
printf("TinyUSB Host Information -> Device CDC Example\r\n");
usb_device_init();
usb_host_init();
main_task(NULL);
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
freertos_init(); // create RTOS tasks for device, host stack and main_task()
#else
#error RTOS not supported
#endif
return 0;
}
#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO
// USB Device Driver task for RTOS
static void usb_device_task(void *param) {
(void) param;
usb_device_init();
while (1) {
// put this thread to waiting state until there is new events
tud_task();
}
}
static void usb_host_task(void *param) {
(void) param;
usb_host_init();
while (1) {
// put this thread to waiting state until there is new events
tuh_task();
}
}
#endif
//--------------------------------------------------------------------+
// Device CDC
//--------------------------------------------------------------------+
// Invoked when device is mounted
void tud_mount_cb(void) {
blink_interval_ms = BLINK_MOUNTED;
}
// Invoked when device is unmounted
void tud_umount_cb(void) {
blink_interval_ms = BLINK_NOT_MOUNTED;
}
// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en) {
(void) remote_wakeup_en;
blink_interval_ms = BLINK_SUSPENDED;
}
// Invoked when usb bus is resumed
void tud_resume_cb(void) {
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
void cdc_task(void) {
static uint32_t connected_ms = 0;
if (!tud_cdc_connected()) {
connected_ms = tusb_time_millis_api();
return;
}
// delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding.
// If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop
if (tusb_time_millis_api() - connected_ms < 100) {
return; // wait for stable connection
}
for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) {
if (tuh_mounted(daddr)) {
if (is_printable[daddr]) {
is_printable[daddr] = false;
print_device_info(daddr, &descriptor_device[daddr]);
tud_cdc_write_flush();
}
}
}
}
//--------------------------------------------------------------------+
// Host Get device information
//--------------------------------------------------------------------+
static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device) {
// Get String descriptor using Sync API
uint16_t serial[64];
uint16_t buf[128];
(void) buf;
cdc_printf("Device %u: ID %04x:%04x SN ", daddr, desc_device->idVendor, desc_device->idProduct);
uint8_t xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, serial, sizeof(serial));
if (XFER_RESULT_SUCCESS != xfer_result) {
serial[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * 1 + 2));
serial[1] = '0';
serial[2] = 0;
}
print_utf16(serial, TU_ARRAY_SIZE(serial));
cdc_printf("\r\n");
cdc_printf("Device Descriptor:\r\n");
cdc_printf(" bLength %u\r\n" , desc_device->bLength);
cdc_printf(" bDescriptorType %u\r\n" , desc_device->bDescriptorType);
cdc_printf(" bcdUSB %04x\r\n" , desc_device->bcdUSB);
cdc_printf(" bDeviceClass %u\r\n" , desc_device->bDeviceClass);
cdc_printf(" bDeviceSubClass %u\r\n" , desc_device->bDeviceSubClass);
cdc_printf(" bDeviceProtocol %u\r\n" , desc_device->bDeviceProtocol);
cdc_printf(" bMaxPacketSize0 %u\r\n" , desc_device->bMaxPacketSize0);
cdc_printf(" idVendor 0x%04x\r\n" , desc_device->idVendor);
cdc_printf(" idProduct 0x%04x\r\n" , desc_device->idProduct);
cdc_printf(" bcdDevice %04x\r\n" , desc_device->bcdDevice);
cdc_printf(" iManufacturer %u " , desc_device->iManufacturer);
xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
if (XFER_RESULT_SUCCESS == xfer_result) {
print_utf16(buf, TU_ARRAY_SIZE(buf));
}
cdc_printf("\r\n");
cdc_printf(" iProduct %u " , desc_device->iProduct);
xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
if (XFER_RESULT_SUCCESS == xfer_result) {
print_utf16(buf, TU_ARRAY_SIZE(buf));
}
cdc_printf("\r\n");
cdc_printf(" iSerialNumber %u " , desc_device->iSerialNumber);
cdc_printf("%s \r\n", (char*)serial); // serial is already to UTF-8
cdc_printf(" bNumConfigurations %u\r\n" , desc_device->bNumConfigurations);
}
void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc_device) {
(void) daddr;
descriptor_device[daddr] = *desc_device; // save device descriptor
}
void tuh_mount_cb(uint8_t daddr) {
cdc_printf("mounted device %u\r\n", daddr);
tud_cdc_write_flush();
is_printable[daddr] = true;
}
void tuh_umount_cb(uint8_t daddr) {
cdc_printf("unmounted device %u\r\n", daddr);
tud_cdc_write_flush();
is_printable[daddr] = false;
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void) {
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if (tusb_time_millis_api() - start_ms < blink_interval_ms) {
return;// not enough time
}
start_ms += blink_interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
//--------------------------------------------------------------------+
// String Descriptor Helper
//--------------------------------------------------------------------+
static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
// TODO: Check for runover.
(void)utf8_len;
// Get the UTF-16 length out of the data itself.
for (size_t i = 0; i < utf16_len; i++) {
uint16_t chr = utf16[i];
if (chr < 0x80) {
*utf8++ = chr & 0xffu;
} else if (chr < 0x800) {
*utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F));
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
} else {
// TODO: Verify surrogate.
*utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F));
*utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
}
// TODO: Handle UTF-16 code points that take two entries.
}
}
// Count how many bytes a utf-16-le encoded string will take in utf-8.
static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
size_t total_bytes = 0;
for (size_t i = 0; i < len; i++) {
uint16_t chr = buf[i];
if (chr < 0x80) {
total_bytes += 1;
} else if (chr < 0x800) {
total_bytes += 2;
} else {
total_bytes += 3;
}
// TODO: Handle UTF-16 code points that take two entries.
}
return (int) total_bytes;
}
static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
if ((temp_buf[0] & 0xff) == 0) {
return;// empty
}
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
((uint8_t*) temp_buf)[utf8_len] = '\0';
cdc_printf("%s", (char*) temp_buf);
}
//--------------------------------------------------------------------+
// FreeRTOS
//--------------------------------------------------------------------+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
#ifdef ESP_PLATFORM
#define USBD_STACK_SIZE 4096
#define USBH_STACK_SIZE 4096
void app_main(void) {
main();
}
#else
// Increase stack size when debug log is enabled
#define USBD_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2))
#define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2))
#endif
#define MAIN_STACK_SIZE (configMINIMAL_STACK_SIZE*4)
// static task
#if configSUPPORT_STATIC_ALLOCATION
StackType_t main_stack[MAIN_STACK_SIZE];
StaticTask_t main_taskdef;
StackType_t usb_device_stack[USBD_STACK_SIZE];
StaticTask_t usb_device_taskdef;
StackType_t usb_host_stack[USBH_STACK_SIZE];
StaticTask_t usb_host_taskdef;
#endif
void freertos_init(void) {
#if configSUPPORT_STATIC_ALLOCATION
xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);
xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef);
xTaskCreateStatic(main_task, "main", MAIN_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, main_stack, &main_taskdef);
#else
xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
xTaskCreate(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
xTaskCreate(main_task, "main", MAIN_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL);
#endif
// only start scheduler for non-espressif mcu
#ifndef ESP_PLATFORM
vTaskStartScheduler();
#endif
}
#endif
================================================
FILE: examples/dual/host_info_to_device_cdc/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// Board Specific Configuration
//--------------------------------------------------------------------+
// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUD_MAX_SPEED
#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
// RHPort number used for host can be defined by board.mk, default to port 1
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 1
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// COMMON CONFIGURATION
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
// Enable Device stack, Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUD_ENABLED 1
#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED
// Enable Host stack, Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_ENABLED 1
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// Use pico-pio-usb as host controller for raspberry rp2040
#define CFG_TUH_RPI_PIO_USB 1
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUD_MEM_SECTION
#define CFG_TUD_MEM_SECTION
#endif
#ifndef CFG_TUD_MEM_ALIGN
#define CFG_TUD_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
#define CFG_TUD_CDC 1
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 256)
// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
//--------------------------------------------------------------------
// HOST CONFIGURATION
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
#define CFG_TUH_HUB 1
// max device support (excluding hub device)
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: examples/dual/host_info_to_device_cdc/src/usb_descriptors.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
*/
#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0)
#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \
PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) )
#define USB_VID 0xCafe
#define USB_BCD 0x0200
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
static tusb_desc_device_t const desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = USB_BCD,
// Use Interface Association Descriptor (IAD) for CDC
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
.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
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
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
};
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x83
#elif CFG_TUSB_MCU == OPT_MCU_CXD56
// CXD56 doesn't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
// CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number
// 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN)
#define EPNUM_CDC_NOTIF 0x83
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x81
#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
// FT9XX doesn't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x83
#else
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
#endif
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
// full speed configuration
static uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
};
#if TUD_OPT_HIGH_SPEED
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
// high speed configuration
static uint8_t const desc_hs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
};
// other speed configuration
static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
static tusb_desc_device_qualifier_t const desc_device_qualifier = {
.bLength = sizeof(tusb_desc_device_qualifier_t),
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
.bcdUSB = USB_BCD,
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.bNumConfigurations = 0x01,
.bReserved = 0x00
};
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
// device_qualifier descriptor describes information about a high-speed capable device that would
// change if the device were operating at the other speed. If not highspeed capable stall this request.
uint8_t const* tud_descriptor_device_qualifier_cb(void) {
return (uint8_t const*) &desc_device_qualifier;
}
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
// if link speed is high return fullspeed config, and vice versa
// Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG
memcpy(desc_other_speed_config,
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
CONFIG_TOTAL_LEN);
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
return desc_other_speed_config;
}
#endif // highspeed
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const* tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
#if TUD_OPT_HIGH_SPEED
// Although we are highspeed, host may be fullspeed.
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
#else
return desc_fs_configuration;
#endif
}
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
// String Descriptor Index
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
};
// array of pointer to string descriptors
char const* string_desc_arr[] = {
(const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
NULL, // 3: Serials will use unique ID if possible
"TinyUSB CDC", // 4: CDC Interface
};
static uint16_t _desc_str[32 + 1];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
(void) langid;
size_t chr_count;
switch (index) {
case STRID_LANGID:
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
break;
case STRID_SERIAL:
chr_count = board_usb_get_serial(_desc_str + 1, 32);
break;
default:
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) return NULL;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
if (chr_count > max_count) chr_count = max_count;
// Convert ASCII string into UTF-16
for (size_t i = 0; i < chr_count; i++) {
_desc_str[1 + i] = str[i];
}
break;
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
return _desc_str;
}
================================================
FILE: examples/host/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
project(tinyusb_host_examples C CXX ASM)
family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
# family_add_subdirectory will filter what to actually add based on selected FAMILY
set(EXAMPLE_LIST
bare_api
cdc_msc_hid
cdc_msc_hid_freertos
device_info
hid_controller
midi_rx
msc_file_explorer
)
foreach (example ${EXAMPLE_LIST})
family_add_subdirectory(${example})
endforeach ()
================================================
FILE: examples/host/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/bare_api/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(bare_api C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_host_example(${PROJECT_NAME} noos)
================================================
FILE: examples/host/bare_api/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/bare_api/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += \
src/main.c
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/host/bare_api/only.txt
================================================
family:hpmicro
family:samd21
family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:LPC54
mcu:LPC55
mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RAXXX
mcu:RP2040
mcu:RW61X
mcu:RX65X
mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
mcu:STM32G0
mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
mcu:STM32U3
mcu:STM32U5
================================================
FILE: examples/host/bare_api/skip.txt
================================================
board:lpcxpresso54114
================================================
FILE: examples/host/bare_api/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
#include "class/hid/hid.h"
// English
#define LANGUAGE_ID 0x0409
#define BUF_COUNT 4
CFG_TUH_MEM_SECTION tusb_desc_device_t desc_device;
CFG_TUH_MEM_SECTION uint8_t buf_pool[BUF_COUNT][64];
uint8_t buf_owner[BUF_COUNT] = { 0 }; // device address that owns buffer
CFG_TUH_MEM_SECTION uint16_t temp_buf[128]; // temp buffer for string descriptor
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);
static void print_utf16(uint16_t *temp_buf, size_t buf_len);
void print_device_descriptor(tuh_xfer_t* xfer);
void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
uint8_t* get_hid_buf(uint8_t daddr);
void free_hid_buf(uint8_t daddr);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Bare API Example\r\n");
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
board_init_after_tusb();
while (1) {
// tinyusb host task
tuh_task();
led_blinking_task();
}
}
/*------------- TinyUSB Callbacks -------------*/
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
printf("Device attached, address = %d\r\n", daddr);
// Get Device Descriptor
// TODO: invoking control transfer now has issue with mounting hub with multiple devices attached, fix later
tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0);
}
/// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t daddr) {
printf("Device removed, address = %d\r\n", daddr);
free_hid_buf(daddr);
}
//--------------------------------------------------------------------+
// Device Descriptor
//--------------------------------------------------------------------+
void print_device_descriptor(tuh_xfer_t *xfer) {
if (XFER_RESULT_SUCCESS != xfer->result) {
printf("Failed to get device descriptor\r\n");
return;
}
uint8_t const daddr = xfer->daddr;
printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct);
printf("Device Descriptor:\r\n");
printf(" bLength %u\r\n" , desc_device.bLength);
printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType);
printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB);
printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass);
printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass);
printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol);
printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0);
printf(" idVendor 0x%04x\r\n" , desc_device.idVendor);
printf(" idProduct 0x%04x\r\n" , desc_device.idProduct);
printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice);
// Get String descriptor using Sync API
printf(" iManufacturer %u ", desc_device.iManufacturer);
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) {
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
printf("\r\n");
printf(" iProduct %u ", desc_device.iProduct);
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) {
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
printf("\r\n");
printf(" iSerialNumber %u ", desc_device.iSerialNumber);
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) {
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
printf("\r\n");
printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations);
// Get configuration descriptor with sync API
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf))) {
parse_config_descriptor(daddr, (tusb_desc_configuration_t *) temp_buf);
}
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
// count total length of an interface
uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);
void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
// simple configuration parser to open and listen to HID Endpoint IN
void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const *desc_cfg) {
uint8_t const *desc_end = ((uint8_t const *) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
uint8_t const *p_desc = tu_desc_next(desc_cfg);
// parse each interfaces
while (p_desc < desc_end) {
uint8_t assoc_itf_count = 1;
// Class will always starts with Interface Association (if any) and then Interface descriptor
if (TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc)) {
tusb_desc_interface_assoc_t const *desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
assoc_itf_count = desc_iad->bInterfaceCount;
p_desc = tu_desc_next(p_desc);// next to Interface
}
// must be interface from now
if (TUSB_DESC_INTERFACE != tu_desc_type(p_desc)) { return; }
tusb_desc_interface_t const *desc_itf = (tusb_desc_interface_t const *) p_desc;
uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end - p_desc));
// probably corrupted descriptor
if (drv_len < sizeof(tusb_desc_interface_t)) { return; }
// only open and listen to HID endpoint IN
if (desc_itf->bInterfaceClass == TUSB_CLASS_HID) {
open_hid_interface(dev_addr, desc_itf, drv_len);
}
// next Interface or IAD descriptor
p_desc += drv_len;
}
}
uint16_t count_interface_total_len(tusb_desc_interface_t const *desc_itf, uint8_t itf_count, uint16_t max_len) {
uint8_t const *p_desc = (uint8_t const *) desc_itf;
uint16_t len = 0;
while (itf_count--) {
// Next on interface desc
len += tu_desc_len(desc_itf);
p_desc = tu_desc_next(p_desc);
while (len < max_len) {
// return on IAD regardless of itf count
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { return len; }
if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
((tusb_desc_interface_t const *) p_desc)->bAlternateSetting == 0) {
break;
}
len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
}
return len;
}
//--------------------------------------------------------------------+
// HID Interface
//--------------------------------------------------------------------+
void hid_report_received(tuh_xfer_t* xfer);
void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) {
// len = interface + hid + n*endpoints
uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) +
desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
// corrupted descriptor
if (max_len < drv_len) { return; }
uint8_t const *p_desc = (uint8_t const *) desc_itf;
// HID descriptor
p_desc = tu_desc_next(p_desc);
tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
if (HID_DESC_TYPE_HID != desc_hid->bDescriptorType) { return; }
// Endpoint descriptor
p_desc = tu_desc_next(p_desc);
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
for (int i = 0; i < desc_itf->bNumEndpoints; i++) {
if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) { return; }
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
if (!tuh_edpt_open(daddr, desc_ep)) {
return; // skip if failed to open endpoint
}
uint8_t *buf = get_hid_buf(daddr);
if (!buf) {
return;// out of memory
}
tuh_xfer_t xfer = {
.daddr = daddr,
.ep_addr = desc_ep->bEndpointAddress,
.buflen = 64,
.buffer = buf,
.complete_cb = hid_report_received,
.user_data = (uintptr_t) buf,// since buffer is not available in callback, use user data to store the buffer
};
// submit transfer for this EP
tuh_edpt_xfer(&xfer);
printf("Listen to [dev %u: ep %02x]\r\n", daddr, desc_ep->bEndpointAddress);
}
p_desc = tu_desc_next(p_desc);
desc_ep = (tusb_desc_endpoint_t const *) p_desc;
}
}
void hid_report_received(tuh_xfer_t *xfer) {
// Note: not all field in xfer is available for use (i.e filled by tinyusb stack) in callback to save sram
// For instance, xfer->buffer is NULL. We have used user_data to store buffer when submitted callback
uint8_t *buf = (uint8_t *) xfer->user_data;
if (xfer->result == XFER_RESULT_SUCCESS) {
printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr);
for (uint32_t i = 0; i < xfer->actual_len; i++) {
if (i % 16 == 0) {
printf("\r\n ");
}
printf("%02X ", buf[i]);
}
printf("\r\n");
}
// continue to submit transfer, with updated buffer
// other field remain the same
xfer->buflen = 64;
xfer->buffer = buf;
tuh_edpt_xfer(xfer);
}
//--------------------------------------------------------------------+
// Buffer helper
//--------------------------------------------------------------------+
// get an buffer from pool
uint8_t *get_hid_buf(uint8_t daddr) {
for (size_t i = 0; i < BUF_COUNT; i++) {
if (buf_owner[i] == 0) {
buf_owner[i] = daddr;
return buf_pool[i];
}
}
// out of memory, increase BUF_COUNT
return NULL;
}
// free all buffer owned by device
void free_hid_buf(uint8_t daddr) {
for (size_t i = 0; i < BUF_COUNT; i++) {
if (buf_owner[i] == daddr) buf_owner[i] = 0;
}
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if (tusb_time_millis_api() - start_ms < interval_ms) {
return; // not enough time
}
start_ms += interval_ms;
board_led_write(led_state);
led_state = 1 - led_state;// toggle
}
//--------------------------------------------------------------------+
// String Descriptor Helper
//--------------------------------------------------------------------+
static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
// TODO: Check for runover.
(void) utf8_len;
// Get the UTF-16 length out of the data itself.
for (size_t i = 0; i < utf16_len; i++) {
uint16_t chr = utf16[i];
if (chr < 0x80) {
*utf8++ = chr & 0xffu;
} else if (chr < 0x800) {
*utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
} else {
// TODO: Verify surrogate.
*utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
*utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
}
// TODO: Handle UTF-16 code points that take two entries.
}
}
// Count how many bytes a utf-16-le encoded string will take in utf-8.
static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
size_t total_bytes = 0;
for (size_t i = 0; i < len; i++) {
uint16_t chr = buf[i];
if (chr < 0x80) {
total_bytes += 1;
} else if (chr < 0x800) {
total_bytes += 2;
} else {
total_bytes += 3;
}
// TODO: Handle UTF-16 code points that take two entries.
}
return (int) total_bytes;
}
static void print_utf16(uint16_t *buf, size_t buf_len) {
if ((buf[0] & 0xff) == 0) return;// empty
size_t utf16_len = ((buf[0] & 0xff) - 2) / sizeof(uint16_t);
size_t utf8_len = (size_t) _count_utf8_bytes(buf + 1, utf16_len);
_convert_utf16le_to_utf8(buf + 1, utf16_len, (uint8_t *) buf, sizeof(uint16_t) * buf_len);
((uint8_t *) buf)[utf8_len] = '\0';
printf("%s", (char *) buf);
}
================================================
FILE: examples/host/bare_api/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// Host Configuration
//--------------------------------------------------------------------
// Enable Host stack
#define CFG_TUH_ENABLED 1
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
#define BOARD_TUH_RHPORT 1
#endif
#endif
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
//------------------------- Board Specific --------------------------
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
// only hub class is enabled
#define CFG_TUH_HUB 1
// max device support (excluding hub device)
// 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
// Max endpoint per device
#define CFG_TUH_ENDPOINT_MAX 8
// Enable tuh_edpt_xfer() API
#define CFG_TUH_API_EDPT_XFER 1
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: examples/host/cdc_msc_hid/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(cdc_msc_hid C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_host_example(${PROJECT_NAME} noos)
================================================
FILE: examples/host/cdc_msc_hid/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/cdc_msc_hid/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE = \
src/cdc_app.c \
src/hid_app.c \
src/main.c \
src/msc_app.c \
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/host/cdc_msc_hid/only.txt
================================================
family:hpmicro
family:samd21
family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:LPC54
mcu:LPC55
mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RAXXX
mcu:RP2040
mcu:RW61X
mcu:RX65X
mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
mcu:STM32G0
mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
mcu:STM32U3
mcu:STM32U5
================================================
FILE: examples/host/cdc_msc_hid/skip.txt
================================================
board:lpcxpresso54114
================================================
FILE: examples/host/cdc_msc_hid/src/app.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2025 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef TUSB_TINYUSB_EXAMPLES_APP_H
#define TUSB_TINYUSB_EXAMPLES_APP_H
#include
void cdc_app_task(void);
void hid_app_task(void);
#endif
================================================
FILE: examples/host/cdc_msc_hid/src/cdc_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2022, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include "tusb.h"
#include "bsp/board_api.h"
#include "app.h"
static size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
size_t count = 0;
while (count < bufsize) {
int ch = board_getchar();
if (ch <= 0) { break; }
buf[count] = (uint8_t) ch;
count++;
}
return count;
}
void cdc_app_task(void) {
uint8_t buf[64 + 1]; // +1 for extra null character
uint32_t const bufsize = sizeof(buf) - 1;
uint32_t count = get_console_inputs(buf, bufsize);
buf[count] = 0;
// loop over all mounted interfaces
for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
if (tuh_cdc_mounted(idx)) {
// console --> cdc interfaces
if (count > 0) {
tuh_cdc_write(idx, buf, count);
tuh_cdc_write_flush(idx);
}
}
}
}
//--------------------------------------------------------------------+
// TinyUSB callbacks
//--------------------------------------------------------------------+
// Invoked when received new data
void tuh_cdc_rx_cb(uint8_t idx) {
uint8_t buf[64 + 1]; // +1 for extra null character
uint32_t const bufsize = sizeof(buf) - 1;
// forward cdc interfaces -> console
const uint32_t count = tuh_cdc_read(idx, buf, bufsize);
if (count) {
buf[count] = 0;
printf("%s", (char*) buf);
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
fflush(stdout);// flush right away, else nanolib will wait for newline
#endif
}
}
// Invoked when a device with CDC interface is mounted
// idx is index of cdc interface in the internal pool.
void tuh_cdc_mount_cb(uint8_t idx) {
tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info);
printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
itf_info.desc.bInterfaceNumber);
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
// If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack
// while eneumerating new cdc device
cdc_line_coding_t line_coding = {0};
if (tuh_cdc_get_line_coding_local(idx, &line_coding)) {
printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
}
#else
// Set Line Coding upon mounted
cdc_line_coding_t new_line_coding = { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 };
tuh_cdc_set_line_coding(idx, &new_line_coding, NULL, 0);
#endif
}
// Invoked when a device with CDC interface is unmounted
void tuh_cdc_umount_cb(uint8_t idx) {
tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info);
printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
itf_info.desc.bInterfaceNumber);
}
================================================
FILE: examples/host/cdc_msc_hid/src/hid_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2021, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
#include "app.h"
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
#define MAX_REPORT 4
static uint8_t const keycode2ascii[128][2] = {HID_KEYCODE_TO_ASCII};
// Each HID instance can has multiple reports
static struct {
uint8_t report_count;
tuh_hid_report_info_t report_info[MAX_REPORT];
} hid_info[CFG_TUH_HID];
static void process_kbd_report(hid_keyboard_report_t const *report);
static void process_mouse_report(hid_mouse_report_t const *report);
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len);
void hid_app_task(void) {
// nothing to do
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
// Interface protocol (hid_interface_protocol_enum_t)
const char *protocol_str[] = {"None", "Keyboard", "Mouse"};
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
// By default, host stack will use boot protocol on supported interface.
// Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
if (itf_protocol == HID_ITF_PROTOCOL_NONE) {
hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len);
printf("HID has %u reports \r\n", hid_info[instance].report_count);
}
// request to receive report
// tuh_hid_report_received_cb() will be invoked when report is available
if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
TU_LOG2("HID receive boot keyboard report\r\n");
process_kbd_report((hid_keyboard_report_t const *) report);
break;
case HID_ITF_PROTOCOL_MOUSE:
TU_LOG2("HID receive boot mouse report\r\n");
process_mouse_report((hid_mouse_report_t const *) report);
break;
default:
// Generic report requires matching ReportID and contents with previous parsed report info
process_generic_report(dev_addr, instance, report, len);
break;
}
// continue to request to receive report
if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
//--------------------------------------------------------------------+
// Keyboard
//--------------------------------------------------------------------+
// look up new key in previous keys
static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) {
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i] == keycode) {
return true;
}
}
return false;
}
static void process_kbd_report(hid_keyboard_report_t const *report) {
static hid_keyboard_report_t prev_report = {0, 0, {0}};// previous report to check key released
//------------- example code ignore control (non-printable) key affects -------------//
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i]) {
if (find_key_in_report(&prev_report, report->keycode[i])) {
// exist in previous report means the current key is holding
} else {
// not existed in previous report means the current key is pressed
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
putchar(ch);
if (ch == '\r') {
putchar('\n');
}
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
fflush(stdout);// flush right away, else nanolib will wait for newline
#endif
}
}
// TODO example skips key released
}
prev_report = *report;
}
//--------------------------------------------------------------------+
// Mouse
//--------------------------------------------------------------------+
static void cursor_movement(int8_t x, int8_t y, int8_t wheel) {
printf("(%d %d %d)\r\n", x, y, wheel);
}
static void process_mouse_report(hid_mouse_report_t const *report) {
static hid_mouse_report_t prev_report = {0};
// button state
uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
if (button_changed_mask & report->buttons) {
printf(" %c%c%c ",
report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
}
// cursor movement
cursor_movement(report->x, report->y, report->wheel);
}
//--------------------------------------------------------------------+
// Generic Report
//--------------------------------------------------------------------+
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
(void) dev_addr;
(void) len;
uint8_t const rpt_count = hid_info[instance].report_count;
tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info;
tuh_hid_report_info_t *rpt_info = NULL;
if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) {
// Simple report without report ID as 1st byte
rpt_info = &rpt_info_arr[0];
} else {
// Composite report, 1st byte is report ID, data starts from 2nd byte
uint8_t const rpt_id = report[0];
// Find report id in the array
for (uint8_t i = 0; i < rpt_count; i++) {
if (rpt_id == rpt_info_arr[i].report_id) {
rpt_info = &rpt_info_arr[i];
break;
}
}
report++;
len--;
}
if (!rpt_info) {
printf("Couldn't find report info !\r\n");
return;
}
// For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples:
// - Keyboard : Desktop, Keyboard
// - Mouse : Desktop, Mouse
// - Gamepad : Desktop, Gamepad
// - Consumer Control (Media Key) : Consumer, Consumer Control
// - System Control (Power key) : Desktop, System Control
// - Generic (vendor) : 0xFFxx, xx
if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) {
switch (rpt_info->usage) {
case HID_USAGE_DESKTOP_KEYBOARD:
TU_LOG2("HID receive keyboard report\r\n");
// Assume keyboard follow boot report layout
process_kbd_report((hid_keyboard_report_t const *) report);
break;
case HID_USAGE_DESKTOP_MOUSE:
TU_LOG2("HID receive mouse report\r\n");
// Assume mouse follow boot report layout
process_mouse_report((hid_mouse_report_t const *) report);
break;
default:
printf("report[%u] ", rpt_info->report_id);
for (uint8_t i = 0; i < len; i++) {
printf("%02X ", report[i]);
}
printf("\r\n");
break;
}
}
}
================================================
FILE: examples/host/cdc_msc_hid/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
#include "app.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Host CDC MSC HID Example\r\n");
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
board_init_after_tusb();
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
#endif
while (1) {
// tinyusb host task
tuh_task();
led_blinking_task();
cdc_app_task();
hid_app_task();
}
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
void tuh_mount_cb(uint8_t dev_addr) {
// application set-up
printf("A device with address %u is mounted\r\n", dev_addr);
}
void tuh_umount_cb(uint8_t dev_addr) {
// application tear-down
printf("A device with address %u is unmounted \r\n", dev_addr);
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if (tusb_time_millis_api() - start_ms < interval_ms) {
return;// not enough time
}
start_ms += interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
================================================
FILE: examples/host/cdc_msc_hid/src/msc_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include "tusb.h"
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
static scsi_inquiry_resp_t inquiry_resp;
static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) {
msc_cbw_t const* cbw = cb_data->cbw;
msc_csw_t const* csw = cb_data->csw;
if (csw->status != 0) {
printf("Inquiry failed\r\n");
return false;
}
// Print out Vendor ID, Product ID and Rev
printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev);
// Get capacity of device
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size));
printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size);
return true;
}
//------------- IMPLEMENTATION -------------//
void tuh_msc_mount_cb(uint8_t dev_addr) {
printf("A MassStorage device is mounted\r\n");
uint8_t const lun = 0;
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0);
}
void tuh_msc_umount_cb(uint8_t dev_addr) {
(void) dev_addr;
printf("A MassStorage device is unmounted\r\n");
}
================================================
FILE: examples/host/cdc_msc_hid/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// Host Configuration
//--------------------------------------------------------------------
// Enable Host stack
#define CFG_TUH_ENABLED 1
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
#define BOARD_TUH_RHPORT 1
#endif
#endif
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
//------------------------- Board Specific --------------------------
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 1 // number of supported hubs
#define CFG_TUH_CDC 2 // number of supported CDC devices. also activates CDC ACM
#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_PL2303 1 // PL2303 Serial. PL2303 is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_MSC 1
#define CFG_TUH_VENDOR 0
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- HID -------------//
#define CFG_TUH_HID_EPIN_BUFSIZE 64
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
//------------- CDC -------------//
// Set Line Control state on enumeration/mounted:
// DTR ( bit 0), RTS (bit 1)
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS)
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
#ifdef __cplusplus
}
#endif
#endif /* TUSB_CONFIG_H_ */
================================================
FILE: examples/host/cdc_msc_hid_freertos/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(cdc_msc_hid_freertos C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_host_example(${PROJECT_NAME} freertos)
================================================
FILE: examples/host/cdc_msc_hid_freertos/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/cdc_msc_hid_freertos/Makefile
================================================
RTOS = freertos
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE = \
src/cdc_app.c \
src/hid_app.c \
src/main.c \
src/msc_app.c \
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/host/cdc_msc_hid_freertos/only.txt
================================================
family:espressif
family:samd21
family:samd5x_e5x
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:LPC54
mcu:LPC55
mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RW61X
mcu:RX65X
mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
mcu:STM32G0
mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
mcu:STM32U3
mcu:STM32U5
================================================
FILE: examples/host/cdc_msc_hid_freertos/skip.txt
================================================
mcu:CH32F20X
mcu:RP2040
board:lpcxpresso54114
mcu:FT90X
================================================
FILE: examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt
================================================
# This file is for ESP-IDF only
idf_component_register(SRCS "cdc_app.c" "hid_app.c" "main.c" "msc_app.c"
INCLUDE_DIRS "."
REQUIRES boards tinyusb_src)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)
================================================
FILE: examples/host/cdc_msc_hid_freertos/src/app.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2025 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef TUSB_TINYUSB_EXAMPLES_APP_H
#define TUSB_TINYUSB_EXAMPLES_APP_H
#include
void cdc_app_init(void);
void hid_app_init(void);
void msc_app_init(void);
#endif
================================================
FILE: examples/host/cdc_msc_hid_freertos/src/cdc_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2022, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include "tusb.h"
#include "bsp/board_api.h"
#include "app.h"
#ifdef ESP_PLATFORM
#define CDC_STACK_SZIE 2048
#else
#define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2)
#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
#if configSUPPORT_STATIC_ALLOCATION
StackType_t cdc_stack[CDC_STACK_SZIE];
StaticTask_t cdc_taskdef;
#endif
static void cdc_app_task(void* param);
void cdc_app_init(void) {
#if configSUPPORT_STATIC_ALLOCATION
(void) xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef);
#else
(void) xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL);
#endif
}
// helper
static size_t get_console_inputs(uint8_t *buf, size_t bufsize) {
size_t count = 0;
while (count < bufsize) {
int ch = board_getchar();
if (ch <= 0) {
break;
}
buf[count] = (uint8_t) ch;
count++;
}
return count;
}
static void cdc_app_task(void* param) {
(void) param;
uint8_t buf[64 + 1]; // +1 for extra null character
uint32_t const bufsize = sizeof(buf) - 1;
while (1) {
uint32_t count = get_console_inputs(buf, bufsize);
buf[count] = 0;
if (count) {
// loop over all mounted interfaces
for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
if (tuh_cdc_mounted(idx)) {
// console --> cdc interfaces
tuh_cdc_write(idx, buf, count);
tuh_cdc_write_flush(idx);
}
}
}
vTaskDelay(1);
}
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
// Invoked when received new data
void tuh_cdc_rx_cb(uint8_t idx) {
uint8_t buf[64 + 1]; // +1 for extra null character
uint32_t const bufsize = sizeof(buf) - 1;
// forward cdc interfaces -> console
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
buf[count] = 0;
printf("%s", (char *) buf);
}
void tuh_cdc_mount_cb(uint8_t idx) {
tuh_itf_info_t itf_info = { 0 };
tuh_cdc_itf_get_info(idx, &itf_info);
printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
// CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration
// otherwise you need to call tuh_cdc_set_line_coding() first
cdc_line_coding_t line_coding = { 0 };
if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
}
#endif
}
void tuh_cdc_umount_cb(uint8_t idx) {
tuh_itf_info_t itf_info = { 0 };
tuh_cdc_itf_get_info(idx, &itf_info);
printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
}
================================================
FILE: examples/host/cdc_msc_hid_freertos/src/hid_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2021, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
#include "app.h"
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
// If your host terminal support ansi escape code such as TeraTerm
// it can be use to simulate mouse cursor movement within terminal
#define USE_ANSI_ESCAPE 0
#define MAX_REPORT 4
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
// Each HID instance can has multiple reports
static struct {
uint8_t report_count;
tuh_hid_report_info_t report_info[MAX_REPORT];
} hid_info[CFG_TUH_HID];
static void process_kbd_report(hid_keyboard_report_t const *report);
static void process_mouse_report(hid_mouse_report_t const *report);
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len);
void hid_app_init(void) {
// nothing to do
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
// Interface protocol (hid_interface_protocol_enum_t)
const char *protocol_str[] = { "None", "Keyboard", "Mouse" };
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
// By default host stack will use activate boot protocol on supported interface.
// Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
if (itf_protocol == HID_ITF_PROTOCOL_NONE) {
hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT,
desc_report, desc_len);
printf("HID has %u reports \r\n", hid_info[instance].report_count);
}
// request to receive report
// tuh_hid_report_received_cb() will be invoked when report is available
if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
TU_LOG2("HID receive boot keyboard report\r\n");
process_kbd_report((hid_keyboard_report_t const *) report);
break;
case HID_ITF_PROTOCOL_MOUSE:
TU_LOG2("HID receive boot mouse report\r\n");
process_mouse_report((hid_mouse_report_t const *) report);
break;
default:
// Generic report requires matching ReportID and contents with previous parsed report info
process_generic_report(dev_addr, instance, report, len);
break;
}
// continue to request to receive report
if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
//--------------------------------------------------------------------+
// Keyboard
//--------------------------------------------------------------------+
// look up new key in previous keys
static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) {
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i] == keycode) return true;
}
return false;
}
static void process_kbd_report(hid_keyboard_report_t const *report) {
static hid_keyboard_report_t prev_report = { 0, 0, { 0 } }; // previous report to check key released
//------------- example code ignore control (non-printable) key affects -------------//
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i]) {
if (find_key_in_report(&prev_report, report->keycode[i])) {
// exist in previous report means the current key is holding
} else {
// not existed in previous report means the current key is pressed
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
putchar(ch);
if (ch == '\r') putchar('\n'); // added new line for enter key
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
fflush(stdout); // flush right away, else nanolib will wait for newline
#endif
}
}
// TODO example skips key released
}
prev_report = *report;
}
//--------------------------------------------------------------------+
// Mouse
//--------------------------------------------------------------------+
static void cursor_movement(int8_t x, int8_t y, int8_t wheel) {
#if USE_ANSI_ESCAPE
// Move X using ansi escape
if ( x < 0) {
printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
}else if ( x > 0) {
printf(ANSI_CURSOR_FORWARD(%d), x); // move right
}
// Move Y using ansi escape
if ( y < 0) {
printf(ANSI_CURSOR_UP(%d), (-y)); // move up
}else if ( y > 0) {
printf(ANSI_CURSOR_DOWN(%d), y); // move down
}
// Scroll using ansi escape
if (wheel < 0) {
printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
}else if (wheel > 0) {
printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
}
printf("\r\n");
#else
printf("(%d %d %d)\r\n", x, y, wheel);
#endif
}
static void process_mouse_report(hid_mouse_report_t const *report) {
static hid_mouse_report_t prev_report = { 0 };
//------------- button state -------------//
uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
if (button_changed_mask & report->buttons) {
printf(" %c%c%c ",
report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
}
//------------- cursor movement -------------//
cursor_movement(report->x, report->y, report->wheel);
}
//--------------------------------------------------------------------+
// Generic Report
//--------------------------------------------------------------------+
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
(void) dev_addr;
(void) len;
uint8_t const rpt_count = hid_info[instance].report_count;
tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info;
tuh_hid_report_info_t *rpt_info = NULL;
if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) {
// Simple report without report ID as 1st byte
rpt_info = &rpt_info_arr[0];
} else {
// Composite report, 1st byte is report ID, data starts from 2nd byte
uint8_t const rpt_id = report[0];
// Find report id in the array
for (uint8_t i = 0; i < rpt_count; i++) {
if (rpt_id == rpt_info_arr[i].report_id) {
rpt_info = &rpt_info_arr[i];
break;
}
}
report++;
len--;
}
if (!rpt_info) {
printf("Couldn't find report info !\r\n");
return;
}
// For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples:
// - Keyboard : Desktop, Keyboard
// - Mouse : Desktop, Mouse
// - Gamepad : Desktop, Gamepad
// - Consumer Control (Media Key) : Consumer, Consumer Control
// - System Control (Power key) : Desktop, System Control
// - Generic (vendor) : 0xFFxx, xx
if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) {
switch (rpt_info->usage) {
case HID_USAGE_DESKTOP_KEYBOARD:
TU_LOG1("HID receive keyboard report\r\n");
// Assume keyboard follow boot report layout
process_kbd_report((hid_keyboard_report_t const *) report);
break;
case HID_USAGE_DESKTOP_MOUSE:
TU_LOG1("HID receive mouse report\r\n");
// Assume mouse follow boot report layout
process_mouse_report((hid_mouse_report_t const *) report);
break;
default:
break;
}
}
}
================================================
FILE: examples/host/cdc_msc_hid_freertos/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
#include "app.h"
#ifdef ESP_PLATFORM
#define USBH_STACK_SIZE 4096
#else
// Increase stack size when debug log is enabled
#define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2))
#endif
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
/* Blink pattern
* - 250 ms : device not mounted
* - 1000 ms : device mounted
* - 2500 ms : device is suspended
*/
enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
};
// static timer & task
#if configSUPPORT_STATIC_ALLOCATION
StaticTimer_t blinky_tmdef;
StackType_t usb_host_stack[USBH_STACK_SIZE];
StaticTask_t usb_host_taskdef;
#endif
TimerHandle_t blinky_tm;
static void led_blinky_cb(TimerHandle_t xTimer);
static void usb_host_task(void* param);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n");
// Create soft timer for blinky, task for tinyusb stack
#if configSUPPORT_STATIC_ALLOCATION
blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef);
xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef);
#else
blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
xTaskCreate(usb_host_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL);
#endif
xTimerStart(blinky_tm, 0);
// only start scheduler for non-espressif mcu
#ifndef ESP_PLATFORM
vTaskStartScheduler();
#endif
return 0;
}
#ifdef ESP_PLATFORM
void app_main(void) {
main();
}
#endif
// USB Host task
// This top level thread process all usb events and invoke callbacks
static void usb_host_task(void *param) {
(void) param;
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
if (!tusb_init(BOARD_TUH_RHPORT, &host_init)) {
printf("Failed to init USB Host Stack\r\n");
vTaskSuspend(NULL);
}
board_init_after_tusb();
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
#endif
cdc_app_init();
hid_app_init();
msc_app_init();
// RTOS forever loop
while (1) {
// put this thread to waiting state until there is new events
tuh_task();
// following code only run if tuh_task() process at least 1 event
}
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
void tuh_mount_cb(uint8_t dev_addr) {
// application set-up
printf("A device with address %d is mounted\r\n", dev_addr);
}
void tuh_umount_cb(uint8_t dev_addr) {
// application tear-down
printf("A device with address %d is unmounted \r\n", dev_addr);
}
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
static void led_blinky_cb(TimerHandle_t xTimer) {
(void) xTimer;
static bool led_state = false;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
================================================
FILE: examples/host/cdc_msc_hid_freertos/src/msc_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include "tusb.h"
#include "app.h"
// define the buffer to be place in USB/DMA memory with correct alignment/cache line size
CFG_TUH_MEM_SECTION static struct {
TUH_EPBUF_TYPE_DEF(scsi_inquiry_resp_t, inquiry);
} scsi_resp;
void msc_app_init(void) {
// nothing to do
}
static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) {
msc_cbw_t const *cbw = cb_data->cbw;
msc_csw_t const *csw = cb_data->csw;
if (csw->status != 0) {
printf("Inquiry failed\r\n");
return false;
}
// Print out Vendor ID, Product ID and Rev
printf("%.8s %.16s rev %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, scsi_resp.inquiry.product_rev);
// Get capacity of device
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024 * 1024) / block_size));
printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size);
return true;
}
//------------- IMPLEMENTATION -------------//
void tuh_msc_mount_cb(uint8_t dev_addr) {
printf("A MassStorage device is mounted\r\n");
uint8_t const lun = 0;
tuh_msc_inquiry(dev_addr, lun, &scsi_resp.inquiry, inquiry_complete_cb, 0);
}
void tuh_msc_umount_cb(uint8_t dev_addr) {
(void) dev_addr;
printf("A MassStorage device is unmounted\r\n");
}
================================================
FILE: examples/host/cdc_msc_hid_freertos/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_FREERTOS
#endif
// Espressif IDF requires "freertos/" prefix in include path
#ifdef ESP_PLATFORM
#define CFG_TUSB_OS_INC_PATH freertos/
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// Host Configuration
//--------------------------------------------------------------------
// Enable Host stack
#define CFG_TUH_ENABLED 1
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
#define BOARD_TUH_RHPORT 1
#endif
#endif
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
//------------------------- Board Specific --------------------------
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 1 // number of supported hubs
#define CFG_TUH_CDC 1 // number of supported CDC devices. also activates CDC ACM
#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_PL2303 1 // PL2303 Serial. PL2303 is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_MSC 1
#define CFG_TUH_VENDOR 0
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- HID -------------//
#define CFG_TUH_HID_EPIN_BUFSIZE 64
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
//------------- CDC -------------//
// Set Line Control state on enumeration/mounted:
// DTR ( bit 0), RTS (bit 1)
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS)
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
#ifdef __cplusplus
}
#endif
#endif /* TUSB_CONFIG_H_ */
================================================
FILE: examples/host/device_info/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(device_info C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_host_example(${PROJECT_NAME} noos)
================================================
FILE: examples/host/device_info/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/device_info/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += \
src/main.c
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/host/device_info/only.txt
================================================
family:espressif
family:hpmicro
family:samd21
family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:LPC54
mcu:LPC55
mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RAXXX
mcu:RP2040
mcu:RW61X
mcu:RX65X
mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
mcu:STM32G0
mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
mcu:STM32U3
mcu:STM32U5
================================================
FILE: examples/host/device_info/skip.txt
================================================
board:lpcxpresso54114
================================================
FILE: examples/host/device_info/src/CMakeLists.txt
================================================
# This file is for ESP-IDF only
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES boards tinyusb_src)
================================================
FILE: examples/host/device_info/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/* Host example will get device descriptors of attached devices and print it out via uart/rtt (logger) as follows:
* Device 1: ID 046d:c52f SN 11223344
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 0200
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x046d
idProduct 0xc52f
bcdDevice 2200
iManufacturer 1 Logitech
iProduct 2 USB Receiver
iSerialNumber 0
bNumConfigurations 1
*
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
// English
#define LANGUAGE_ID 0x0409
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
};
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
// Declare for buffer for usb transfer, may need to be in USB/DMA section and
// multiple of dcache line size if dcache is enabled (for some ports).
CFG_TUH_MEM_SECTION struct {
TUH_EPBUF_TYPE_DEF(tusb_desc_device_t, device);
TUH_EPBUF_DEF(serial, 64*sizeof(uint16_t));
TUH_EPBUF_DEF(buf, 128*sizeof(uint16_t));
} desc;
void led_blinking_task(void* param);
static void print_utf16(uint16_t* temp_buf, size_t buf_len);
#if CFG_TUSB_OS == OPT_OS_FREERTOS
void init_freertos_task(void);
#endif
//--------------------------------------------------------------------
// Main
//--------------------------------------------------------------------
static void init_tinyusb(void) {
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
board_init_after_tusb();
}
int main(void) {
board_init();
printf("TinyUSB Device Info Example\r\n");
#if CFG_TUSB_OS == OPT_OS_FREERTOS
init_freertos_task();
#else
board_delay(100); // wait for uart to be ready
init_tinyusb();
while (1) {
tuh_task(); // tinyusb host task
led_blinking_task(NULL);
}
#endif
}
/*------------- TinyUSB Callbacks -------------*/
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
blink_interval_ms = BLINK_MOUNTED;
// Get Device Descriptor
uint8_t xfer_result = tuh_descriptor_get_device_sync(daddr, &desc.device, 18);
if (XFER_RESULT_SUCCESS != xfer_result) {
printf("Failed to get device descriptor\r\n");
return;
}
printf("Device %u: ID %04x:%04x SN ", daddr, desc.device.idVendor, desc.device.idProduct);
xfer_result = XFER_RESULT_FAILED;
if (desc.device.iSerialNumber != 0) {
xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial));
}
if (XFER_RESULT_SUCCESS != xfer_result) {
uint16_t* serial = (uint16_t*)(uintptr_t) desc.serial;
serial[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * 1 + 2));
serial[1] = '0'; // simply 0
serial[2] = 0;
}
print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2);
printf("\r\n");
printf("Device Descriptor:\r\n");
printf(" bLength %u\r\n", desc.device.bLength);
printf(" bDescriptorType %u\r\n", desc.device.bDescriptorType);
printf(" bcdUSB %04x\r\n", desc.device.bcdUSB);
printf(" bDeviceClass %u\r\n", desc.device.bDeviceClass);
printf(" bDeviceSubClass %u\r\n", desc.device.bDeviceSubClass);
printf(" bDeviceProtocol %u\r\n", desc.device.bDeviceProtocol);
printf(" bMaxPacketSize0 %u\r\n", desc.device.bMaxPacketSize0);
printf(" idVendor 0x%04x\r\n", desc.device.idVendor);
printf(" idProduct 0x%04x\r\n", desc.device.idProduct);
printf(" bcdDevice %04x\r\n", desc.device.bcdDevice);
// Get String descriptor using Sync API
printf(" iManufacturer %u ", desc.device.iManufacturer);
if (desc.device.iManufacturer != 0) {
xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
if (XFER_RESULT_SUCCESS == xfer_result) {
print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
}
}
printf("\r\n");
printf(" iProduct %u ", desc.device.iProduct);
if (desc.device.iProduct != 0) {
xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
if (XFER_RESULT_SUCCESS == xfer_result) {
print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
}
}
printf("\r\n");
printf(" iSerialNumber %u ", desc.device.iSerialNumber);
printf("%s\r\n", (char*)desc.serial); // serial is already to UTF-8
printf(" bNumConfigurations %u\r\n", desc.device.bNumConfigurations);
}
// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t daddr) {
blink_interval_ms = BLINK_NOT_MOUNTED;
printf("Device removed, address = %d\r\n", daddr);
}
//--------------------------------------------------------------------+
// String Descriptor Helper
//--------------------------------------------------------------------+
static void _convert_utf16le_to_utf8(const uint16_t* utf16, size_t utf16_len, uint8_t* utf8, size_t utf8_len) {
// TODO: Check for runover.
(void) utf8_len;
// Get the UTF-16 length out of the data itself.
for (size_t i = 0; i < utf16_len; i++) {
uint16_t chr = utf16[i];
if (chr < 0x80) {
*utf8++ = chr & 0xffu;
} else if (chr < 0x800) {
*utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
} else {
// TODO: Verify surrogate.
*utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
*utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
}
// TODO: Handle UTF-16 code points that take two entries.
}
}
// Count how many bytes a utf-16-le encoded string will take in utf-8.
static int _count_utf8_bytes(const uint16_t* buf, size_t len) {
size_t total_bytes = 0;
for (size_t i = 0; i < len; i++) {
uint16_t chr = buf[i];
if (chr < 0x80) {
total_bytes += 1;
} else if (chr < 0x800) {
total_bytes += 2;
} else {
total_bytes += 3;
}
// TODO: Handle UTF-16 code points that take two entries.
}
return (int) total_bytes;
}
static void print_utf16(uint16_t* temp_buf, size_t buf_len) {
if ((temp_buf[0] & 0xff) == 0) return; // empty
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t*) temp_buf, sizeof(uint16_t) * buf_len);
((uint8_t*) temp_buf)[utf8_len] = '\0';
printf("%s", (char*) temp_buf);
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void* param) {
(void) param;
static uint32_t start_ms = 0;
static bool led_state = false;
while (1) {
#if CFG_TUSB_OS == OPT_OS_FREERTOS
vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS);
#else
if (tusb_time_millis_api() - start_ms < blink_interval_ms) {
return; // not enough time
}
#endif
start_ms += blink_interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
}
//--------------------------------------------------------------------+
// FreeRTOS
//--------------------------------------------------------------------+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
#ifdef ESP_PLATFORM
#define USB_STACK_SIZE 4096
#else
// Increase stack size when debug log is enabled
#define USB_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
#endif
// static task
#if configSUPPORT_STATIC_ALLOCATION
StackType_t blinky_stack[BLINKY_STACK_SIZE];
StaticTask_t blinky_taskdef;
StackType_t usb_stack[USB_STACK_SIZE];
StaticTask_t usb_taskdef;
#endif
#ifdef ESP_PLATFORM
void app_main(void) {
main();
}
#endif
void usb_host_task(void *param) {
(void) param;
board_delay(100); // wait for uart to be ready
init_tinyusb();
while (1) {
tuh_task();
}
}
void init_freertos_task(void) {
#if configSUPPORT_STATIC_ALLOCATION
xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef);
xTaskCreateStatic(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_stack, &usb_taskdef);
#else
xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
#endif
// only start scheduler for non-espressif mcu
#ifndef ESP_PLATFORM
vTaskStartScheduler();
#endif
}
#endif
================================================
FILE: examples/host/device_info/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
// Espressif IDF requires "freertos/" prefix in include path
#ifdef ESP_PLATFORM
#define CFG_TUSB_OS_INC_PATH freertos/
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// Host Configuration
//--------------------------------------------------------------------
// Enable Host stack
#define CFG_TUH_ENABLED 1
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
#define BOARD_TUH_RHPORT 1
#endif
#endif
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
//------------------------- Board Specific --------------------------
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
// only hub class is enabled
#define CFG_TUH_HUB 1
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: examples/host/hid_controller/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(hid_controller C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_host_example(${PROJECT_NAME} noos)
================================================
FILE: examples/host/hid_controller/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/hid_controller/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += \
src/hid_app.c \
src/main.c
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/host/hid_controller/only.txt
================================================
family:hpmicro
family:samd21
family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:LPC54
mcu:LPC55
mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RAXXX
mcu:RP2040
mcu:RW61X
mcu:RX65X
mcu:STM32F4
mcu:STM32F7
mcu:STM32G0
mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
mcu:STM32U3
mcu:STM32U5
================================================
FILE: examples/host/hid_controller/skip.txt
================================================
board:lpcxpresso54114
================================================
FILE: examples/host/hid_controller/src/app.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2025 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef TUSB_TINYUSB_EXAMPLES_APP_H
#define TUSB_TINYUSB_EXAMPLES_APP_H
#include
void hid_app_task(void);
#endif
================================================
FILE: examples/host/hid_controller/src/hid_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2021, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
#include "app.h"
/* From https://www.kernel.org/doc/html/latest/input/gamepad.html
____________________________ __
/ [__ZL__] [__ZR__] \ |
/ [__ TL __] [__ TR __] \ | Front Triggers
__/________________________________\__ __|
/ _ \ |
/ /\ __ (N) \ |
/ || __ |MO| __ _ _ \ | Main Pad
| <===DP===> |SE| |ST| (W) -|- (E) | |
\ || ___ ___ _ / |
/\ \/ / \ / \ (S) /\ __|
/ \________ | LS | ____ | RS | ________/ \ |
| / \ \___/ / \ \___/ / \ | | Control Sticks
| / \_____/ \_____/ \ | __|
| / \ |
\_____/ \_____/
|________|______| |______|___________|
D-Pad Left Right Action Pad
Stick Stick
|_____________|
Menu Pad
Most gamepads have the following features:
- Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST.
- D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right.
- Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START.
- Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also
provide a digital button if you press them.
- Triggers are located on the upper-side of the pad in vertical direction. The upper buttons
are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right.
- Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors.
*/
// Sony DS4 report layout detail https://www.psdevwiki.com/ps4/DS4-USB
typedef struct TU_ATTR_PACKED
{
uint8_t x, y, z, rz; // joystick
struct {
uint8_t dpad : 4; // (hat format, 0x08 is released, 0=N, 1=NE, 2=E, 3=SE, 4=S, 5=SW, 6=W, 7=NW)
uint8_t square : 1; // west
uint8_t cross : 1; // south
uint8_t circle : 1; // east
uint8_t triangle : 1; // north
};
struct {
uint8_t l1 : 1;
uint8_t r1 : 1;
uint8_t l2 : 1;
uint8_t r2 : 1;
uint8_t share : 1;
uint8_t option : 1;
uint8_t l3 : 1;
uint8_t r3 : 1;
};
struct {
uint8_t ps : 1; // playstation button
uint8_t tpad : 1; // track pad click
uint8_t counter : 6; // +1 each report
};
uint8_t l2_trigger; // 0 released, 0xff fully pressed
uint8_t r2_trigger; // as above
// uint16_t timestamp;
// uint8_t battery;
//
// int16_t gyro[3]; // x, y, z;
// int16_t accel[3]; // x, y, z
// there is still lots more info
} sony_ds4_report_t;
typedef struct TU_ATTR_PACKED {
// First 16 bits set what data is pertinent in this structure (1 = set; 0 = not set)
uint8_t set_rumble : 1;
uint8_t set_led : 1;
uint8_t set_led_blink : 1;
uint8_t set_ext_write : 1;
uint8_t set_left_volume : 1;
uint8_t set_right_volume : 1;
uint8_t set_mic_volume : 1;
uint8_t set_speaker_volume : 1;
uint8_t set_flags2;
uint8_t reserved;
uint8_t motor_right;
uint8_t motor_left;
uint8_t lightbar_red;
uint8_t lightbar_green;
uint8_t lightbar_blue;
uint8_t lightbar_blink_on;
uint8_t lightbar_blink_off;
uint8_t ext_data[8];
uint8_t volume_left;
uint8_t volume_right;
uint8_t volume_mic;
uint8_t volume_speaker;
uint8_t other[9];
} sony_ds4_output_report_t;
static bool ds4_mounted = false;
static uint8_t ds4_dev_addr = 0;
static uint8_t ds4_instance = 0;
static uint8_t motor_left = 0;
static uint8_t motor_right = 0;
// check if device is Sony DualShock 4
static inline bool is_sony_ds4(uint8_t dev_addr)
{
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
|| (vid == 0x0f0d && pid == 0x005e) // Hori FC4
|| (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
|| (vid == 0x1f4f && pid == 0x1002) // ASW GG xrd controller
);
}
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
void hid_app_task(void)
{
if (ds4_mounted)
{
const uint32_t interval_ms = 200;
static uint32_t start_ms = 0;
uint32_t current_time_ms = tusb_time_millis_api();
if ( current_time_ms - start_ms >= interval_ms)
{
start_ms = current_time_ms;
sony_ds4_output_report_t output_report = {0};
output_report.set_rumble = 1;
output_report.motor_left = motor_left;
output_report.motor_right = motor_right;
tuh_hid_send_report(ds4_dev_addr, ds4_instance, 5, &output_report, sizeof(output_report));
}
}
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
{
(void)desc_report;
(void)desc_len;
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
printf("VID = %04x, PID = %04x\r\n", vid, pid);
// Sony DualShock 4 [CUH-ZCT2x]
if ( is_sony_ds4(dev_addr) )
{
if (!ds4_mounted)
{
ds4_dev_addr = dev_addr;
ds4_instance = instance;
motor_left = 0;
motor_right = 0;
ds4_mounted = true;
}
// request to receive report
// tuh_hid_report_received_cb() will be invoked when report is available
if ( !tuh_hid_receive_report(dev_addr, instance) )
{
printf("Error: cannot request to receive report\r\n");
}
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
{
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
if (ds4_mounted && ds4_dev_addr == dev_addr && ds4_instance == instance)
{
ds4_mounted = false;
}
}
// check if different than 2
static inline bool diff_than_2(uint8_t x, uint8_t y) {
return (x - y > 2) || (y - x > 2);
}
// check if 2 reports are different enough
static bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2) {
bool result;
// x, y, z, rz must different than 2 to be counted
result = diff_than_2(rpt1->x, rpt2->x) || diff_than_2(rpt1->y , rpt2->y ) ||
diff_than_2(rpt1->z, rpt2->z) || diff_than_2(rpt1->rz, rpt2->rz);
// check the rest with mem compare
result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-6);
return result;
}
static void process_sony_ds4(uint8_t const* report, uint16_t len)
{
(void)len;
const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" };
// previous report used to compare for changes
static sony_ds4_report_t prev_report = { 0 };
uint8_t const report_id = report[0];
report++;
len--;
// all buttons state is stored in ID 1
if (report_id == 1)
{
sony_ds4_report_t ds4_report;
memcpy(&ds4_report, report, sizeof(ds4_report));
// counter is +1, assign to make it easier to compare 2 report
prev_report.counter = ds4_report.counter;
// only print if changes since it is polled ~ 5ms
// Since count+1 after each report and x, y, z, rz fluctuate within 1 or 2
// We need more than memcmp to check if report is different enough
if ( diff_report(&prev_report, &ds4_report) )
{
printf("(x, y, z, rz) = (%u, %u, %u, %u)\r\n", ds4_report.x, ds4_report.y, ds4_report.z, ds4_report.rz);
printf("DPad = %s ", dpad_str[ds4_report.dpad]);
if (ds4_report.square ) printf("Square ");
if (ds4_report.cross ) printf("Cross ");
if (ds4_report.circle ) printf("Circle ");
if (ds4_report.triangle ) printf("Triangle ");
if (ds4_report.l1 ) printf("L1 ");
if (ds4_report.r1 ) printf("R1 ");
if (ds4_report.l2 ) printf("L2 ");
if (ds4_report.r2 ) printf("R2 ");
if (ds4_report.share ) printf("Share ");
if (ds4_report.option ) printf("Option ");
if (ds4_report.l3 ) printf("L3 ");
if (ds4_report.r3 ) printf("R3 ");
if (ds4_report.ps ) printf("PS ");
if (ds4_report.tpad ) printf("TPad ");
printf("\r\n");
}
// The left and right triggers control the intensity of the left and right rumble motors
motor_left = ds4_report.l2_trigger;
motor_right = ds4_report.r2_trigger;
prev_report = ds4_report;
}
}
// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
if (is_sony_ds4(dev_addr)) {
process_sony_ds4(report, len);
}
// continue to request to receive report
if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
================================================
FILE: examples/host/hid_controller/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/* This example current worked and tested with following controller
* - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
#include "app.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Host HID Controller Example\r\n");
printf("Note: Events only displayed for explicit supported controllers\r\n");
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
board_init_after_tusb();
while (1) {
// tinyusb host task
tuh_task();
led_blinking_task();
hid_app_task();
}
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if ( tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time
start_ms += interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
================================================
FILE: examples/host/hid_controller/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// Host Configuration
//--------------------------------------------------------------------
// Enable Host stack
#define CFG_TUH_ENABLED 1
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
#define BOARD_TUH_RHPORT 1
#endif
#endif
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
//------------------------- Board Specific --------------------------
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 0
#define CFG_TUH_CDC 0
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_MSC 0
#define CFG_TUH_VENDOR 0
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- HID -------------//
#define CFG_TUH_HID_EP_BUFSIZE 64
#ifdef __cplusplus
}
#endif
#endif /* TUSB_CONFIG_H_ */
================================================
FILE: examples/host/midi_rx/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(midi_rx C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_host_example(${PROJECT_NAME} noos)
================================================
FILE: examples/host/midi_rx/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/midi_rx/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += \
src/main.c
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/host/midi_rx/only.txt
================================================
family:hpmicro
family:samd21
family:samd5x_e5x
mcu:CH32V20X
mcu:ESP32P4
mcu:ESP32S2
mcu:ESP32S3
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:LPC54
mcu:LPC55
mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RAXXX
mcu:RP2040
mcu:RW61X
mcu:RX65X
mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
mcu:STM32G0
mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
mcu:STM32U3
mcu:STM32U5
================================================
FILE: examples/host/midi_rx/skip.txt
================================================
board:lpcxpresso54114
================================================
FILE: examples/host/midi_rx/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
// STATIC GLOBALS DECLARATION
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);
void midi_host_rx_task(void);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Host MIDI Example\r\n");
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
while (1) {
tuh_task();
led_blinking_task();
midi_host_rx_task();
}
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if (tusb_time_millis_api() - start_ms < interval_ms) return;// not enough time
start_ms += interval_ms;
board_led_write(led_state);
led_state = 1 - led_state;// toggle
}
//--------------------------------------------------------------------+
// MIDI host receive task
//--------------------------------------------------------------------+
void midi_host_rx_task(void) {
// nothing to do, we just print out received data in callback
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
// Invoked when device with MIDI interface is mounted.
void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) {
printf("MIDI Interface Index = %u, Address = %u, Number of RX cables = %u, Number of TX cables = %u\r\n",
idx, mount_cb_data->daddr, mount_cb_data->rx_cable_count, mount_cb_data->tx_cable_count);
}
// Invoked when device with hid interface is un-mounted
void tuh_midi_umount_cb(uint8_t idx) {
printf("MIDI Interface Index = %u is unmounted\r\n", idx);
}
void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) {
if (xferred_bytes == 0) {
return;
}
uint8_t buffer[48];
uint8_t cable_num = 0;
uint32_t bytes_read = tuh_midi_stream_read(idx, &cable_num, buffer, sizeof(buffer));
printf("Cable %u rx: ", cable_num);
for (uint32_t i = 0; i < bytes_read; i++) {
printf("%02X ", buffer[i]);
}
printf("\r\n");
}
void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) {
(void) idx;
(void) xferred_bytes;
}
================================================
FILE: examples/host/midi_rx/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
// Espressif IDF requires "freertos/" prefix in include path
#ifdef ESP_PLATFORM
#define CFG_TUSB_OS_INC_PATH freertos/
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// Host Configuration
//--------------------------------------------------------------------
// Enable Host stack
#define CFG_TUH_ENABLED 1
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
#define BOARD_TUH_RHPORT 1
#endif
#endif
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
//------------------------- Board Specific --------------------------
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 1
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
#define CFG_TUH_MIDI CFG_TUH_DEVICE_MAX
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: examples/host/msc_file_explorer/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(msc_file_explorer C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
${TOP}/lib/fatfs/source/ff.c
${TOP}/lib/fatfs/source/ffsystem.c
${TOP}/lib/fatfs/source/ffunicode.c
)
# Suppress warnings on fatfs
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_source_files_properties(${TOP}/lib/fatfs/source/ff.c PROPERTIES
COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual"
)
endif ()
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
${TOP}/lib/fatfs/source
${TOP}/lib/embedded-cli
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_host_example(${PROJECT_NAME} noos)
================================================
FILE: examples/host/msc_file_explorer/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/host/msc_file_explorer/Makefile
================================================
include ../../../hw/bsp/family_support.mk
FATFS_PATH = lib/fatfs/source
INC += \
src \
$(TOP)/$(FATFS_PATH) \
$(TOP)/lib/embedded-cli \
# Example source
EXAMPLE_SOURCE = \
src/main.c \
src/msc_app.c \
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
# FatFS source
SRC_C += \
$(FATFS_PATH)/ff.c \
$(FATFS_PATH)/ffsystem.c \
$(FATFS_PATH)/ffunicode.c \
# suppress warning caused by fatfs
CFLAGS_GCC += -Wno-error=cast-qual
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/host/msc_file_explorer/only.txt
================================================
family:hpmicro
family:samd21
family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:LPC54
mcu:LPC55
mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RAXXX
mcu:RP2040
mcu:RW61X
mcu:RX65X
mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
mcu:STM32G0
mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
mcu:STM32U3
mcu:STM32U5
================================================
FILE: examples/host/msc_file_explorer/skip.txt
================================================
board:lpcxpresso54114
================================================
FILE: examples/host/msc_file_explorer/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/* Example to show how to navigate mass storage device with built-in command line.
* Type help for list of supported commands and syntax (mostly linux commands)
> help
* help
Print list of commands
* cat
Usage: cat [FILE]...
Concatenate FILE(s) to standard output..
* cd
Usage: cd [DIR]...
Change the current directory to DIR.
* cp
Usage: cp SOURCE DEST
Copy SOURCE to DEST.
* ls
Usage: ls [DIR]...
List information about the FILEs (the current directory by default).
* pwd
Usage: pwd
Print the name of the current working directory.
* mkdir
Usage: mkdir DIR...
Create the DIRECTORY(ies), if they do not already exist..
* mv
Usage: mv SOURCE DEST...
Rename SOURCE to DEST.
* rm
Usage: rm [FILE]...
Remove (unlink) the FILE(s).
*/
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
#include "msc_app.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Host MassStorage Explorer Example\r\n");
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
board_init_after_tusb();
msc_app_init();
while (1) {
// tinyusb host task
tuh_task();
msc_app_task();
led_blinking_task();
}
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
void tuh_mount_cb(uint8_t dev_addr) {
(void) dev_addr;
}
void tuh_umount_cb(uint8_t dev_addr) {
(void) dev_addr;
}
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
void led_blinking_task(void) {
const uint32_t interval_ms = 1000;
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if (tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time
start_ms += interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
================================================
FILE: examples/host/msc_file_explorer/src/msc_app.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include "tusb.h"
#include "bsp/board_api.h"
#include "ff.h"
#include "diskio.h"
// lib/embedded-cli
#define EMBEDDED_CLI_IMPL
#include "embedded_cli.h"
#include "msc_app.h"
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
//------------- embedded-cli -------------//
#define CLI_BUFFER_SIZE 512
#define CLI_RX_BUFFER_SIZE 16
#define CLI_CMD_BUFFER_SIZE 64
#define CLI_HISTORY_SIZE 32
#define CLI_BINDING_COUNT 8
static EmbeddedCli *_cli;
static CLI_UINT cli_buffer[BYTES_TO_CLI_UINTS(CLI_BUFFER_SIZE)];
//------------- Elm Chan FatFS -------------//
static CFG_TUH_MEM_SECTION FATFS fatfs[CFG_TUH_DEVICE_MAX]; // for simplicity only support 1 LUN per device
static volatile bool _disk_busy[CFG_TUH_DEVICE_MAX];
static CFG_TUH_MEM_SECTION FIL file1, file2;
static CFG_TUH_MEM_SECTION uint8_t rw_buf[512];
// define the buffer to be place in USB/DMA memory with correct alignment/cache line size
CFG_TUH_MEM_SECTION static struct {
TUH_EPBUF_TYPE_DEF(scsi_inquiry_resp_t, inquiry);
} scsi_resp;
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
bool cli_init(void);
bool msc_app_init(void) {
for (size_t i = 0; i < CFG_TUH_DEVICE_MAX; i++) {
_disk_busy[i] = false;
}
// disable stdout buffered for echoing typing command
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
setbuf(stdout, NULL);
#endif
cli_init();
return true;
}
void msc_app_task(void) {
if (!_cli) {
return;
}
int ch = board_getchar();
if (ch > 0) {
while (ch > 0) {
embeddedCliReceiveChar(_cli, (char)ch);
ch = board_getchar();
}
embeddedCliProcess(_cli);
}
}
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
static bool inquiry_complete_cb(uint8_t dev_addr, const tuh_msc_complete_data_t *cb_data) {
const msc_cbw_t *cbw = cb_data->cbw;
const msc_csw_t *csw = cb_data->csw;
if (csw->status != 0) {
printf("Inquiry failed\r\n");
return false;
}
// Print out Vendor ID, Product ID and Rev
printf("%.8s %.16s rev %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id,
scsi_resp.inquiry.product_rev);
// Get capacity of device
const uint32_t block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
const uint32_t block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024 * 1024) / block_size));
// printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
// For simplicity: we only mount 1 LUN per device
const uint8_t drive_num = dev_addr - 1;
char drive_path[3] = "0:";
drive_path[0] += drive_num;
if (f_mount(&fatfs[drive_num], drive_path, 1) != FR_OK) {
printf("mount failed\r\n");
return true;
}
// change to newly mounted drive
f_chdrive(drive_path);
FRESULT rc = f_chdir("/");
if (rc != FR_OK) {
printf("chdir failed: %d\r\n", rc);
}
// print the drive label
// char label[34];
// if ( FR_OK == f_getlabel(drive_path, label, NULL) )
// {
// puts(label);
// }
return true;
}
//------------- IMPLEMENTATION -------------//
void tuh_msc_mount_cb(uint8_t dev_addr) {
printf("A MassStorage device (addr = %u) is mounted\r\n", dev_addr);
const uint8_t lun = 0;
tuh_msc_inquiry(dev_addr, lun, &scsi_resp.inquiry, inquiry_complete_cb, 0);
}
void tuh_msc_umount_cb(uint8_t dev_addr) {
printf("A MassStorage device is unmounted\r\n");
const uint8_t drive_num = dev_addr - 1;
char drive_path[3] = "0:";
drive_path[0] += drive_num;
f_unmount(drive_path);
// if ( phy_disk == f_get_current_drive() )
// { // active drive is unplugged --> change to other drive
// for(uint8_t i=0; icliBuffer = cli_buffer;
config->cliBufferSize = CLI_BUFFER_SIZE;
config->rxBufferSize = CLI_RX_BUFFER_SIZE;
config->cmdBufferSize = CLI_CMD_BUFFER_SIZE;
config->historyBufferSize = CLI_HISTORY_SIZE;
config->maxBindingCount = CLI_BINDING_COUNT;
TU_ASSERT(embeddedCliRequiredSize(config) <= CLI_BUFFER_SIZE);
_cli = embeddedCliNew(config);
TU_ASSERT(_cli != NULL);
_cli->writeChar = cli_write_char;
embeddedCliAddBinding(_cli,
(CliCommandBinding){"cat", "Usage: cat [FILE]...\r\n\tConcatenate FILE(s) to standard output..",
true, NULL, cli_cmd_cat});
embeddedCliAddBinding(_cli, (CliCommandBinding){"cd", "Usage: cd [DIR]...\r\n\tChange the current directory to DIR.",
true, NULL, cli_cmd_cd});
embeddedCliAddBinding(_cli, (CliCommandBinding){"cp", "Usage: cp SOURCE DEST\r\n\tCopy SOURCE to DEST.", true, NULL,
cli_cmd_cp});
embeddedCliAddBinding(_cli, (CliCommandBinding){"ls",
"Usage: ls [DIR]...\r\n\tList information about the FILEs (the "
"current directory by default).",
true, NULL, cli_cmd_ls});
embeddedCliAddBinding(_cli,
(CliCommandBinding){"pwd", "Usage: pwd\r\n\tPrint the name of the current working directory.",
true, NULL, cli_cmd_pwd});
embeddedCliAddBinding(_cli, (CliCommandBinding){"mkdir",
"Usage: mkdir DIR...\r\n\tCreate the DIRECTORY(ies), if they do not "
"already exist..",
true, NULL, cli_cmd_mkdir});
embeddedCliAddBinding(_cli, (CliCommandBinding){"mv", "Usage: mv SOURCE DEST...\r\n\tRename SOURCE to DEST.", true,
NULL, cli_cmd_mv});
embeddedCliAddBinding(_cli, (CliCommandBinding){"rm", "Usage: rm [FILE]...\r\n\tRemove (unlink) the FILE(s).", true,
NULL, cli_cmd_rm});
return true;
}
void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
// need at least 1 argument
if (argc == 0) {
printf("invalid arguments\r\n");
return;
}
for (uint16_t i = 0; i < argc; i++) {
FIL *fi = &file1;
const char *fpath = embeddedCliGetToken(args, i + 1); // token count from 1
if (FR_OK != f_open(fi, fpath, FA_READ)) {
printf("%s: No such file or directory\r\n", fpath);
} else {
UINT count = 0;
while ((FR_OK == f_read(fi, rw_buf, sizeof(rw_buf), &count)) && (count > 0)) {
for (UINT c = 0; c < count; c++) {
const uint8_t ch = rw_buf[c];
if (isprint(ch) || iscntrl(ch)) {
putchar(ch);
} else {
putchar('.');
}
}
}
}
f_close(fi);
}
}
void cli_cmd_cd(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
// only support 1 argument
if (argc != 1) {
printf("invalid arguments\r\n");
return;
}
// default is current directory
const char *dpath = args;
if (FR_OK != f_chdir(dpath)) {
printf("%s: No such file or directory\r\n", dpath);
return;
}
}
void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
if (argc != 2) {
printf("invalid arguments\r\n");
return;
}
// default is current directory
const char *src = embeddedCliGetToken(args, 1);
const char *dst = embeddedCliGetToken(args, 2);
FIL *f_src = &file1;
FIL *f_dst = &file2;
if (FR_OK != f_open(f_src, src, FA_READ)) {
printf("cannot stat '%s': No such file or directory\r\n", src);
return;
}
if (FR_OK != f_open(f_dst, dst, FA_WRITE | FA_CREATE_ALWAYS)) {
printf("cannot create '%s'\r\n", dst);
return;
} else {
UINT rd_count = 0;
while ((FR_OK == f_read(f_src, rw_buf, sizeof(rw_buf), &rd_count)) && (rd_count > 0)) {
UINT wr_count = 0;
if (FR_OK != f_write(f_dst, rw_buf, rd_count, &wr_count)) {
printf("cannot write to '%s'\r\n", dst);
break;
}
}
}
f_close(f_src);
f_close(f_dst);
}
void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
// only support 1 argument
if (argc > 1) {
printf("invalid arguments\r\n");
return;
}
// default is current directory
const char *dpath = ".";
if (argc) {
dpath = args;
}
DIR dir;
if (FR_OK != f_opendir(&dir, dpath)) {
printf("cannot access '%s': No such file or directory\r\n", dpath);
return;
}
FILINFO fno;
while ((f_readdir(&dir, &fno) == FR_OK) && (fno.fname[0] != 0)) {
if (fno.fname[0] != '.') // ignore . and .. entry
{
if (fno.fattrib & AM_DIR) {
// directory
printf("/%s\r\n", fno.fname);
} else {
printf("%-40s", fno.fname);
if (fno.fsize < 1024) {
printf("%" PRIu32 " B\r\n", fno.fsize);
} else {
printf("%" PRIu32 " KB\r\n", fno.fsize / 1024);
}
}
}
}
f_closedir(&dir);
}
void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
if (argc != 0) {
printf("invalid arguments\r\n");
return;
}
char path[256];
if (FR_OK != f_getcwd(path, sizeof(path))) {
printf("cannot get current working directory\r\n");
}
puts(path);
}
void cli_cmd_mkdir(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
// only support 1 argument
if (argc != 1) {
printf("invalid arguments\r\n");
return;
}
// default is current directory
const char *dpath = args;
if (FR_OK != f_mkdir(dpath)) {
printf("%s: cannot create this directory\r\n", dpath);
return;
}
}
void cli_cmd_mv(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
if (argc != 2) {
printf("invalid arguments\r\n");
return;
}
// default is current directory
const char *src = embeddedCliGetToken(args, 1);
const char *dst = embeddedCliGetToken(args, 2);
if (FR_OK != f_rename(src, dst)) {
printf("cannot mv %s to %s\r\n", src, dst);
return;
}
}
void cli_cmd_rm(EmbeddedCli *cli, char *args, void *context) {
(void)cli;
(void)context;
uint16_t argc = embeddedCliGetTokenCount(args);
// need at least 1 argument
if (argc == 0) {
printf("invalid arguments\r\n");
return;
}
for (uint16_t i = 0; i < argc; i++) {
const char *fpath = embeddedCliGetToken(args, i + 1); // token count from 1
if (FR_OK != f_unlink(fpath)) {
printf("cannot remove '%s': No such file or directory\r\n", fpath);
}
}
}
================================================
FILE: examples/host/msc_file_explorer/src/msc_app.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2025 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef MSC_APP_H
#define MSC_APP_H
#include
#include
bool msc_app_init(void);
void msc_app_task(void);
#endif
================================================
FILE: examples/host/msc_file_explorer/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Common Configuration
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// Host Configuration
//--------------------------------------------------------------------
// Enable Host stack
#define CFG_TUH_ENABLED 1
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
#define BOARD_TUH_RHPORT 1
#endif
#endif
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
//------------------------- Board Specific --------------------------
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif
//--------------------------------------------------------------------
// Driver Configuration
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 1 // number of supported hubs
#define CFG_TUH_MSC 1
#define CFG_TUH_CDC 0
#define CFG_TUH_HID 0 // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_VENDOR 0
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- MSC -------------//
#define CFG_TUH_MSC_MAXLUN 4 // typical for most card reader
#ifdef __cplusplus
}
#endif
#endif /* TUSB_CONFIG_H_ */
================================================
FILE: examples/typec/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
project(tinyusb_host_examples C CXX ASM)
family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
# family_add_subdirectory will filter what to actually add based on selected FAMILY
family_add_subdirectory(power_delivery)
================================================
FILE: examples/typec/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/typec/power_delivery/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
project(power_delivery C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT_NAME})
# Example source
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
)
# Example include
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_device_example(${PROJECT_NAME} noos)
================================================
FILE: examples/typec/power_delivery/CMakePresets.json
================================================
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}
================================================
FILE: examples/typec/power_delivery/Makefile
================================================
include ../../../hw/bsp/family_support.mk
INC += \
src \
# Example source
EXAMPLE_SOURCE += \
src/main.c
SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
include ../../../hw/bsp/family_rules.mk
================================================
FILE: examples/typec/power_delivery/only.txt
================================================
mcu:STM32G4
================================================
FILE: examples/typec/power_delivery/src/main.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include
#include
#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
// Voltage and current for selecting PDO
// DANGEROUS: Please make sure your board can withstand the voltage and current
// defined here. Otherwise, you may damage your board, smoke can come out
#define VOLTAGE_MAX_MV 5000 // maximum voltage in mV
#define CURRENT_MAX_MA 500 // maximum current in mA
#define CURRENT_OPERATING_MA 100 // operating current in mA
/* Blink pattern
* - 250 ms : button is not pressed
* - 1000 ms : button is pressed (and hold)
*/
enum {
BLINK_PRESSED = 250,
BLINK_UNPRESSED = 1000
};
static uint32_t blink_interval_ms = BLINK_UNPRESSED;
void led_blinking_task(void);
#define HELLO_STR "Hello from TinyUSB\r\n"
int main(void)
{
board_init();
board_led_write(true);
tuc_init(0, TUSB_TYPEC_PORT_SNK);
while (1) {
led_blinking_task();
// tinyusb typec task
tuc_task();
}
}
#ifdef ESP_PLATFORM
void app_main(void) {
main();
}
#endif
//--------------------------------------------------------------------+
// TypeC PD callbacks
//--------------------------------------------------------------------+
bool tuc_pd_data_received_cb(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end) {
switch (header->msg_type) {
case PD_DATA_SOURCE_CAP: {
printf("PD Source Capabilities\r\n");
// Examine source capability and select a suitable PDO (starting from 1 with safe5v)
uint8_t selected_pos = 1;
for(size_t i=0; in_data_obj; i++) {
TU_VERIFY(dobj < p_end);
uint32_t const pdo = tu_le32toh(tu_unaligned_read32(dobj));
switch ((pdo >> 30) & 0x03ul) {
case PD_PDO_TYPE_FIXED: {
pd_pdo_fixed_t const* fixed = (pd_pdo_fixed_t const*) &pdo;
uint32_t const voltage_mv = fixed->voltage_50mv*50;
uint32_t const current_ma = fixed->current_max_10ma*10;
printf("[Fixed] %"PRIu32" mV %"PRIu32" mA\r\n", voltage_mv, current_ma);
if (voltage_mv <= VOLTAGE_MAX_MV && current_ma >= CURRENT_MAX_MA) {
// Found a suitable PDO
selected_pos = i+1;
}
break;
}
case PD_PDO_TYPE_BATTERY:
break;
case PD_PDO_TYPE_VARIABLE:
break;
case PD_PDO_TYPE_APDO:
break;
}
dobj += 4;
}
//------------- Response with selected PDO -------------//
// Be careful and make sure your board can withstand the selected PDO
// voltage other than safe5v e.g 12v or 20v
printf("Selected PDO %u\r\n", selected_pos);
// Send request with selected PDO position as response to Source Cap
pd_rdo_fixed_variable_t rdo = {
.current_extremum_10ma = 50, // max 500mA
.current_operate_10ma = 30, // 300mA
.reserved = 0,
.epr_mode_capable = 0,
.unchunked_ext_msg_support = 0,
.no_usb_suspend = 0,
.usb_comm_capable = 1,
.capability_mismatch = 0,
.give_back_flag = 0, // exteremum is max
.object_position = selected_pos,
};
tuc_msg_request(rhport, &rdo);
break;
}
default: break;
}
return true;
}
bool tuc_pd_control_received_cb(uint8_t rhport, pd_header_t const* header) {
(void) rhport;
switch (header->msg_type) {
case PD_CTRL_ACCEPT:
printf("PD Request Accepted\r\n");
// preparing for power transition
break;
case PD_CTRL_REJECT:
printf("PD Request Rejected\r\n");
// try to negotiate further power
break;
case PD_CTRL_PS_READY:
printf("PD Power Ready\r\n");
// Source is ready to supply power
break;
default:
break;
}
return true;
}
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
void led_blinking_task(void)
{
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time
start_ms += blink_interval_ms;
board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
================================================
FILE: examples/typec/power_delivery/src/tusb_config.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// COMMON CONFIGURATION
//--------------------------------------------------------------------
// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif
#define CFG_TUD_ENABLED 0
#define CFG_TUH_ENABLED 0
// Enable TYPEC stack
#define CFG_TUC_ENABLED 1
// special example that doesn't enable device or host stack
// This can cause some TinyUSB API missing, this define hack to allow us to fill those API
// to pass the compilation process
#if CFG_TUD_ENABLED == 0
#define tud_int_handler(x)
#endif
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
// #define CFG_TUSB_DEBUG 0
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_SECTION
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
#ifdef __cplusplus
}
#endif
#endif /* TUSB_CONFIG_H_ */
================================================
FILE: examples/west.yml
================================================
manifest:
remotes:
- name: zephyrproject-rtos
url-base: https://github.com/zephyrproject-rtos
projects:
- name: zephyr
remote: zephyrproject-rtos
revision: main
path: zephyr
import: true
self:
path: .
================================================
FILE: hw/bsp/BoardPresets.json
================================================
{
"version": 6,
"configurePresets": [
{
"name": "default",
"hidden": true,
"description": "Configure preset for the ${presetName} board",
"generator": "Ninja Multi-Config",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_DEFAULT_BUILD_TYPE": "RelWithDebInfo",
"BOARD": "${presetName}"
}
},
{
"name": "default single config",
"hidden": true,
"description": "Configure preset for the ${presetName} board",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BOARD": "${presetName}"
}
},
{
"name": "adafruit_clue",
"inherits": "default"
},
{
"name": "adafruit_feather_rp2040_usb_host",
"inherits": "default"
},
{
"name": "adafruit_fruit_jam",
"inherits": "default"
},
{
"name": "adafruit_metro_rp2350",
"inherits": "default"
},
{
"name": "apard32690",
"inherits": "default"
},
{
"name": "arduino_nano33_ble",
"inherits": "default"
},
{
"name": "at32f403a_weact_blackpill",
"inherits": "default"
},
{
"name": "at_start_f402",
"inherits": "default"
},
{
"name": "at_start_f403a",
"inherits": "default"
},
{
"name": "at_start_f405",
"inherits": "default"
},
{
"name": "at_start_f407",
"inherits": "default"
},
{
"name": "at_start_f413",
"inherits": "default"
},
{
"name": "at_start_f415",
"inherits": "default"
},
{
"name": "at_start_f423",
"inherits": "default"
},
{
"name": "at_start_f425",
"inherits": "default"
},
{
"name": "at_start_f435",
"inherits": "default"
},
{
"name": "at_start_f437",
"inherits": "default"
},
{
"name": "at_start_f455",
"inherits": "default"
},
{
"name": "at_start_f456",
"inherits": "default"
},
{
"name": "at_start_f457",
"inherits": "default"
},
{
"name": "atsamd21_xpro",
"inherits": "default"
},
{
"name": "atsaml21_xpro",
"inherits": "default"
},
{
"name": "b_g474e_dpow1",
"inherits": "default"
},
{
"name": "b_u585i_iot2a",
"inherits": "default"
},
{
"name": "ch32v103r_r1_1v0",
"inherits": "default"
},
{
"name": "ch32v203c_r0_1v0",
"inherits": "default"
},
{
"name": "ch32v203g_r0_1v0",
"inherits": "default"
},
{
"name": "ch32v307v_r1_1v0",
"inherits": "default"
},
{
"name": "circuitplayground_bluefruit",
"inherits": "default"
},
{
"name": "circuitplayground_express",
"inherits": "default"
},
{
"name": "curiosity_nano",
"inherits": "default"
},
{
"name": "cynthion_d11",
"inherits": "default"
},
{
"name": "cynthion_d21",
"inherits": "default"
},
{
"name": "d5035_01",
"inherits": "default"
},
{
"name": "da14695_dk_usb",
"inherits": "default"
},
{
"name": "da1469x_dk_pro",
"inherits": "default"
},
{
"name": "daisyseed",
"inherits": "default"
},
{
"name": "double_m33_express",
"inherits": "default"
},
{
"name": "ea4088_quickstart",
"inherits": "default"
},
{
"name": "ea4357",
"inherits": "default"
},
{
"name": "ek_tm4c123gxl",
"inherits": "default"
},
{
"name": "ek_tm4c1294xl",
"inherits": "default"
},
{
"name": "f1c100s",
"inherits": "default"
},
{
"name": "feather_m0_express",
"inherits": "default"
},
{
"name": "feather_m4_express",
"inherits": "default"
},
{
"name": "feather_nrf52840_express",
"inherits": "default"
},
{
"name": "feather_nrf52840_sense",
"inherits": "default"
},
{
"name": "feather_rp2040_max3421",
"inherits": "default"
},
{
"name": "feather_stm32f405",
"inherits": "default"
},
{
"name": "fomu",
"inherits": "default"
},
{
"name": "frdm_k32l2a4s",
"inherits": "default"
},
{
"name": "frdm_k32l2b",
"inherits": "default"
},
{
"name": "frdm_k64f",
"inherits": "default"
},
{
"name": "frdm_kl25z",
"inherits": "default"
},
{
"name": "frdm_mcxa153",
"inherits": "default"
},
{
"name": "frdm_mcxa156",
"inherits": "default"
},
{
"name": "frdm_mcxn947",
"inherits": "default"
},
{
"name": "frdm_rw612",
"inherits": "default"
},
{
"name": "hpm6750evk2",
"inherits": "default"
},
{
"name": "itsybitsy_m0",
"inherits": "default"
},
{
"name": "itsybitsy_m4",
"inherits": "default"
},
{
"name": "itsybitsy_nrf52840",
"inherits": "default"
},
{
"name": "kuiic",
"inherits": "default"
},
{
"name": "lpcxpresso11u37",
"inherits": "default"
},
{
"name": "lpcxpresso11u68",
"inherits": "default"
},
{
"name": "lpcxpresso1347",
"inherits": "default"
},
{
"name": "lpcxpresso1549",
"inherits": "default"
},
{
"name": "lpcxpresso1769",
"inherits": "default"
},
{
"name": "lpcxpresso18s37",
"inherits": "default"
},
{
"name": "lpcxpresso43s67",
"inherits": "default"
},
{
"name": "lpcxpresso51u68",
"inherits": "default"
},
{
"name": "lpcxpresso54114",
"inherits": "default"
},
{
"name": "lpcxpresso54608",
"inherits": "default"
},
{
"name": "lpcxpresso54628",
"inherits": "default"
},
{
"name": "lpcxpresso55s28",
"inherits": "default"
},
{
"name": "lpcxpresso55s69",
"inherits": "default"
},
{
"name": "max32650evkit",
"inherits": "default"
},
{
"name": "max32650fthr",
"inherits": "default"
},
{
"name": "max32651evkit",
"inherits": "default"
},
{
"name": "max32666evkit",
"inherits": "default"
},
{
"name": "max32666fthr",
"inherits": "default"
},
{
"name": "max32690evkit",
"inherits": "default"
},
{
"name": "max78002evkit",
"inherits": "default"
},
{
"name": "mbed1768",
"inherits": "default"
},
{
"name": "mcb1800",
"inherits": "default"
},
{
"name": "mcu_link",
"inherits": "default"
},
{
"name": "mcxn947brk",
"inherits": "default"
},
{
"name": "metro_m0_express",
"inherits": "default"
},
{
"name": "metro_m4_express",
"inherits": "default"
},
{
"name": "metro_m7_1011",
"inherits": "default"
},
{
"name": "mimxrt1010_evk",
"inherits": "default"
},
{
"name": "mimxrt1015_evk",
"inherits": "default"
},
{
"name": "mimxrt1020_evk",
"inherits": "default"
},
{
"name": "mimxrt1024_evk",
"inherits": "default"
},
{
"name": "mimxrt1050_evkb",
"inherits": "default"
},
{
"name": "mimxrt1060_evk",
"inherits": "default"
},
{
"name": "mimxrt1064_evk",
"inherits": "default"
},
{
"name": "mimxrt1170_evkb",
"inherits": "default"
},
{
"name": "mm32f327x_mb39",
"inherits": "default"
},
{
"name": "mm32f327x_pitaya_lite",
"inherits": "default"
},
{
"name": "msp_exp430f5529lp",
"inherits": "default"
},
{
"name": "msp_exp432e401y",
"inherits": "default"
},
{
"name": "nanoch32v203",
"inherits": "default"
},
{
"name": "nanoch32v305",
"inherits": "default"
},
{
"name": "nrf52833dk",
"inherits": "default"
},
{
"name": "nrf52840dk",
"inherits": "default"
},
{
"name": "nrf52840dongle",
"inherits": "default"
},
{
"name": "nrf5340dk",
"inherits": "default"
},
{
"name": "nrf54h20dk",
"inherits": "default"
},
{
"name": "nutiny_nuc126v",
"inherits": "default"
},
{
"name": "nutiny_sdk_nuc120",
"inherits": "default"
},
{
"name": "nutiny_sdk_nuc121",
"inherits": "default"
},
{
"name": "nutiny_sdk_nuc125",
"inherits": "default"
},
{
"name": "nutiny_sdk_nuc505",
"inherits": "default"
},
{
"name": "pico_sdk",
"inherits": "default"
},
{
"name": "portenta_c33",
"inherits": "default"
},
{
"name": "pybadge",
"inherits": "default"
},
{
"name": "pyboardv11",
"inherits": "default"
},
{
"name": "pyportal",
"inherits": "default"
},
{
"name": "qtpy",
"inherits": "default"
},
{
"name": "ra2a1_ek",
"inherits": "default"
},
{
"name": "ra4m1_ek",
"inherits": "default"
},
{
"name": "ra4m3_ek",
"inherits": "default"
},
{
"name": "ra6m1_ek",
"inherits": "default"
},
{
"name": "ra6m5_ek",
"inherits": "default"
},
{
"name": "ra8m1_ek",
"inherits": "default"
},
{
"name": "raspberry_pi_pico",
"inherits": "default"
},
{
"name": "raspberry_pi_pico2",
"inherits": "default"
},
{
"name": "raspberry_pi_pico_w",
"inherits": "default"
},
{
"name": "raspberrypi_cm4",
"inherits": "default"
},
{
"name": "raspberrypi_zero",
"inherits": "default"
},
{
"name": "raspberrypi_zero2",
"inherits": "default"
},
{
"name": "samd11_xplained",
"inherits": "default"
},
{
"name": "same54_xplained",
"inherits": "default"
},
{
"name": "same70_qmtech",
"inherits": "default"
},
{
"name": "same70_xplained",
"inherits": "default"
},
{
"name": "samg55_xplained",
"inherits": "default"
},
{
"name": "saml22_feather",
"inherits": "default"
},
{
"name": "seeeduino_xiao",
"inherits": "default"
},
{
"name": "sensorwatch_m0",
"inherits": "default"
},
{
"name": "sipeed_longan_nano",
"inherits": "default"
},
{
"name": "sltb009a",
"inherits": "default"
},
{
"name": "sparkfun_samd21_mini_usb",
"inherits": "default"
},
{
"name": "spresense",
"inherits": "default"
},
{
"name": "stlinkv3mini",
"inherits": "default"
},
{
"name": "stm32c071nucleo",
"inherits": "default"
},
{
"name": "stm32f070rbnucleo",
"inherits": "default"
},
{
"name": "stm32f072disco",
"inherits": "default"
},
{
"name": "stm32f072eval",
"inherits": "default"
},
{
"name": "stm32f103_bluepill",
"inherits": "default"
},
{
"name": "stm32f103_mini_2",
"inherits": "default"
},
{
"name": "stm32f103ze_iar",
"inherits": "default"
},
{
"name": "stm32f207nucleo",
"inherits": "default"
},
{
"name": "stm32f303disco",
"inherits": "default"
},
{
"name": "stm32f401blackpill",
"inherits": "default"
},
{
"name": "stm32f407blackvet",
"inherits": "default"
},
{
"name": "stm32f407disco",
"inherits": "default"
},
{
"name": "stm32f411blackpill",
"inherits": "default"
},
{
"name": "stm32f411disco",
"inherits": "default"
},
{
"name": "stm32f412disco",
"inherits": "default"
},
{
"name": "stm32f412nucleo",
"inherits": "default"
},
{
"name": "stm32f439nucleo",
"inherits": "default"
},
{
"name": "stm32f723disco",
"inherits": "default"
},
{
"name": "stm32f746disco",
"inherits": "default"
},
{
"name": "stm32f746nucleo",
"inherits": "default"
},
{
"name": "stm32f767nucleo",
"inherits": "default"
},
{
"name": "stm32f769disco",
"inherits": "default"
},
{
"name": "stm32g0b1nucleo",
"inherits": "default"
},
{
"name": "stm32g474nucleo",
"inherits": "default"
},
{
"name": "stm32g491nucleo",
"inherits": "default"
},
{
"name": "stm32h503nucleo",
"inherits": "default"
},
{
"name": "stm32h563nucleo",
"inherits": "default"
},
{
"name": "stm32h573i_dk",
"inherits": "default"
},
{
"name": "stm32h723nucleo",
"inherits": "default"
},
{
"name": "stm32h743eval",
"inherits": "default"
},
{
"name": "stm32h743nucleo",
"inherits": "default"
},
{
"name": "stm32h745disco",
"inherits": "default"
},
{
"name": "stm32h747disco",
"inherits": "default"
},
{
"name": "stm32h750_weact",
"inherits": "default"
},
{
"name": "stm32h750bdk",
"inherits": "default"
},
{
"name": "stm32h7s3nucleo",
"inherits": "default"
},
{
"name": "stm32l052dap52",
"inherits": "default"
},
{
"name": "stm32l0538disco",
"inherits": "default"
},
{
"name": "stm32l412nucleo",
"inherits": "default"
},
{
"name": "stm32l476disco",
"inherits": "default"
},
{
"name": "stm32l496nucleo",
"inherits": "default"
},
{
"name": "stm32l4p5nucleo",
"inherits": "default"
},
{
"name": "stm32l4r5nucleo",
"inherits": "default"
},
{
"name": "stm32n6570dk",
"inherits": "default"
},
{
"name": "stm32n657nucleo",
"inherits": "default"
},
{
"name": "stm32u083cdk",
"inherits": "default"
},
{
"name": "stm32u545nucleo",
"inherits": "default"
},
{
"name": "stm32u575eval",
"inherits": "default"
},
{
"name": "stm32u575nucleo",
"inherits": "default"
},
{
"name": "stm32u5a5nucleo",
"inherits": "default"
},
{
"name": "stm32wb55nucleo",
"inherits": "default"
},
{
"name": "stm32wba_nucleo",
"inherits": "default"
},
{
"name": "teensy_35",
"inherits": "default"
},
{
"name": "teensy_40",
"inherits": "default"
},
{
"name": "teensy_41",
"inherits": "default"
},
{
"name": "trinket_m0",
"inherits": "default"
},
{
"name": "uno_r4",
"inherits": "default"
},
{
"name": "waveshare_openh743i",
"inherits": "default"
},
{
"name": "xmc4500_relax",
"inherits": "default"
},
{
"name": "xmc4700_relax",
"inherits": "default"
},
{
"name": "adafruit_feather_esp32_v2",
"inherits": "default single config"
},
{
"name": "adafruit_feather_esp32c6",
"inherits": "default single config"
},
{
"name": "adafruit_feather_esp32s2",
"inherits": "default single config"
},
{
"name": "adafruit_feather_esp32s3",
"inherits": "default single config"
},
{
"name": "adafruit_magtag_29gray",
"inherits": "default single config"
},
{
"name": "adafruit_metro_esp32s2",
"inherits": "default single config"
},
{
"name": "espressif_addax_1",
"inherits": "default single config"
},
{
"name": "espressif_c3_devkitc",
"inherits": "default single config"
},
{
"name": "espressif_c6_devkitc",
"inherits": "default single config"
},
{
"name": "espressif_kaluga_1",
"inherits": "default single config"
},
{
"name": "espressif_p4_function_ev",
"inherits": "default single config"
},
{
"name": "espressif_s2_devkitc",
"inherits": "default single config"
},
{
"name": "espressif_s3_devkitc",
"inherits": "default single config"
},
{
"name": "espressif_s3_devkitm",
"inherits": "default single config"
},
{
"name": "espressif_saola_1",
"inherits": "default single config"
}
],
"buildPresets": [
{
"name": "adafruit_clue",
"description": "Build preset for the adafruit_clue board",
"configurePreset": "adafruit_clue"
},
{
"name": "adafruit_feather_esp32_v2",
"description": "Build preset for the adafruit_feather_esp32_v2 board",
"configurePreset": "adafruit_feather_esp32_v2"
},
{
"name": "adafruit_feather_esp32c6",
"description": "Build preset for the adafruit_feather_esp32c6 board",
"configurePreset": "adafruit_feather_esp32c6"
},
{
"name": "adafruit_feather_esp32s2",
"description": "Build preset for the adafruit_feather_esp32s2 board",
"configurePreset": "adafruit_feather_esp32s2"
},
{
"name": "adafruit_feather_esp32s3",
"description": "Build preset for the adafruit_feather_esp32s3 board",
"configurePreset": "adafruit_feather_esp32s3"
},
{
"name": "adafruit_feather_rp2040_usb_host",
"description": "Build preset for the adafruit_feather_rp2040_usb_host board",
"configurePreset": "adafruit_feather_rp2040_usb_host"
},
{
"name": "adafruit_fruit_jam",
"description": "Build preset for the adafruit_fruit_jam board",
"configurePreset": "adafruit_fruit_jam"
},
{
"name": "adafruit_magtag_29gray",
"description": "Build preset for the adafruit_magtag_29gray board",
"configurePreset": "adafruit_magtag_29gray"
},
{
"name": "adafruit_metro_esp32s2",
"description": "Build preset for the adafruit_metro_esp32s2 board",
"configurePreset": "adafruit_metro_esp32s2"
},
{
"name": "adafruit_metro_rp2350",
"description": "Build preset for the adafruit_metro_rp2350 board",
"configurePreset": "adafruit_metro_rp2350"
},
{
"name": "apard32690",
"description": "Build preset for the apard32690 board",
"configurePreset": "apard32690"
},
{
"name": "arduino_nano33_ble",
"description": "Build preset for the arduino_nano33_ble board",
"configurePreset": "arduino_nano33_ble"
},
{
"name": "at32f403a_weact_blackpill",
"description": "Build preset for the at32f403a_weact_blackpill board",
"configurePreset": "at32f403a_weact_blackpill"
},
{
"name": "at_start_f402",
"description": "Build preset for the at_start_f402 board",
"configurePreset": "at_start_f402"
},
{
"name": "at_start_f403a",
"description": "Build preset for the at_start_f403a board",
"configurePreset": "at_start_f403a"
},
{
"name": "at_start_f405",
"description": "Build preset for the at_start_f405 board",
"configurePreset": "at_start_f405"
},
{
"name": "at_start_f407",
"description": "Build preset for the at_start_f407 board",
"configurePreset": "at_start_f407"
},
{
"name": "at_start_f413",
"description": "Build preset for the at_start_f413 board",
"configurePreset": "at_start_f413"
},
{
"name": "at_start_f415",
"description": "Build preset for the at_start_f415 board",
"configurePreset": "at_start_f415"
},
{
"name": "at_start_f423",
"description": "Build preset for the at_start_f423 board",
"configurePreset": "at_start_f423"
},
{
"name": "at_start_f425",
"description": "Build preset for the at_start_f425 board",
"configurePreset": "at_start_f425"
},
{
"name": "at_start_f435",
"description": "Build preset for the at_start_f435 board",
"configurePreset": "at_start_f435"
},
{
"name": "at_start_f437",
"description": "Build preset for the at_start_f437 board",
"configurePreset": "at_start_f437"
},
{
"name": "at_start_f455",
"description": "Build preset for the at_start_f455 board",
"configurePreset": "at_start_f455"
},
{
"name": "at_start_f456",
"description": "Build preset for the at_start_f456 board",
"configurePreset": "at_start_f456"
},
{
"name": "at_start_f457",
"description": "Build preset for the at_start_f457 board",
"configurePreset": "at_start_f457"
},
{
"name": "atsamd21_xpro",
"description": "Build preset for the atsamd21_xpro board",
"configurePreset": "atsamd21_xpro"
},
{
"name": "atsaml21_xpro",
"description": "Build preset for the atsaml21_xpro board",
"configurePreset": "atsaml21_xpro"
},
{
"name": "b_g474e_dpow1",
"description": "Build preset for the b_g474e_dpow1 board",
"configurePreset": "b_g474e_dpow1"
},
{
"name": "b_u585i_iot2a",
"description": "Build preset for the b_u585i_iot2a board",
"configurePreset": "b_u585i_iot2a"
},
{
"name": "ch32v103r_r1_1v0",
"description": "Build preset for the ch32v103r_r1_1v0 board",
"configurePreset": "ch32v103r_r1_1v0"
},
{
"name": "ch32v203c_r0_1v0",
"description": "Build preset for the ch32v203c_r0_1v0 board",
"configurePreset": "ch32v203c_r0_1v0"
},
{
"name": "ch32v203g_r0_1v0",
"description": "Build preset for the ch32v203g_r0_1v0 board",
"configurePreset": "ch32v203g_r0_1v0"
},
{
"name": "ch32v307v_r1_1v0",
"description": "Build preset for the ch32v307v_r1_1v0 board",
"configurePreset": "ch32v307v_r1_1v0"
},
{
"name": "circuitplayground_bluefruit",
"description": "Build preset for the circuitplayground_bluefruit board",
"configurePreset": "circuitplayground_bluefruit"
},
{
"name": "circuitplayground_express",
"description": "Build preset for the circuitplayground_express board",
"configurePreset": "circuitplayground_express"
},
{
"name": "curiosity_nano",
"description": "Build preset for the curiosity_nano board",
"configurePreset": "curiosity_nano"
},
{
"name": "cynthion_d11",
"description": "Build preset for the cynthion_d11 board",
"configurePreset": "cynthion_d11"
},
{
"name": "cynthion_d21",
"description": "Build preset for the cynthion_d21 board",
"configurePreset": "cynthion_d21"
},
{
"name": "d5035_01",
"description": "Build preset for the d5035_01 board",
"configurePreset": "d5035_01"
},
{
"name": "da14695_dk_usb",
"description": "Build preset for the da14695_dk_usb board",
"configurePreset": "da14695_dk_usb"
},
{
"name": "da1469x_dk_pro",
"description": "Build preset for the da1469x_dk_pro board",
"configurePreset": "da1469x_dk_pro"
},
{
"name": "daisyseed",
"description": "Build preset for the daisyseed board",
"configurePreset": "daisyseed"
},
{
"name": "double_m33_express",
"description": "Build preset for the double_m33_express board",
"configurePreset": "double_m33_express"
},
{
"name": "ea4088_quickstart",
"description": "Build preset for the ea4088_quickstart board",
"configurePreset": "ea4088_quickstart"
},
{
"name": "ea4357",
"description": "Build preset for the ea4357 board",
"configurePreset": "ea4357"
},
{
"name": "ek_tm4c123gxl",
"description": "Build preset for the ek_tm4c123gxl board",
"configurePreset": "ek_tm4c123gxl"
},
{
"name": "ek_tm4c1294xl",
"description": "Build preset for the ek_tm4c1294xl board",
"configurePreset": "ek_tm4c1294xl"
},
{
"name": "espressif_addax_1",
"description": "Build preset for the espressif_addax_1 board",
"configurePreset": "espressif_addax_1"
},
{
"name": "espressif_c3_devkitc",
"description": "Build preset for the espressif_c3_devkitc board",
"configurePreset": "espressif_c3_devkitc"
},
{
"name": "espressif_c6_devkitc",
"description": "Build preset for the espressif_c6_devkitc board",
"configurePreset": "espressif_c6_devkitc"
},
{
"name": "espressif_kaluga_1",
"description": "Build preset for the espressif_kaluga_1 board",
"configurePreset": "espressif_kaluga_1"
},
{
"name": "espressif_p4_function_ev",
"description": "Build preset for the espressif_p4_function_ev board",
"configurePreset": "espressif_p4_function_ev"
},
{
"name": "espressif_s2_devkitc",
"description": "Build preset for the espressif_s2_devkitc board",
"configurePreset": "espressif_s2_devkitc"
},
{
"name": "espressif_s3_devkitc",
"description": "Build preset for the espressif_s3_devkitc board",
"configurePreset": "espressif_s3_devkitc"
},
{
"name": "espressif_s3_devkitm",
"description": "Build preset for the espressif_s3_devkitm board",
"configurePreset": "espressif_s3_devkitm"
},
{
"name": "espressif_saola_1",
"description": "Build preset for the espressif_saola_1 board",
"configurePreset": "espressif_saola_1"
},
{
"name": "f1c100s",
"description": "Build preset for the f1c100s board",
"configurePreset": "f1c100s"
},
{
"name": "feather_m0_express",
"description": "Build preset for the feather_m0_express board",
"configurePreset": "feather_m0_express"
},
{
"name": "feather_m4_express",
"description": "Build preset for the feather_m4_express board",
"configurePreset": "feather_m4_express"
},
{
"name": "feather_nrf52840_express",
"description": "Build preset for the feather_nrf52840_express board",
"configurePreset": "feather_nrf52840_express"
},
{
"name": "feather_nrf52840_sense",
"description": "Build preset for the feather_nrf52840_sense board",
"configurePreset": "feather_nrf52840_sense"
},
{
"name": "feather_rp2040_max3421",
"description": "Build preset for the feather_rp2040_max3421 board",
"configurePreset": "feather_rp2040_max3421"
},
{
"name": "feather_stm32f405",
"description": "Build preset for the feather_stm32f405 board",
"configurePreset": "feather_stm32f405"
},
{
"name": "fomu",
"description": "Build preset for the fomu board",
"configurePreset": "fomu"
},
{
"name": "frdm_k32l2a4s",
"description": "Build preset for the frdm_k32l2a4s board",
"configurePreset": "frdm_k32l2a4s"
},
{
"name": "frdm_k32l2b",
"description": "Build preset for the frdm_k32l2b board",
"configurePreset": "frdm_k32l2b"
},
{
"name": "frdm_k64f",
"description": "Build preset for the frdm_k64f board",
"configurePreset": "frdm_k64f"
},
{
"name": "frdm_kl25z",
"description": "Build preset for the frdm_kl25z board",
"configurePreset": "frdm_kl25z"
},
{
"name": "frdm_mcxa153",
"description": "Build preset for the frdm_mcxa153 board",
"configurePreset": "frdm_mcxa153"
},
{
"name": "frdm_mcxa156",
"description": "Build preset for the frdm_mcxa156 board",
"configurePreset": "frdm_mcxa156"
},
{
"name": "frdm_mcxn947",
"description": "Build preset for the frdm_mcxn947 board",
"configurePreset": "frdm_mcxn947"
},
{
"name": "frdm_rw612",
"description": "Build preset for the frdm_rw612 board",
"configurePreset": "frdm_rw612"
},
{
"name": "hpm6750evk2",
"description": "Build preset for the hpm6750evk2 board",
"configurePreset": "hpm6750evk2"
},
{
"name": "itsybitsy_m0",
"description": "Build preset for the itsybitsy_m0 board",
"configurePreset": "itsybitsy_m0"
},
{
"name": "itsybitsy_m4",
"description": "Build preset for the itsybitsy_m4 board",
"configurePreset": "itsybitsy_m4"
},
{
"name": "itsybitsy_nrf52840",
"description": "Build preset for the itsybitsy_nrf52840 board",
"configurePreset": "itsybitsy_nrf52840"
},
{
"name": "kuiic",
"description": "Build preset for the kuiic board",
"configurePreset": "kuiic"
},
{
"name": "lpcxpresso11u37",
"description": "Build preset for the lpcxpresso11u37 board",
"configurePreset": "lpcxpresso11u37"
},
{
"name": "lpcxpresso11u68",
"description": "Build preset for the lpcxpresso11u68 board",
"configurePreset": "lpcxpresso11u68"
},
{
"name": "lpcxpresso1347",
"description": "Build preset for the lpcxpresso1347 board",
"configurePreset": "lpcxpresso1347"
},
{
"name": "lpcxpresso1549",
"description": "Build preset for the lpcxpresso1549 board",
"configurePreset": "lpcxpresso1549"
},
{
"name": "lpcxpresso1769",
"description": "Build preset for the lpcxpresso1769 board",
"configurePreset": "lpcxpresso1769"
},
{
"name": "lpcxpresso18s37",
"description": "Build preset for the lpcxpresso18s37 board",
"configurePreset": "lpcxpresso18s37"
},
{
"name": "lpcxpresso43s67",
"description": "Build preset for the lpcxpresso43s67 board",
"configurePreset": "lpcxpresso43s67"
},
{
"name": "lpcxpresso51u68",
"description": "Build preset for the lpcxpresso51u68 board",
"configurePreset": "lpcxpresso51u68"
},
{
"name": "lpcxpresso54114",
"description": "Build preset for the lpcxpresso54114 board",
"configurePreset": "lpcxpresso54114"
},
{
"name": "lpcxpresso54608",
"description": "Build preset for the lpcxpresso54608 board",
"configurePreset": "lpcxpresso54608"
},
{
"name": "lpcxpresso54628",
"description": "Build preset for the lpcxpresso54628 board",
"configurePreset": "lpcxpresso54628"
},
{
"name": "lpcxpresso55s28",
"description": "Build preset for the lpcxpresso55s28 board",
"configurePreset": "lpcxpresso55s28"
},
{
"name": "lpcxpresso55s69",
"description": "Build preset for the lpcxpresso55s69 board",
"configurePreset": "lpcxpresso55s69"
},
{
"name": "max32650evkit",
"description": "Build preset for the max32650evkit board",
"configurePreset": "max32650evkit"
},
{
"name": "max32650fthr",
"description": "Build preset for the max32650fthr board",
"configurePreset": "max32650fthr"
},
{
"name": "max32651evkit",
"description": "Build preset for the max32651evkit board",
"configurePreset": "max32651evkit"
},
{
"name": "max32666evkit",
"description": "Build preset for the max32666evkit board",
"configurePreset": "max32666evkit"
},
{
"name": "max32666fthr",
"description": "Build preset for the max32666fthr board",
"configurePreset": "max32666fthr"
},
{
"name": "max32690evkit",
"description": "Build preset for the max32690evkit board",
"configurePreset": "max32690evkit"
},
{
"name": "max78002evkit",
"description": "Build preset for the max78002evkit board",
"configurePreset": "max78002evkit"
},
{
"name": "mbed1768",
"description": "Build preset for the mbed1768 board",
"configurePreset": "mbed1768"
},
{
"name": "mcb1800",
"description": "Build preset for the mcb1800 board",
"configurePreset": "mcb1800"
},
{
"name": "mcu_link",
"description": "Build preset for the mcu_link board",
"configurePreset": "mcu_link"
},
{
"name": "mcxn947brk",
"description": "Build preset for the mcxn947brk board",
"configurePreset": "mcxn947brk"
},
{
"name": "metro_m0_express",
"description": "Build preset for the metro_m0_express board",
"configurePreset": "metro_m0_express"
},
{
"name": "metro_m4_express",
"description": "Build preset for the metro_m4_express board",
"configurePreset": "metro_m4_express"
},
{
"name": "metro_m7_1011",
"description": "Build preset for the metro_m7_1011 board",
"configurePreset": "metro_m7_1011"
},
{
"name": "mimxrt1010_evk",
"description": "Build preset for the mimxrt1010_evk board",
"configurePreset": "mimxrt1010_evk"
},
{
"name": "mimxrt1015_evk",
"description": "Build preset for the mimxrt1015_evk board",
"configurePreset": "mimxrt1015_evk"
},
{
"name": "mimxrt1020_evk",
"description": "Build preset for the mimxrt1020_evk board",
"configurePreset": "mimxrt1020_evk"
},
{
"name": "mimxrt1024_evk",
"description": "Build preset for the mimxrt1024_evk board",
"configurePreset": "mimxrt1024_evk"
},
{
"name": "mimxrt1050_evkb",
"description": "Build preset for the mimxrt1050_evkb board",
"configurePreset": "mimxrt1050_evkb"
},
{
"name": "mimxrt1060_evk",
"description": "Build preset for the mimxrt1060_evk board",
"configurePreset": "mimxrt1060_evk"
},
{
"name": "mimxrt1064_evk",
"description": "Build preset for the mimxrt1064_evk board",
"configurePreset": "mimxrt1064_evk"
},
{
"name": "mimxrt1170_evkb",
"description": "Build preset for the mimxrt1170_evkb board",
"configurePreset": "mimxrt1170_evkb"
},
{
"name": "mm32f327x_mb39",
"description": "Build preset for the mm32f327x_mb39 board",
"configurePreset": "mm32f327x_mb39"
},
{
"name": "mm32f327x_pitaya_lite",
"description": "Build preset for the mm32f327x_pitaya_lite board",
"configurePreset": "mm32f327x_pitaya_lite"
},
{
"name": "msp_exp430f5529lp",
"description": "Build preset for the msp_exp430f5529lp board",
"configurePreset": "msp_exp430f5529lp"
},
{
"name": "msp_exp432e401y",
"description": "Build preset for the msp_exp432e401y board",
"configurePreset": "msp_exp432e401y"
},
{
"name": "nanoch32v203",
"description": "Build preset for the nanoch32v203 board",
"configurePreset": "nanoch32v203"
},
{
"name": "nanoch32v305",
"description": "Build preset for the nanoch32v305 board",
"configurePreset": "nanoch32v305"
},
{
"name": "nrf52833dk",
"description": "Build preset for the nrf52833dk board",
"configurePreset": "nrf52833dk"
},
{
"name": "nrf52840dk",
"description": "Build preset for the nrf52840dk board",
"configurePreset": "nrf52840dk"
},
{
"name": "nrf52840dongle",
"description": "Build preset for the nrf52840dongle board",
"configurePreset": "nrf52840dongle"
},
{
"name": "nrf5340dk",
"description": "Build preset for the nrf5340dk board",
"configurePreset": "nrf5340dk"
},
{
"name": "nrf54h20dk",
"description": "Build preset for the nrf54h20dk board",
"configurePreset": "nrf54h20dk"
},
{
"name": "nutiny_nuc126v",
"description": "Build preset for the nutiny_nuc126v board",
"configurePreset": "nutiny_nuc126v"
},
{
"name": "nutiny_sdk_nuc120",
"description": "Build preset for the nutiny_sdk_nuc120 board",
"configurePreset": "nutiny_sdk_nuc120"
},
{
"name": "nutiny_sdk_nuc121",
"description": "Build preset for the nutiny_sdk_nuc121 board",
"configurePreset": "nutiny_sdk_nuc121"
},
{
"name": "nutiny_sdk_nuc125",
"description": "Build preset for the nutiny_sdk_nuc125 board",
"configurePreset": "nutiny_sdk_nuc125"
},
{
"name": "nutiny_sdk_nuc505",
"description": "Build preset for the nutiny_sdk_nuc505 board",
"configurePreset": "nutiny_sdk_nuc505"
},
{
"name": "pico_sdk",
"description": "Build preset for the pico_sdk board",
"configurePreset": "pico_sdk"
},
{
"name": "portenta_c33",
"description": "Build preset for the portenta_c33 board",
"configurePreset": "portenta_c33"
},
{
"name": "pybadge",
"description": "Build preset for the pybadge board",
"configurePreset": "pybadge"
},
{
"name": "pyboardv11",
"description": "Build preset for the pyboardv11 board",
"configurePreset": "pyboardv11"
},
{
"name": "pyportal",
"description": "Build preset for the pyportal board",
"configurePreset": "pyportal"
},
{
"name": "qtpy",
"description": "Build preset for the qtpy board",
"configurePreset": "qtpy"
},
{
"name": "ra2a1_ek",
"description": "Build preset for the ra2a1_ek board",
"configurePreset": "ra2a1_ek"
},
{
"name": "ra4m1_ek",
"description": "Build preset for the ra4m1_ek board",
"configurePreset": "ra4m1_ek"
},
{
"name": "ra4m3_ek",
"description": "Build preset for the ra4m3_ek board",
"configurePreset": "ra4m3_ek"
},
{
"name": "ra6m1_ek",
"description": "Build preset for the ra6m1_ek board",
"configurePreset": "ra6m1_ek"
},
{
"name": "ra6m5_ek",
"description": "Build preset for the ra6m5_ek board",
"configurePreset": "ra6m5_ek"
},
{
"name": "ra8m1_ek",
"description": "Build preset for the ra8m1_ek board",
"configurePreset": "ra8m1_ek"
},
{
"name": "raspberry_pi_pico",
"description": "Build preset for the raspberry_pi_pico board",
"configurePreset": "raspberry_pi_pico"
},
{
"name": "raspberry_pi_pico2",
"description": "Build preset for the raspberry_pi_pico2 board",
"configurePreset": "raspberry_pi_pico2"
},
{
"name": "raspberry_pi_pico_w",
"description": "Build preset for the raspberry_pi_pico_w board",
"configurePreset": "raspberry_pi_pico_w"
},
{
"name": "raspberrypi_cm4",
"description": "Build preset for the raspberrypi_cm4 board",
"configurePreset": "raspberrypi_cm4"
},
{
"name": "raspberrypi_zero",
"description": "Build preset for the raspberrypi_zero board",
"configurePreset": "raspberrypi_zero"
},
{
"name": "raspberrypi_zero2",
"description": "Build preset for the raspberrypi_zero2 board",
"configurePreset": "raspberrypi_zero2"
},
{
"name": "samd11_xplained",
"description": "Build preset for the samd11_xplained board",
"configurePreset": "samd11_xplained"
},
{
"name": "same54_xplained",
"description": "Build preset for the same54_xplained board",
"configurePreset": "same54_xplained"
},
{
"name": "same70_qmtech",
"description": "Build preset for the same70_qmtech board",
"configurePreset": "same70_qmtech"
},
{
"name": "same70_xplained",
"description": "Build preset for the same70_xplained board",
"configurePreset": "same70_xplained"
},
{
"name": "samg55_xplained",
"description": "Build preset for the samg55_xplained board",
"configurePreset": "samg55_xplained"
},
{
"name": "saml22_feather",
"description": "Build preset for the saml22_feather board",
"configurePreset": "saml22_feather"
},
{
"name": "seeeduino_xiao",
"description": "Build preset for the seeeduino_xiao board",
"configurePreset": "seeeduino_xiao"
},
{
"name": "sensorwatch_m0",
"description": "Build preset for the sensorwatch_m0 board",
"configurePreset": "sensorwatch_m0"
},
{
"name": "sipeed_longan_nano",
"description": "Build preset for the sipeed_longan_nano board",
"configurePreset": "sipeed_longan_nano"
},
{
"name": "sltb009a",
"description": "Build preset for the sltb009a board",
"configurePreset": "sltb009a"
},
{
"name": "sparkfun_samd21_mini_usb",
"description": "Build preset for the sparkfun_samd21_mini_usb board",
"configurePreset": "sparkfun_samd21_mini_usb"
},
{
"name": "spresense",
"description": "Build preset for the spresense board",
"configurePreset": "spresense"
},
{
"name": "stlinkv3mini",
"description": "Build preset for the stlinkv3mini board",
"configurePreset": "stlinkv3mini"
},
{
"name": "stm32c071nucleo",
"description": "Build preset for the stm32c071nucleo board",
"configurePreset": "stm32c071nucleo"
},
{
"name": "stm32f070rbnucleo",
"description": "Build preset for the stm32f070rbnucleo board",
"configurePreset": "stm32f070rbnucleo"
},
{
"name": "stm32f072disco",
"description": "Build preset for the stm32f072disco board",
"configurePreset": "stm32f072disco"
},
{
"name": "stm32f072eval",
"description": "Build preset for the stm32f072eval board",
"configurePreset": "stm32f072eval"
},
{
"name": "stm32f103_bluepill",
"description": "Build preset for the stm32f103_bluepill board",
"configurePreset": "stm32f103_bluepill"
},
{
"name": "stm32f103_mini_2",
"description": "Build preset for the stm32f103_mini_2 board",
"configurePreset": "stm32f103_mini_2"
},
{
"name": "stm32f103ze_iar",
"description": "Build preset for the stm32f103ze_iar board",
"configurePreset": "stm32f103ze_iar"
},
{
"name": "stm32f207nucleo",
"description": "Build preset for the stm32f207nucleo board",
"configurePreset": "stm32f207nucleo"
},
{
"name": "stm32f303disco",
"description": "Build preset for the stm32f303disco board",
"configurePreset": "stm32f303disco"
},
{
"name": "stm32f401blackpill",
"description": "Build preset for the stm32f401blackpill board",
"configurePreset": "stm32f401blackpill"
},
{
"name": "stm32f407blackvet",
"description": "Build preset for the stm32f407blackvet board",
"configurePreset": "stm32f407blackvet"
},
{
"name": "stm32f407disco",
"description": "Build preset for the stm32f407disco board",
"configurePreset": "stm32f407disco"
},
{
"name": "stm32f411blackpill",
"description": "Build preset for the stm32f411blackpill board",
"configurePreset": "stm32f411blackpill"
},
{
"name": "stm32f411disco",
"description": "Build preset for the stm32f411disco board",
"configurePreset": "stm32f411disco"
},
{
"name": "stm32f412disco",
"description": "Build preset for the stm32f412disco board",
"configurePreset": "stm32f412disco"
},
{
"name": "stm32f412nucleo",
"description": "Build preset for the stm32f412nucleo board",
"configurePreset": "stm32f412nucleo"
},
{
"name": "stm32f439nucleo",
"description": "Build preset for the stm32f439nucleo board",
"configurePreset": "stm32f439nucleo"
},
{
"name": "stm32f723disco",
"description": "Build preset for the stm32f723disco board",
"configurePreset": "stm32f723disco"
},
{
"name": "stm32f746disco",
"description": "Build preset for the stm32f746disco board",
"configurePreset": "stm32f746disco"
},
{
"name": "stm32f746nucleo",
"description": "Build preset for the stm32f746nucleo board",
"configurePreset": "stm32f746nucleo"
},
{
"name": "stm32f767nucleo",
"description": "Build preset for the stm32f767nucleo board",
"configurePreset": "stm32f767nucleo"
},
{
"name": "stm32f769disco",
"description": "Build preset for the stm32f769disco board",
"configurePreset": "stm32f769disco"
},
{
"name": "stm32g0b1nucleo",
"description": "Build preset for the stm32g0b1nucleo board",
"configurePreset": "stm32g0b1nucleo"
},
{
"name": "stm32g474nucleo",
"description": "Build preset for the stm32g474nucleo board",
"configurePreset": "stm32g474nucleo"
},
{
"name": "stm32g491nucleo",
"description": "Build preset for the stm32g491nucleo board",
"configurePreset": "stm32g491nucleo"
},
{
"name": "stm32h503nucleo",
"description": "Build preset for the stm32h503nucleo board",
"configurePreset": "stm32h503nucleo"
},
{
"name": "stm32h563nucleo",
"description": "Build preset for the stm32h563nucleo board",
"configurePreset": "stm32h563nucleo"
},
{
"name": "stm32h573i_dk",
"description": "Build preset for the stm32h573i_dk board",
"configurePreset": "stm32h573i_dk"
},
{
"name": "stm32h723nucleo",
"description": "Build preset for the stm32h723nucleo board",
"configurePreset": "stm32h723nucleo"
},
{
"name": "stm32h743eval",
"description": "Build preset for the stm32h743eval board",
"configurePreset": "stm32h743eval"
},
{
"name": "stm32h743nucleo",
"description": "Build preset for the stm32h743nucleo board",
"configurePreset": "stm32h743nucleo"
},
{
"name": "stm32h745disco",
"description": "Build preset for the stm32h745disco board",
"configurePreset": "stm32h745disco"
},
{
"name": "stm32h747disco",
"description": "Build preset for the stm32h747disco board",
"configurePreset": "stm32h747disco"
},
{
"name": "stm32h750_weact",
"description": "Build preset for the stm32h750_weact board",
"configurePreset": "stm32h750_weact"
},
{
"name": "stm32h750bdk",
"description": "Build preset for the stm32h750bdk board",
"configurePreset": "stm32h750bdk"
},
{
"name": "stm32h7s3nucleo",
"description": "Build preset for the stm32h7s3nucleo board",
"configurePreset": "stm32h7s3nucleo"
},
{
"name": "stm32l052dap52",
"description": "Build preset for the stm32l052dap52 board",
"configurePreset": "stm32l052dap52"
},
{
"name": "stm32l0538disco",
"description": "Build preset for the stm32l0538disco board",
"configurePreset": "stm32l0538disco"
},
{
"name": "stm32l412nucleo",
"description": "Build preset for the stm32l412nucleo board",
"configurePreset": "stm32l412nucleo"
},
{
"name": "stm32l476disco",
"description": "Build preset for the stm32l476disco board",
"configurePreset": "stm32l476disco"
},
{
"name": "stm32l496nucleo",
"description": "Build preset for the stm32l496nucleo board",
"configurePreset": "stm32l496nucleo"
},
{
"name": "stm32l4p5nucleo",
"description": "Build preset for the stm32l4p5nucleo board",
"configurePreset": "stm32l4p5nucleo"
},
{
"name": "stm32l4r5nucleo",
"description": "Build preset for the stm32l4r5nucleo board",
"configurePreset": "stm32l4r5nucleo"
},
{
"name": "stm32n6570dk",
"description": "Build preset for the stm32n6570dk board",
"configurePreset": "stm32n6570dk"
},
{
"name": "stm32n657nucleo",
"description": "Build preset for the stm32n657nucleo board",
"configurePreset": "stm32n657nucleo"
},
{
"name": "stm32u083cdk",
"description": "Build preset for the stm32u083cdk board",
"configurePreset": "stm32u083cdk"
},
{
"name": "stm32u545nucleo",
"description": "Build preset for the stm32u545nucleo board",
"configurePreset": "stm32u545nucleo"
},
{
"name": "stm32u575eval",
"description": "Build preset for the stm32u575eval board",
"configurePreset": "stm32u575eval"
},
{
"name": "stm32u575nucleo",
"description": "Build preset for the stm32u575nucleo board",
"configurePreset": "stm32u575nucleo"
},
{
"name": "stm32u5a5nucleo",
"description": "Build preset for the stm32u5a5nucleo board",
"configurePreset": "stm32u5a5nucleo"
},
{
"name": "stm32wb55nucleo",
"description": "Build preset for the stm32wb55nucleo board",
"configurePreset": "stm32wb55nucleo"
},
{
"name": "stm32wba_nucleo",
"description": "Build preset for the stm32wba_nucleo board",
"configurePreset": "stm32wba_nucleo"
},
{
"name": "teensy_35",
"description": "Build preset for the teensy_35 board",
"configurePreset": "teensy_35"
},
{
"name": "teensy_40",
"description": "Build preset for the teensy_40 board",
"configurePreset": "teensy_40"
},
{
"name": "teensy_41",
"description": "Build preset for the teensy_41 board",
"configurePreset": "teensy_41"
},
{
"name": "trinket_m0",
"description": "Build preset for the trinket_m0 board",
"configurePreset": "trinket_m0"
},
{
"name": "uno_r4",
"description": "Build preset for the uno_r4 board",
"configurePreset": "uno_r4"
},
{
"name": "waveshare_openh743i",
"description": "Build preset for the waveshare_openh743i board",
"configurePreset": "waveshare_openh743i"
},
{
"name": "xmc4500_relax",
"description": "Build preset for the xmc4500_relax board",
"configurePreset": "xmc4500_relax"
},
{
"name": "xmc4700_relax",
"description": "Build preset for the xmc4700_relax board",
"configurePreset": "xmc4700_relax"
}
],
"workflowPresets": [
{
"name": "adafruit_clue",
"steps": [
{
"type": "configure",
"name": "adafruit_clue"
},
{
"type": "build",
"name": "adafruit_clue"
}
]
},
{
"name": "adafruit_feather_esp32_v2",
"steps": [
{
"type": "configure",
"name": "adafruit_feather_esp32_v2"
},
{
"type": "build",
"name": "adafruit_feather_esp32_v2"
}
]
},
{
"name": "adafruit_feather_esp32c6",
"steps": [
{
"type": "configure",
"name": "adafruit_feather_esp32c6"
},
{
"type": "build",
"name": "adafruit_feather_esp32c6"
}
]
},
{
"name": "adafruit_feather_esp32s2",
"steps": [
{
"type": "configure",
"name": "adafruit_feather_esp32s2"
},
{
"type": "build",
"name": "adafruit_feather_esp32s2"
}
]
},
{
"name": "adafruit_feather_esp32s3",
"steps": [
{
"type": "configure",
"name": "adafruit_feather_esp32s3"
},
{
"type": "build",
"name": "adafruit_feather_esp32s3"
}
]
},
{
"name": "adafruit_feather_rp2040_usb_host",
"steps": [
{
"type": "configure",
"name": "adafruit_feather_rp2040_usb_host"
},
{
"type": "build",
"name": "adafruit_feather_rp2040_usb_host"
}
]
},
{
"name": "adafruit_fruit_jam",
"steps": [
{
"type": "configure",
"name": "adafruit_fruit_jam"
},
{
"type": "build",
"name": "adafruit_fruit_jam"
}
]
},
{
"name": "adafruit_magtag_29gray",
"steps": [
{
"type": "configure",
"name": "adafruit_magtag_29gray"
},
{
"type": "build",
"name": "adafruit_magtag_29gray"
}
]
},
{
"name": "adafruit_metro_esp32s2",
"steps": [
{
"type": "configure",
"name": "adafruit_metro_esp32s2"
},
{
"type": "build",
"name": "adafruit_metro_esp32s2"
}
]
},
{
"name": "adafruit_metro_rp2350",
"steps": [
{
"type": "configure",
"name": "adafruit_metro_rp2350"
},
{
"type": "build",
"name": "adafruit_metro_rp2350"
}
]
},
{
"name": "apard32690",
"steps": [
{
"type": "configure",
"name": "apard32690"
},
{
"type": "build",
"name": "apard32690"
}
]
},
{
"name": "arduino_nano33_ble",
"steps": [
{
"type": "configure",
"name": "arduino_nano33_ble"
},
{
"type": "build",
"name": "arduino_nano33_ble"
}
]
},
{
"name": "at32f403a_weact_blackpill",
"steps": [
{
"type": "configure",
"name": "at32f403a_weact_blackpill"
},
{
"type": "build",
"name": "at32f403a_weact_blackpill"
}
]
},
{
"name": "at_start_f402",
"steps": [
{
"type": "configure",
"name": "at_start_f402"
},
{
"type": "build",
"name": "at_start_f402"
}
]
},
{
"name": "at_start_f403a",
"steps": [
{
"type": "configure",
"name": "at_start_f403a"
},
{
"type": "build",
"name": "at_start_f403a"
}
]
},
{
"name": "at_start_f405",
"steps": [
{
"type": "configure",
"name": "at_start_f405"
},
{
"type": "build",
"name": "at_start_f405"
}
]
},
{
"name": "at_start_f407",
"steps": [
{
"type": "configure",
"name": "at_start_f407"
},
{
"type": "build",
"name": "at_start_f407"
}
]
},
{
"name": "at_start_f413",
"steps": [
{
"type": "configure",
"name": "at_start_f413"
},
{
"type": "build",
"name": "at_start_f413"
}
]
},
{
"name": "at_start_f415",
"steps": [
{
"type": "configure",
"name": "at_start_f415"
},
{
"type": "build",
"name": "at_start_f415"
}
]
},
{
"name": "at_start_f423",
"steps": [
{
"type": "configure",
"name": "at_start_f423"
},
{
"type": "build",
"name": "at_start_f423"
}
]
},
{
"name": "at_start_f425",
"steps": [
{
"type": "configure",
"name": "at_start_f425"
},
{
"type": "build",
"name": "at_start_f425"
}
]
},
{
"name": "at_start_f435",
"steps": [
{
"type": "configure",
"name": "at_start_f435"
},
{
"type": "build",
"name": "at_start_f435"
}
]
},
{
"name": "at_start_f437",
"steps": [
{
"type": "configure",
"name": "at_start_f437"
},
{
"type": "build",
"name": "at_start_f437"
}
]
},
{
"name": "at_start_f455",
"steps": [
{
"type": "configure",
"name": "at_start_f455"
},
{
"type": "build",
"name": "at_start_f455"
}
]
},
{
"name": "at_start_f456",
"steps": [
{
"type": "configure",
"name": "at_start_f456"
},
{
"type": "build",
"name": "at_start_f456"
}
]
},
{
"name": "at_start_f457",
"steps": [
{
"type": "configure",
"name": "at_start_f457"
},
{
"type": "build",
"name": "at_start_f457"
}
]
},
{
"name": "atsamd21_xpro",
"steps": [
{
"type": "configure",
"name": "atsamd21_xpro"
},
{
"type": "build",
"name": "atsamd21_xpro"
}
]
},
{
"name": "atsaml21_xpro",
"steps": [
{
"type": "configure",
"name": "atsaml21_xpro"
},
{
"type": "build",
"name": "atsaml21_xpro"
}
]
},
{
"name": "b_g474e_dpow1",
"steps": [
{
"type": "configure",
"name": "b_g474e_dpow1"
},
{
"type": "build",
"name": "b_g474e_dpow1"
}
]
},
{
"name": "b_u585i_iot2a",
"steps": [
{
"type": "configure",
"name": "b_u585i_iot2a"
},
{
"type": "build",
"name": "b_u585i_iot2a"
}
]
},
{
"name": "ch32v103r_r1_1v0",
"steps": [
{
"type": "configure",
"name": "ch32v103r_r1_1v0"
},
{
"type": "build",
"name": "ch32v103r_r1_1v0"
}
]
},
{
"name": "ch32v203c_r0_1v0",
"steps": [
{
"type": "configure",
"name": "ch32v203c_r0_1v0"
},
{
"type": "build",
"name": "ch32v203c_r0_1v0"
}
]
},
{
"name": "ch32v203g_r0_1v0",
"steps": [
{
"type": "configure",
"name": "ch32v203g_r0_1v0"
},
{
"type": "build",
"name": "ch32v203g_r0_1v0"
}
]
},
{
"name": "ch32v307v_r1_1v0",
"steps": [
{
"type": "configure",
"name": "ch32v307v_r1_1v0"
},
{
"type": "build",
"name": "ch32v307v_r1_1v0"
}
]
},
{
"name": "circuitplayground_bluefruit",
"steps": [
{
"type": "configure",
"name": "circuitplayground_bluefruit"
},
{
"type": "build",
"name": "circuitplayground_bluefruit"
}
]
},
{
"name": "circuitplayground_express",
"steps": [
{
"type": "configure",
"name": "circuitplayground_express"
},
{
"type": "build",
"name": "circuitplayground_express"
}
]
},
{
"name": "curiosity_nano",
"steps": [
{
"type": "configure",
"name": "curiosity_nano"
},
{
"type": "build",
"name": "curiosity_nano"
}
]
},
{
"name": "cynthion_d11",
"steps": [
{
"type": "configure",
"name": "cynthion_d11"
},
{
"type": "build",
"name": "cynthion_d11"
}
]
},
{
"name": "cynthion_d21",
"steps": [
{
"type": "configure",
"name": "cynthion_d21"
},
{
"type": "build",
"name": "cynthion_d21"
}
]
},
{
"name": "d5035_01",
"steps": [
{
"type": "configure",
"name": "d5035_01"
},
{
"type": "build",
"name": "d5035_01"
}
]
},
{
"name": "da14695_dk_usb",
"steps": [
{
"type": "configure",
"name": "da14695_dk_usb"
},
{
"type": "build",
"name": "da14695_dk_usb"
}
]
},
{
"name": "da1469x_dk_pro",
"steps": [
{
"type": "configure",
"name": "da1469x_dk_pro"
},
{
"type": "build",
"name": "da1469x_dk_pro"
}
]
},
{
"name": "daisyseed",
"steps": [
{
"type": "configure",
"name": "daisyseed"
},
{
"type": "build",
"name": "daisyseed"
}
]
},
{
"name": "double_m33_express",
"steps": [
{
"type": "configure",
"name": "double_m33_express"
},
{
"type": "build",
"name": "double_m33_express"
}
]
},
{
"name": "ea4088_quickstart",
"steps": [
{
"type": "configure",
"name": "ea4088_quickstart"
},
{
"type": "build",
"name": "ea4088_quickstart"
}
]
},
{
"name": "ea4357",
"steps": [
{
"type": "configure",
"name": "ea4357"
},
{
"type": "build",
"name": "ea4357"
}
]
},
{
"name": "ek_tm4c123gxl",
"steps": [
{
"type": "configure",
"name": "ek_tm4c123gxl"
},
{
"type": "build",
"name": "ek_tm4c123gxl"
}
]
},
{
"name": "ek_tm4c1294xl",
"steps": [
{
"type": "configure",
"name": "ek_tm4c1294xl"
},
{
"type": "build",
"name": "ek_tm4c1294xl"
}
]
},
{
"name": "espressif_addax_1",
"steps": [
{
"type": "configure",
"name": "espressif_addax_1"
},
{
"type": "build",
"name": "espressif_addax_1"
}
]
},
{
"name": "espressif_c3_devkitc",
"steps": [
{
"type": "configure",
"name": "espressif_c3_devkitc"
},
{
"type": "build",
"name": "espressif_c3_devkitc"
}
]
},
{
"name": "espressif_c6_devkitc",
"steps": [
{
"type": "configure",
"name": "espressif_c6_devkitc"
},
{
"type": "build",
"name": "espressif_c6_devkitc"
}
]
},
{
"name": "espressif_kaluga_1",
"steps": [
{
"type": "configure",
"name": "espressif_kaluga_1"
},
{
"type": "build",
"name": "espressif_kaluga_1"
}
]
},
{
"name": "espressif_p4_function_ev",
"steps": [
{
"type": "configure",
"name": "espressif_p4_function_ev"
},
{
"type": "build",
"name": "espressif_p4_function_ev"
}
]
},
{
"name": "espressif_s2_devkitc",
"steps": [
{
"type": "configure",
"name": "espressif_s2_devkitc"
},
{
"type": "build",
"name": "espressif_s2_devkitc"
}
]
},
{
"name": "espressif_s3_devkitc",
"steps": [
{
"type": "configure",
"name": "espressif_s3_devkitc"
},
{
"type": "build",
"name": "espressif_s3_devkitc"
}
]
},
{
"name": "espressif_s3_devkitm",
"steps": [
{
"type": "configure",
"name": "espressif_s3_devkitm"
},
{
"type": "build",
"name": "espressif_s3_devkitm"
}
]
},
{
"name": "espressif_saola_1",
"steps": [
{
"type": "configure",
"name": "espressif_saola_1"
},
{
"type": "build",
"name": "espressif_saola_1"
}
]
},
{
"name": "f1c100s",
"steps": [
{
"type": "configure",
"name": "f1c100s"
},
{
"type": "build",
"name": "f1c100s"
}
]
},
{
"name": "feather_m0_express",
"steps": [
{
"type": "configure",
"name": "feather_m0_express"
},
{
"type": "build",
"name": "feather_m0_express"
}
]
},
{
"name": "feather_m4_express",
"steps": [
{
"type": "configure",
"name": "feather_m4_express"
},
{
"type": "build",
"name": "feather_m4_express"
}
]
},
{
"name": "feather_nrf52840_express",
"steps": [
{
"type": "configure",
"name": "feather_nrf52840_express"
},
{
"type": "build",
"name": "feather_nrf52840_express"
}
]
},
{
"name": "feather_nrf52840_sense",
"steps": [
{
"type": "configure",
"name": "feather_nrf52840_sense"
},
{
"type": "build",
"name": "feather_nrf52840_sense"
}
]
},
{
"name": "feather_rp2040_max3421",
"steps": [
{
"type": "configure",
"name": "feather_rp2040_max3421"
},
{
"type": "build",
"name": "feather_rp2040_max3421"
}
]
},
{
"name": "feather_stm32f405",
"steps": [
{
"type": "configure",
"name": "feather_stm32f405"
},
{
"type": "build",
"name": "feather_stm32f405"
}
]
},
{
"name": "fomu",
"steps": [
{
"type": "configure",
"name": "fomu"
},
{
"type": "build",
"name": "fomu"
}
]
},
{
"name": "frdm_k32l2a4s",
"steps": [
{
"type": "configure",
"name": "frdm_k32l2a4s"
},
{
"type": "build",
"name": "frdm_k32l2a4s"
}
]
},
{
"name": "frdm_k32l2b",
"steps": [
{
"type": "configure",
"name": "frdm_k32l2b"
},
{
"type": "build",
"name": "frdm_k32l2b"
}
]
},
{
"name": "frdm_k64f",
"steps": [
{
"type": "configure",
"name": "frdm_k64f"
},
{
"type": "build",
"name": "frdm_k64f"
}
]
},
{
"name": "frdm_kl25z",
"steps": [
{
"type": "configure",
"name": "frdm_kl25z"
},
{
"type": "build",
"name": "frdm_kl25z"
}
]
},
{
"name": "frdm_mcxa153",
"steps": [
{
"type": "configure",
"name": "frdm_mcxa153"
},
{
"type": "build",
"name": "frdm_mcxa153"
}
]
},
{
"name": "frdm_mcxa156",
"steps": [
{
"type": "configure",
"name": "frdm_mcxa156"
},
{
"type": "build",
"name": "frdm_mcxa156"
}
]
},
{
"name": "frdm_mcxn947",
"steps": [
{
"type": "configure",
"name": "frdm_mcxn947"
},
{
"type": "build",
"name": "frdm_mcxn947"
}
]
},
{
"name": "frdm_rw612",
"steps": [
{
"type": "configure",
"name": "frdm_rw612"
},
{
"type": "build",
"name": "frdm_rw612"
}
]
},
{
"name": "hpm6750evk2",
"steps": [
{
"type": "configure",
"name": "hpm6750evk2"
},
{
"type": "build",
"name": "hpm6750evk2"
}
]
},
{
"name": "itsybitsy_m0",
"steps": [
{
"type": "configure",
"name": "itsybitsy_m0"
},
{
"type": "build",
"name": "itsybitsy_m0"
}
]
},
{
"name": "itsybitsy_m4",
"steps": [
{
"type": "configure",
"name": "itsybitsy_m4"
},
{
"type": "build",
"name": "itsybitsy_m4"
}
]
},
{
"name": "itsybitsy_nrf52840",
"steps": [
{
"type": "configure",
"name": "itsybitsy_nrf52840"
},
{
"type": "build",
"name": "itsybitsy_nrf52840"
}
]
},
{
"name": "kuiic",
"steps": [
{
"type": "configure",
"name": "kuiic"
},
{
"type": "build",
"name": "kuiic"
}
]
},
{
"name": "lpcxpresso11u37",
"steps": [
{
"type": "configure",
"name": "lpcxpresso11u37"
},
{
"type": "build",
"name": "lpcxpresso11u37"
}
]
},
{
"name": "lpcxpresso11u68",
"steps": [
{
"type": "configure",
"name": "lpcxpresso11u68"
},
{
"type": "build",
"name": "lpcxpresso11u68"
}
]
},
{
"name": "lpcxpresso1347",
"steps": [
{
"type": "configure",
"name": "lpcxpresso1347"
},
{
"type": "build",
"name": "lpcxpresso1347"
}
]
},
{
"name": "lpcxpresso1549",
"steps": [
{
"type": "configure",
"name": "lpcxpresso1549"
},
{
"type": "build",
"name": "lpcxpresso1549"
}
]
},
{
"name": "lpcxpresso1769",
"steps": [
{
"type": "configure",
"name": "lpcxpresso1769"
},
{
"type": "build",
"name": "lpcxpresso1769"
}
]
},
{
"name": "lpcxpresso18s37",
"steps": [
{
"type": "configure",
"name": "lpcxpresso18s37"
},
{
"type": "build",
"name": "lpcxpresso18s37"
}
]
},
{
"name": "lpcxpresso43s67",
"steps": [
{
"type": "configure",
"name": "lpcxpresso43s67"
},
{
"type": "build",
"name": "lpcxpresso43s67"
}
]
},
{
"name": "lpcxpresso51u68",
"steps": [
{
"type": "configure",
"name": "lpcxpresso51u68"
},
{
"type": "build",
"name": "lpcxpresso51u68"
}
]
},
{
"name": "lpcxpresso54114",
"steps": [
{
"type": "configure",
"name": "lpcxpresso54114"
},
{
"type": "build",
"name": "lpcxpresso54114"
}
]
},
{
"name": "lpcxpresso54608",
"steps": [
{
"type": "configure",
"name": "lpcxpresso54608"
},
{
"type": "build",
"name": "lpcxpresso54608"
}
]
},
{
"name": "lpcxpresso54628",
"steps": [
{
"type": "configure",
"name": "lpcxpresso54628"
},
{
"type": "build",
"name": "lpcxpresso54628"
}
]
},
{
"name": "lpcxpresso55s28",
"steps": [
{
"type": "configure",
"name": "lpcxpresso55s28"
},
{
"type": "build",
"name": "lpcxpresso55s28"
}
]
},
{
"name": "lpcxpresso55s69",
"steps": [
{
"type": "configure",
"name": "lpcxpresso55s69"
},
{
"type": "build",
"name": "lpcxpresso55s69"
}
]
},
{
"name": "max32650evkit",
"steps": [
{
"type": "configure",
"name": "max32650evkit"
},
{
"type": "build",
"name": "max32650evkit"
}
]
},
{
"name": "max32650fthr",
"steps": [
{
"type": "configure",
"name": "max32650fthr"
},
{
"type": "build",
"name": "max32650fthr"
}
]
},
{
"name": "max32651evkit",
"steps": [
{
"type": "configure",
"name": "max32651evkit"
},
{
"type": "build",
"name": "max32651evkit"
}
]
},
{
"name": "max32666evkit",
"steps": [
{
"type": "configure",
"name": "max32666evkit"
},
{
"type": "build",
"name": "max32666evkit"
}
]
},
{
"name": "max32666fthr",
"steps": [
{
"type": "configure",
"name": "max32666fthr"
},
{
"type": "build",
"name": "max32666fthr"
}
]
},
{
"name": "max32690evkit",
"steps": [
{
"type": "configure",
"name": "max32690evkit"
},
{
"type": "build",
"name": "max32690evkit"
}
]
},
{
"name": "max78002evkit",
"steps": [
{
"type": "configure",
"name": "max78002evkit"
},
{
"type": "build",
"name": "max78002evkit"
}
]
},
{
"name": "mbed1768",
"steps": [
{
"type": "configure",
"name": "mbed1768"
},
{
"type": "build",
"name": "mbed1768"
}
]
},
{
"name": "mcb1800",
"steps": [
{
"type": "configure",
"name": "mcb1800"
},
{
"type": "build",
"name": "mcb1800"
}
]
},
{
"name": "mcu_link",
"steps": [
{
"type": "configure",
"name": "mcu_link"
},
{
"type": "build",
"name": "mcu_link"
}
]
},
{
"name": "mcxn947brk",
"steps": [
{
"type": "configure",
"name": "mcxn947brk"
},
{
"type": "build",
"name": "mcxn947brk"
}
]
},
{
"name": "metro_m0_express",
"steps": [
{
"type": "configure",
"name": "metro_m0_express"
},
{
"type": "build",
"name": "metro_m0_express"
}
]
},
{
"name": "metro_m4_express",
"steps": [
{
"type": "configure",
"name": "metro_m4_express"
},
{
"type": "build",
"name": "metro_m4_express"
}
]
},
{
"name": "metro_m7_1011",
"steps": [
{
"type": "configure",
"name": "metro_m7_1011"
},
{
"type": "build",
"name": "metro_m7_1011"
}
]
},
{
"name": "mimxrt1010_evk",
"steps": [
{
"type": "configure",
"name": "mimxrt1010_evk"
},
{
"type": "build",
"name": "mimxrt1010_evk"
}
]
},
{
"name": "mimxrt1015_evk",
"steps": [
{
"type": "configure",
"name": "mimxrt1015_evk"
},
{
"type": "build",
"name": "mimxrt1015_evk"
}
]
},
{
"name": "mimxrt1020_evk",
"steps": [
{
"type": "configure",
"name": "mimxrt1020_evk"
},
{
"type": "build",
"name": "mimxrt1020_evk"
}
]
},
{
"name": "mimxrt1024_evk",
"steps": [
{
"type": "configure",
"name": "mimxrt1024_evk"
},
{
"type": "build",
"name": "mimxrt1024_evk"
}
]
},
{
"name": "mimxrt1050_evkb",
"steps": [
{
"type": "configure",
"name": "mimxrt1050_evkb"
},
{
"type": "build",
"name": "mimxrt1050_evkb"
}
]
},
{
"name": "mimxrt1060_evk",
"steps": [
{
"type": "configure",
"name": "mimxrt1060_evk"
},
{
"type": "build",
"name": "mimxrt1060_evk"
}
]
},
{
"name": "mimxrt1064_evk",
"steps": [
{
"type": "configure",
"name": "mimxrt1064_evk"
},
{
"type": "build",
"name": "mimxrt1064_evk"
}
]
},
{
"name": "mimxrt1170_evkb",
"steps": [
{
"type": "configure",
"name": "mimxrt1170_evkb"
},
{
"type": "build",
"name": "mimxrt1170_evkb"
}
]
},
{
"name": "mm32f327x_mb39",
"steps": [
{
"type": "configure",
"name": "mm32f327x_mb39"
},
{
"type": "build",
"name": "mm32f327x_mb39"
}
]
},
{
"name": "mm32f327x_pitaya_lite",
"steps": [
{
"type": "configure",
"name": "mm32f327x_pitaya_lite"
},
{
"type": "build",
"name": "mm32f327x_pitaya_lite"
}
]
},
{
"name": "msp_exp430f5529lp",
"steps": [
{
"type": "configure",
"name": "msp_exp430f5529lp"
},
{
"type": "build",
"name": "msp_exp430f5529lp"
}
]
},
{
"name": "msp_exp432e401y",
"steps": [
{
"type": "configure",
"name": "msp_exp432e401y"
},
{
"type": "build",
"name": "msp_exp432e401y"
}
]
},
{
"name": "nanoch32v203",
"steps": [
{
"type": "configure",
"name": "nanoch32v203"
},
{
"type": "build",
"name": "nanoch32v203"
}
]
},
{
"name": "nanoch32v305",
"steps": [
{
"type": "configure",
"name": "nanoch32v305"
},
{
"type": "build",
"name": "nanoch32v305"
}
]
},
{
"name": "nrf52833dk",
"steps": [
{
"type": "configure",
"name": "nrf52833dk"
},
{
"type": "build",
"name": "nrf52833dk"
}
]
},
{
"name": "nrf52840dk",
"steps": [
{
"type": "configure",
"name": "nrf52840dk"
},
{
"type": "build",
"name": "nrf52840dk"
}
]
},
{
"name": "nrf52840dongle",
"steps": [
{
"type": "configure",
"name": "nrf52840dongle"
},
{
"type": "build",
"name": "nrf52840dongle"
}
]
},
{
"name": "nrf5340dk",
"steps": [
{
"type": "configure",
"name": "nrf5340dk"
},
{
"type": "build",
"name": "nrf5340dk"
}
]
},
{
"name": "nrf54h20dk",
"steps": [
{
"type": "configure",
"name": "nrf54h20dk"
},
{
"type": "build",
"name": "nrf54h20dk"
}
]
},
{
"name": "nutiny_nuc126v",
"steps": [
{
"type": "configure",
"name": "nutiny_nuc126v"
},
{
"type": "build",
"name": "nutiny_nuc126v"
}
]
},
{
"name": "nutiny_sdk_nuc120",
"steps": [
{
"type": "configure",
"name": "nutiny_sdk_nuc120"
},
{
"type": "build",
"name": "nutiny_sdk_nuc120"
}
]
},
{
"name": "nutiny_sdk_nuc121",
"steps": [
{
"type": "configure",
"name": "nutiny_sdk_nuc121"
},
{
"type": "build",
"name": "nutiny_sdk_nuc121"
}
]
},
{
"name": "nutiny_sdk_nuc125",
"steps": [
{
"type": "configure",
"name": "nutiny_sdk_nuc125"
},
{
"type": "build",
"name": "nutiny_sdk_nuc125"
}
]
},
{
"name": "nutiny_sdk_nuc505",
"steps": [
{
"type": "configure",
"name": "nutiny_sdk_nuc505"
},
{
"type": "build",
"name": "nutiny_sdk_nuc505"
}
]
},
{
"name": "pico_sdk",
"steps": [
{
"type": "configure",
"name": "pico_sdk"
},
{
"type": "build",
"name": "pico_sdk"
}
]
},
{
"name": "portenta_c33",
"steps": [
{
"type": "configure",
"name": "portenta_c33"
},
{
"type": "build",
"name": "portenta_c33"
}
]
},
{
"name": "pybadge",
"steps": [
{
"type": "configure",
"name": "pybadge"
},
{
"type": "build",
"name": "pybadge"
}
]
},
{
"name": "pyboardv11",
"steps": [
{
"type": "configure",
"name": "pyboardv11"
},
{
"type": "build",
"name": "pyboardv11"
}
]
},
{
"name": "pyportal",
"steps": [
{
"type": "configure",
"name": "pyportal"
},
{
"type": "build",
"name": "pyportal"
}
]
},
{
"name": "qtpy",
"steps": [
{
"type": "configure",
"name": "qtpy"
},
{
"type": "build",
"name": "qtpy"
}
]
},
{
"name": "ra2a1_ek",
"steps": [
{
"type": "configure",
"name": "ra2a1_ek"
},
{
"type": "build",
"name": "ra2a1_ek"
}
]
},
{
"name": "ra4m1_ek",
"steps": [
{
"type": "configure",
"name": "ra4m1_ek"
},
{
"type": "build",
"name": "ra4m1_ek"
}
]
},
{
"name": "ra4m3_ek",
"steps": [
{
"type": "configure",
"name": "ra4m3_ek"
},
{
"type": "build",
"name": "ra4m3_ek"
}
]
},
{
"name": "ra6m1_ek",
"steps": [
{
"type": "configure",
"name": "ra6m1_ek"
},
{
"type": "build",
"name": "ra6m1_ek"
}
]
},
{
"name": "ra6m5_ek",
"steps": [
{
"type": "configure",
"name": "ra6m5_ek"
},
{
"type": "build",
"name": "ra6m5_ek"
}
]
},
{
"name": "ra8m1_ek",
"steps": [
{
"type": "configure",
"name": "ra8m1_ek"
},
{
"type": "build",
"name": "ra8m1_ek"
}
]
},
{
"name": "raspberry_pi_pico",
"steps": [
{
"type": "configure",
"name": "raspberry_pi_pico"
},
{
"type": "build",
"name": "raspberry_pi_pico"
}
]
},
{
"name": "raspberry_pi_pico2",
"steps": [
{
"type": "configure",
"name": "raspberry_pi_pico2"
},
{
"type": "build",
"name": "raspberry_pi_pico2"
}
]
},
{
"name": "raspberry_pi_pico_w",
"steps": [
{
"type": "configure",
"name": "raspberry_pi_pico_w"
},
{
"type": "build",
"name": "raspberry_pi_pico_w"
}
]
},
{
"name": "raspberrypi_cm4",
"steps": [
{
"type": "configure",
"name": "raspberrypi_cm4"
},
{
"type": "build",
"name": "raspberrypi_cm4"
}
]
},
{
"name": "raspberrypi_zero",
"steps": [
{
"type": "configure",
"name": "raspberrypi_zero"
},
{
"type": "build",
"name": "raspberrypi_zero"
}
]
},
{
"name": "raspberrypi_zero2",
"steps": [
{
"type": "configure",
"name": "raspberrypi_zero2"
},
{
"type": "build",
"name": "raspberrypi_zero2"
}
]
},
{
"name": "samd11_xplained",
"steps": [
{
"type": "configure",
"name": "samd11_xplained"
},
{
"type": "build",
"name": "samd11_xplained"
}
]
},
{
"name": "same54_xplained",
"steps": [
{
"type": "configure",
"name": "same54_xplained"
},
{
"type": "build",
"name": "same54_xplained"
}
]
},
{
"name": "same70_qmtech",
"steps": [
{
"type": "configure",
"name": "same70_qmtech"
},
{
"type": "build",
"name": "same70_qmtech"
}
]
},
{
"name": "same70_xplained",
"steps": [
{
"type": "configure",
"name": "same70_xplained"
},
{
"type": "build",
"name": "same70_xplained"
}
]
},
{
"name": "samg55_xplained",
"steps": [
{
"type": "configure",
"name": "samg55_xplained"
},
{
"type": "build",
"name": "samg55_xplained"
}
]
},
{
"name": "saml22_feather",
"steps": [
{
"type": "configure",
"name": "saml22_feather"
},
{
"type": "build",
"name": "saml22_feather"
}
]
},
{
"name": "seeeduino_xiao",
"steps": [
{
"type": "configure",
"name": "seeeduino_xiao"
},
{
"type": "build",
"name": "seeeduino_xiao"
}
]
},
{
"name": "sensorwatch_m0",
"steps": [
{
"type": "configure",
"name": "sensorwatch_m0"
},
{
"type": "build",
"name": "sensorwatch_m0"
}
]
},
{
"name": "sipeed_longan_nano",
"steps": [
{
"type": "configure",
"name": "sipeed_longan_nano"
},
{
"type": "build",
"name": "sipeed_longan_nano"
}
]
},
{
"name": "sltb009a",
"steps": [
{
"type": "configure",
"name": "sltb009a"
},
{
"type": "build",
"name": "sltb009a"
}
]
},
{
"name": "sparkfun_samd21_mini_usb",
"steps": [
{
"type": "configure",
"name": "sparkfun_samd21_mini_usb"
},
{
"type": "build",
"name": "sparkfun_samd21_mini_usb"
}
]
},
{
"name": "spresense",
"steps": [
{
"type": "configure",
"name": "spresense"
},
{
"type": "build",
"name": "spresense"
}
]
},
{
"name": "stlinkv3mini",
"steps": [
{
"type": "configure",
"name": "stlinkv3mini"
},
{
"type": "build",
"name": "stlinkv3mini"
}
]
},
{
"name": "stm32c071nucleo",
"steps": [
{
"type": "configure",
"name": "stm32c071nucleo"
},
{
"type": "build",
"name": "stm32c071nucleo"
}
]
},
{
"name": "stm32f070rbnucleo",
"steps": [
{
"type": "configure",
"name": "stm32f070rbnucleo"
},
{
"type": "build",
"name": "stm32f070rbnucleo"
}
]
},
{
"name": "stm32f072disco",
"steps": [
{
"type": "configure",
"name": "stm32f072disco"
},
{
"type": "build",
"name": "stm32f072disco"
}
]
},
{
"name": "stm32f072eval",
"steps": [
{
"type": "configure",
"name": "stm32f072eval"
},
{
"type": "build",
"name": "stm32f072eval"
}
]
},
{
"name": "stm32f103_bluepill",
"steps": [
{
"type": "configure",
"name": "stm32f103_bluepill"
},
{
"type": "build",
"name": "stm32f103_bluepill"
}
]
},
{
"name": "stm32f103_mini_2",
"steps": [
{
"type": "configure",
"name": "stm32f103_mini_2"
},
{
"type": "build",
"name": "stm32f103_mini_2"
}
]
},
{
"name": "stm32f103ze_iar",
"steps": [
{
"type": "configure",
"name": "stm32f103ze_iar"
},
{
"type": "build",
"name": "stm32f103ze_iar"
}
]
},
{
"name": "stm32f207nucleo",
"steps": [
{
"type": "configure",
"name": "stm32f207nucleo"
},
{
"type": "build",
"name": "stm32f207nucleo"
}
]
},
{
"name": "stm32f303disco",
"steps": [
{
"type": "configure",
"name": "stm32f303disco"
},
{
"type": "build",
"name": "stm32f303disco"
}
]
},
{
"name": "stm32f401blackpill",
"steps": [
{
"type": "configure",
"name": "stm32f401blackpill"
},
{
"type": "build",
"name": "stm32f401blackpill"
}
]
},
{
"name": "stm32f407blackvet",
"steps": [
{
"type": "configure",
"name": "stm32f407blackvet"
},
{
"type": "build",
"name": "stm32f407blackvet"
}
]
},
{
"name": "stm32f407disco",
"steps": [
{
"type": "configure",
"name": "stm32f407disco"
},
{
"type": "build",
"name": "stm32f407disco"
}
]
},
{
"name": "stm32f411blackpill",
"steps": [
{
"type": "configure",
"name": "stm32f411blackpill"
},
{
"type": "build",
"name": "stm32f411blackpill"
}
]
},
{
"name": "stm32f411disco",
"steps": [
{
"type": "configure",
"name": "stm32f411disco"
},
{
"type": "build",
"name": "stm32f411disco"
}
]
},
{
"name": "stm32f412disco",
"steps": [
{
"type": "configure",
"name": "stm32f412disco"
},
{
"type": "build",
"name": "stm32f412disco"
}
]
},
{
"name": "stm32f412nucleo",
"steps": [
{
"type": "configure",
"name": "stm32f412nucleo"
},
{
"type": "build",
"name": "stm32f412nucleo"
}
]
},
{
"name": "stm32f439nucleo",
"steps": [
{
"type": "configure",
"name": "stm32f439nucleo"
},
{
"type": "build",
"name": "stm32f439nucleo"
}
]
},
{
"name": "stm32f723disco",
"steps": [
{
"type": "configure",
"name": "stm32f723disco"
},
{
"type": "build",
"name": "stm32f723disco"
}
]
},
{
"name": "stm32f746disco",
"steps": [
{
"type": "configure",
"name": "stm32f746disco"
},
{
"type": "build",
"name": "stm32f746disco"
}
]
},
{
"name": "stm32f746nucleo",
"steps": [
{
"type": "configure",
"name": "stm32f746nucleo"
},
{
"type": "build",
"name": "stm32f746nucleo"
}
]
},
{
"name": "stm32f767nucleo",
"steps": [
{
"type": "configure",
"name": "stm32f767nucleo"
},
{
"type": "build",
"name": "stm32f767nucleo"
}
]
},
{
"name": "stm32f769disco",
"steps": [
{
"type": "configure",
"name": "stm32f769disco"
},
{
"type": "build",
"name": "stm32f769disco"
}
]
},
{
"name": "stm32g0b1nucleo",
"steps": [
{
"type": "configure",
"name": "stm32g0b1nucleo"
},
{
"type": "build",
"name": "stm32g0b1nucleo"
}
]
},
{
"name": "stm32g474nucleo",
"steps": [
{
"type": "configure",
"name": "stm32g474nucleo"
},
{
"type": "build",
"name": "stm32g474nucleo"
}
]
},
{
"name": "stm32g491nucleo",
"steps": [
{
"type": "configure",
"name": "stm32g491nucleo"
},
{
"type": "build",
"name": "stm32g491nucleo"
}
]
},
{
"name": "stm32h503nucleo",
"steps": [
{
"type": "configure",
"name": "stm32h503nucleo"
},
{
"type": "build",
"name": "stm32h503nucleo"
}
]
},
{
"name": "stm32h563nucleo",
"steps": [
{
"type": "configure",
"name": "stm32h563nucleo"
},
{
"type": "build",
"name": "stm32h563nucleo"
}
]
},
{
"name": "stm32h573i_dk",
"steps": [
{
"type": "configure",
"name": "stm32h573i_dk"
},
{
"type": "build",
"name": "stm32h573i_dk"
}
]
},
{
"name": "stm32h723nucleo",
"steps": [
{
"type": "configure",
"name": "stm32h723nucleo"
},
{
"type": "build",
"name": "stm32h723nucleo"
}
]
},
{
"name": "stm32h743eval",
"steps": [
{
"type": "configure",
"name": "stm32h743eval"
},
{
"type": "build",
"name": "stm32h743eval"
}
]
},
{
"name": "stm32h743nucleo",
"steps": [
{
"type": "configure",
"name": "stm32h743nucleo"
},
{
"type": "build",
"name": "stm32h743nucleo"
}
]
},
{
"name": "stm32h745disco",
"steps": [
{
"type": "configure",
"name": "stm32h745disco"
},
{
"type": "build",
"name": "stm32h745disco"
}
]
},
{
"name": "stm32h747disco",
"steps": [
{
"type": "configure",
"name": "stm32h747disco"
},
{
"type": "build",
"name": "stm32h747disco"
}
]
},
{
"name": "stm32h750_weact",
"steps": [
{
"type": "configure",
"name": "stm32h750_weact"
},
{
"type": "build",
"name": "stm32h750_weact"
}
]
},
{
"name": "stm32h750bdk",
"steps": [
{
"type": "configure",
"name": "stm32h750bdk"
},
{
"type": "build",
"name": "stm32h750bdk"
}
]
},
{
"name": "stm32h7s3nucleo",
"steps": [
{
"type": "configure",
"name": "stm32h7s3nucleo"
},
{
"type": "build",
"name": "stm32h7s3nucleo"
}
]
},
{
"name": "stm32l052dap52",
"steps": [
{
"type": "configure",
"name": "stm32l052dap52"
},
{
"type": "build",
"name": "stm32l052dap52"
}
]
},
{
"name": "stm32l0538disco",
"steps": [
{
"type": "configure",
"name": "stm32l0538disco"
},
{
"type": "build",
"name": "stm32l0538disco"
}
]
},
{
"name": "stm32l412nucleo",
"steps": [
{
"type": "configure",
"name": "stm32l412nucleo"
},
{
"type": "build",
"name": "stm32l412nucleo"
}
]
},
{
"name": "stm32l476disco",
"steps": [
{
"type": "configure",
"name": "stm32l476disco"
},
{
"type": "build",
"name": "stm32l476disco"
}
]
},
{
"name": "stm32l496nucleo",
"steps": [
{
"type": "configure",
"name": "stm32l496nucleo"
},
{
"type": "build",
"name": "stm32l496nucleo"
}
]
},
{
"name": "stm32l4p5nucleo",
"steps": [
{
"type": "configure",
"name": "stm32l4p5nucleo"
},
{
"type": "build",
"name": "stm32l4p5nucleo"
}
]
},
{
"name": "stm32l4r5nucleo",
"steps": [
{
"type": "configure",
"name": "stm32l4r5nucleo"
},
{
"type": "build",
"name": "stm32l4r5nucleo"
}
]
},
{
"name": "stm32n6570dk",
"steps": [
{
"type": "configure",
"name": "stm32n6570dk"
},
{
"type": "build",
"name": "stm32n6570dk"
}
]
},
{
"name": "stm32n657nucleo",
"steps": [
{
"type": "configure",
"name": "stm32n657nucleo"
},
{
"type": "build",
"name": "stm32n657nucleo"
}
]
},
{
"name": "stm32u083cdk",
"steps": [
{
"type": "configure",
"name": "stm32u083cdk"
},
{
"type": "build",
"name": "stm32u083cdk"
}
]
},
{
"name": "stm32u545nucleo",
"steps": [
{
"type": "configure",
"name": "stm32u545nucleo"
},
{
"type": "build",
"name": "stm32u545nucleo"
}
]
},
{
"name": "stm32u575eval",
"steps": [
{
"type": "configure",
"name": "stm32u575eval"
},
{
"type": "build",
"name": "stm32u575eval"
}
]
},
{
"name": "stm32u575nucleo",
"steps": [
{
"type": "configure",
"name": "stm32u575nucleo"
},
{
"type": "build",
"name": "stm32u575nucleo"
}
]
},
{
"name": "stm32u5a5nucleo",
"steps": [
{
"type": "configure",
"name": "stm32u5a5nucleo"
},
{
"type": "build",
"name": "stm32u5a5nucleo"
}
]
},
{
"name": "stm32wb55nucleo",
"steps": [
{
"type": "configure",
"name": "stm32wb55nucleo"
},
{
"type": "build",
"name": "stm32wb55nucleo"
}
]
},
{
"name": "stm32wba_nucleo",
"steps": [
{
"type": "configure",
"name": "stm32wba_nucleo"
},
{
"type": "build",
"name": "stm32wba_nucleo"
}
]
},
{
"name": "teensy_35",
"steps": [
{
"type": "configure",
"name": "teensy_35"
},
{
"type": "build",
"name": "teensy_35"
}
]
},
{
"name": "teensy_40",
"steps": [
{
"type": "configure",
"name": "teensy_40"
},
{
"type": "build",
"name": "teensy_40"
}
]
},
{
"name": "teensy_41",
"steps": [
{
"type": "configure",
"name": "teensy_41"
},
{
"type": "build",
"name": "teensy_41"
}
]
},
{
"name": "trinket_m0",
"steps": [
{
"type": "configure",
"name": "trinket_m0"
},
{
"type": "build",
"name": "trinket_m0"
}
]
},
{
"name": "uno_r4",
"steps": [
{
"type": "configure",
"name": "uno_r4"
},
{
"type": "build",
"name": "uno_r4"
}
]
},
{
"name": "waveshare_openh743i",
"steps": [
{
"type": "configure",
"name": "waveshare_openh743i"
},
{
"type": "build",
"name": "waveshare_openh743i"
}
]
},
{
"name": "xmc4500_relax",
"steps": [
{
"type": "configure",
"name": "xmc4500_relax"
},
{
"type": "build",
"name": "xmc4500_relax"
}
]
},
{
"name": "xmc4700_relax",
"steps": [
{
"type": "configure",
"name": "xmc4700_relax"
},
{
"type": "build",
"name": "xmc4700_relax"
}
]
}
]
}
================================================
FILE: hw/bsp/ansi_escape.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/** \ingroup group_board
* \defgroup group_ansi_esc ANSI Escape Code
* @{ */
#ifndef TUSB_ANSI_ESC_CODE_H_
#define TUSB_ANSI_ESC_CODE_H_
#ifdef __cplusplus
extern "C" {
#endif
#define CSI_CODE(seq) "\33[" seq
#define CSI_SGR(x) CSI_CODE(#x) "m"
//------------- Cursor movement -------------//
/** \defgroup group_ansi_cursor Cursor Movement
* @{ */
#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A") ///< Move cursor up
#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B") ///< Move cursor down
#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C") ///< Move cursor forward
#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D") ///< Move cursor backward
#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E") ///< Move cursor to the beginning of the line (n) down
#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F") ///< Move cursor to the beginning of the line (n) up
#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H") ///< Move cursor to position (n, m)
/** @} */
//------------- Screen -------------//
/** \defgroup group_ansi_screen Screen Control
* @{ */
#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J") ///< Erase the screen
#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K") ///< Erase the line (n)
#define ANSI_SCROLL_UP(n) CSI_CODE(#n "S") ///< Scroll the whole page up (n) lines
#define ANSI_SCROLL_DOWN(n) CSI_CODE(#n "T") ///< Scroll the whole page down (n) lines
/** @} */
//------------- Text Color -------------//
/** \defgroup group_ansi_text Text Color
* @{ */
#define ANSI_TEXT_BLACK CSI_SGR(30)
#define ANSI_TEXT_RED CSI_SGR(31)
#define ANSI_TEXT_GREEN CSI_SGR(32)
#define ANSI_TEXT_YELLOW CSI_SGR(33)
#define ANSI_TEXT_BLUE CSI_SGR(34)
#define ANSI_TEXT_MAGENTA CSI_SGR(35)
#define ANSI_TEXT_CYAN CSI_SGR(36)
#define ANSI_TEXT_WHITE CSI_SGR(37)
#define ANSI_TEXT_DEFAULT CSI_SGR(39)
/** @} */
//------------- Background Color -------------//
/** \defgroup group_ansi_background Background Color
* @{ */
#define ANSI_BG_BLACK CSI_SGR(40)
#define ANSI_BG_RED CSI_SGR(41)
#define ANSI_BG_GREEN CSI_SGR(42)
#define ANSI_BG_YELLOW CSI_SGR(43)
#define ANSI_BG_BLUE CSI_SGR(44)
#define ANSI_BG_MAGENTA CSI_SGR(45)
#define ANSI_BG_CYAN CSI_SGR(46)
#define ANSI_BG_WHITE CSI_SGR(47)
#define ANSI_BG_DEFAULT CSI_SGR(49)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* TUSB_ANSI_ESC_CODE_H_ */
/** @} */
================================================
FILE: hw/bsp/at32f402_405/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f402_405.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<CTRL &= ~1U;
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
NVIC_SetPriority(OTGHS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
NVIC_SetPriority(OTGFS1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
#endif
/* config led and key */
led_and_botton_init();
/* config usart to printf */
uart_print_init(115200);
// printf("usart printf config success!\r\n");
}
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
void led_and_botton_init(void)
{
/* LED */
gpio_init_type gpio_led_init_struct;
/* enable the led clock */
LED_GPIO_CLK_EN();
/* set default parameter */
gpio_default_para_init(&gpio_led_init_struct);
/* configure the led gpio */
gpio_led_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_led_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_led_init_struct.gpio_pins = LED_PIN | GPIO_PINS_5 | GPIO_PINS_6;
gpio_led_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(LED_PORT, &gpio_led_init_struct);
gpio_bits_set(LED_PORT, GPIO_PINS_5);
gpio_bits_set(LED_PORT, GPIO_PINS_6);
/* Button */
gpio_init_type gpio_button_init_struct;
/* enable the button clock */
BUTTON_GPIO_CLK_EN();
/* set default parameter */
gpio_default_para_init(&gpio_button_init_struct);
/* configure the button gpio */
gpio_button_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_button_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_button_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_button_init_struct.gpio_pins = BUTTON_PIN;
gpio_button_init_struct.gpio_pull = GPIO_PULL_DOWN;
gpio_init(BUTTON_PORT, &gpio_button_init_struct);
}
/**
* @brief usb 48M clock select
* @param clk_s:USB_CLK_HICK, USB_CLK_HEXT
* @retval none
*/
void usb_clock48m_select(usb_clk48_s clk_s)
{
if(clk_s == USB_CLK_HICK)
{
crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
/* enable the acc calibration ready interrupt */
crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
/* update the c1\c2\c3 value */
acc_write_c1(7980);
acc_write_c2(8000);
acc_write_c3(8020);
/* open acc calibration */
acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
}
else
{
crm_pllu_output_set(TRUE);
/* wait till pll is ready */
while(crm_flag_get(CRM_PLLU_STABLE_FLAG) != SET){}
crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_PLLU);
}
}
void usb_gpio_config(void)
{
/* When the USB clock is enabled, the hardware will automatically
configure the pins; but other special pins that need to be used,
such as the pins used to detect VBUS or the pins that output the
SOF signal, still need to be configured separately, and these pins
are usually not required */
}
/**
* @brief initialize uart
* @param baudrate: uart baudrate
* @retval none
*/
void uart_print_init(uint32_t baudrate)
{
gpio_init_type gpio_init_struct;
/* enable the uart and gpio clock */
crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);
crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);
gpio_default_para_init(&gpio_init_struct);
/* configure the uart tx pin */
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(PRINT_UART_TX_GPIO, &gpio_init_struct);
gpio_pin_mux_config(PRINT_UART_TX_GPIO, PRINT_UART_TX_PIN_SOURCE, PRINT_UART_TX_PIN_MUX_NUM);
/* configure uart param */
usart_init(PRINT_UART, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
usart_transmitter_enable(PRINT_UART, TRUE);
usart_enable(PRINT_UART, TRUE);
}
// Get characters from UART. Return number of read bytes
int board_uart_read(uint8_t *buf, int len) {
(void) buf;
(void) len;
return 0;
}
// Send characters to UART. Return number of sent bytes
int board_uart_write(void const *buf, int len)
{
#if CFG_TUSB_OS == OPT_OS_NONE
int txsize = len;
u16 timeout = 0xffff;
while (txsize--)
{
while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET)
{
timeout--;
if(timeout == 0)
{
return 0;
}
}
PRINT_UART->dt = (*((uint8_t const *)buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
void board_led_write(bool state)
{
gpio_bits_write(LED_PORT, LED_PIN, state ^ (!LED_STATE_ON));
}
uint32_t board_button_read(void)
{
return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN);
}
size_t board_get_unique_id(uint8_t id[], size_t max_len)
{
(void) max_len;
volatile uint32_t * at32_uuid = ((volatile uint32_t*)0x1FFFF7E8);
uint32_t* id32 = (uint32_t*) (uintptr_t) id;
uint8_t const len = 12;
id32[0] = at32_uuid[0];
id32[1] = at32_uuid[1];
id32[2] = at32_uuid[2];
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void)
{
system_ticks++;
}
uint32_t tusb_time_millis_api(void)
{
return system_ticks;
}
void SVC_Handler(void)
{
}
void PendSV_Handler(void)
{
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f402_405/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f402_405)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
if (NOT DEFINED RHPORT_DEVICE)
set(RHPORT_DEVICE 0)
endif ()
if (NOT DEFINED RHPORT_HOST)
set(RHPORT_HOST 0)
endif ()
if (NOT DEFINED RHPORT_SPEED)
set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_FULL_SPEED)
endif ()
if (NOT DEFINED RHPORT_DEVICE_SPEED)
list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED)
endif ()
if (NOT DEFINED RHPORT_HOST_SPEED)
list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED)
endif ()
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
BOARD_TUD_RHPORT=${RHPORT_DEVICE}
BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED}
BOARD_TUH_RHPORT=${RHPORT_HOST}
BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED}
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f402_405/family.mk
================================================
AT32_FAMILY = at32f402_405
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS_GCC += \
-flto
RHPORT_SPEED ?= OPT_MODE_FULL_SPEED OPT_MODE_FULL_SPEED
RHPORT_DEVICE ?= 0
RHPORT_HOST ?= 0
ifndef RHPORT_DEVICE_SPEED
ifeq ($(RHPORT_DEVICE), 0)
RHPORT_DEVICE_SPEED = $(firstword $(RHPORT_SPEED))
else
RHPORT_DEVICE_SPEED = $(lastword $(RHPORT_SPEED))
endif
endif
ifndef RHPORT_HOST_SPEED
ifeq ($(RHPORT_HOST), 0)
RHPORT_HOST_SPEED = $(firstword $(RHPORT_SPEED))
else
RHPORT_HOST_SPEED = $(lastword $(RHPORT_SPEED))
endif
endif
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F402_405 \
-DBOARD_TUD_RHPORT=${RHPORT_DEVICE} \
-DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \
-DBOARD_TUH_RHPORT=${RHPORT_HOST} \
-DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F
flash: flash-atlink
================================================
FILE: hw/bsp/at32f403a_407/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f403a_407.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<dt = (*((uint8_t const *) buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
void SVC_Handler(void) {
}
void PendSV_Handler(void) {
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f403a_407/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f403a_407)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f403a_407/family.mk
================================================
AT32_FAMILY = at32f403a_407
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS_GCC += \
-flto
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F403A_407
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F
flash: flash-atlink
================================================
FILE: hw/bsp/at32f413/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f413.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<dt = (*((uint8_t const *) buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
void SVC_Handler(void) {
}
void PendSV_Handler(void) {
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f413/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f413)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f413/family.mk
================================================
AT32_FAMILY = at32f413
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS_GCC += \
-flto
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F413
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F
flash: flash-atlink
================================================
FILE: hw/bsp/at32f415/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f415.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<dt = (*((uint8_t const *) buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
void board_led_write(bool state) {
gpio_bits_write(LED_PORT, LED_PIN, state ^ (!LED_STATE_ON));
}
uint32_t board_button_read(void) {
return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN);
}
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
(void) max_len;
volatile uint32_t *at32_uuid = ((volatile uint32_t *) 0x1FFFF7E8);
uint32_t *id32 = (uint32_t *) (uintptr_t) id;
uint8_t const len = 12;
id32[0] = at32_uuid[0];
id32[1] = at32_uuid[1];
id32[2] = at32_uuid[2];
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
void SVC_Handler(void) {
}
void PendSV_Handler(void) {
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f415/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f415)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4-nofpu CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f415/family.mk
================================================
AT32_FAMILY = at32f415
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4-nofpu
CFLAGS_GCC += \
-flto
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F415 \
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
flash: flash-atlink
================================================
FILE: hw/bsp/at32f423/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f423.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<dt = (*((uint8_t const *) buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
void SVC_Handler(void) {
}
void PendSV_Handler(void) {
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f423/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f423)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f423/family.mk
================================================
AT32_FAMILY = at32f423
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS_GCC += \
-flto
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F423 \
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
flash: flash-atlink
================================================
FILE: hw/bsp/at32f425/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f425.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<dt = (*((uint8_t const *) buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
void board_led_write(bool state) {
gpio_bits_write(LED_PORT, LED_PIN, state ^ (!LED_STATE_ON));
}
uint32_t board_button_read(void) {
return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN);
}
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
(void) max_len;
volatile uint32_t *at32_uuid = ((volatile uint32_t *) 0x1FFFF7E8);
uint32_t *id32 = (uint32_t *) (uintptr_t) id;
uint8_t const len = 12;
id32[0] = at32_uuid[0];
id32[1] = at32_uuid[1];
id32[2] = at32_uuid[2];
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
void SVC_Handler(void) {
}
void PendSV_Handler(void) {
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f425/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f425)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4-nofpu CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f425/family.mk
================================================
AT32_FAMILY = at32f425
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4-nofpu
CFLAGS_GCC += \
-flto
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F425 \
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
flash: flash-atlink
================================================
FILE: hw/bsp/at32f435_437/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f435_437.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<CTRL &= ~1U;
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
NVIC_SetPriority(OTGFS1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
NVIC_SetPriority(OTGFS2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
#else
SysTick_Config(SystemCoreClock / 1000);
NVIC_SetPriority(OTGFS1_IRQn, 0);
NVIC_SetPriority(OTGFS2_IRQn, 0);
#endif
/* config led and key */
led_and_botton_init();
/* config usart printf */
uart_print_init(115200);
}
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
/**
* @brief usb 48M clock select
* @param clk_s:USB_CLK_HICK, USB_CLK_HEXT
* @retval none
*/
void usb_clock48m_select(usb_clk48_s clk_s) {
if (clk_s == USB_CLK_HICK) {
crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
/* enable the acc calibration ready interrupt */
crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
/* update the c1\c2\c3 value */
acc_write_c1(7980);
acc_write_c2(8000);
acc_write_c3(8020);
#ifdef BOARD_TUD_RHPORT
#if BOARD_TUD_RHPORT == 0
acc_sof_select(ACC_SOF_OTG1);
#else
acc_sof_select(ACC_SOF_OTG2);
#endif
#endif
/* open acc calibration */
acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
} else {
switch (system_core_clock) {
/* 48MHz */
case 48000000:
crm_usb_clock_div_set(CRM_USB_DIV_1);
break;
/* 72MHz */
case 72000000:
crm_usb_clock_div_set(CRM_USB_DIV_1_5);
break;
/* 96MHz */
case 96000000:
crm_usb_clock_div_set(CRM_USB_DIV_2);
break;
/* 120MHz */
case 120000000:
crm_usb_clock_div_set(CRM_USB_DIV_2_5);
break;
/* 144MHz */
case 144000000:
crm_usb_clock_div_set(CRM_USB_DIV_3);
break;
/* 168MHz */
case 168000000:
crm_usb_clock_div_set(CRM_USB_DIV_3_5);
break;
/* 192MHz */
case 192000000:
crm_usb_clock_div_set(CRM_USB_DIV_4);
break;
/* 216MHz */
case 216000000:
crm_usb_clock_div_set(CRM_USB_DIV_4_5);
break;
/* 240MHz */
case 240000000:
crm_usb_clock_div_set(CRM_USB_DIV_5);
break;
/* 264MHz */
case 264000000:
crm_usb_clock_div_set(CRM_USB_DIV_5_5);
break;
/* 288MHz */
case 288000000:
crm_usb_clock_div_set(CRM_USB_DIV_6);
break;
default:
break;
}
}
}
void led_and_botton_init(void) {
/* LED */
gpio_init_type gpio_led_init_struct;
/* enable the led clock */
LED_GPIO_CLK_EN();
/* set default parameter */
gpio_default_para_init(&gpio_led_init_struct);
/* configure the led gpio */
gpio_led_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_led_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_led_init_struct.gpio_pins = LED_PIN;
gpio_led_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(LED_PORT, &gpio_led_init_struct);
gpio_bits_set(LED_PORT, LED_PIN);
gpio_bits_set(LED_PORT, GPIO_PINS_14);
gpio_bits_set(LED_PORT, GPIO_PINS_15);
/* Button */
gpio_init_type gpio_button_init_struct;
/* enable the button clock */
BUTTON_GPIO_CLK_EN();
/* set default parameter */
gpio_default_para_init(&gpio_button_init_struct);
/* configure the button gpio */
gpio_button_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_button_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_button_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_button_init_struct.gpio_pins = BUTTON_PIN;
gpio_button_init_struct.gpio_pull = GPIO_PULL_DOWN;
gpio_init(BUTTON_PORT, &gpio_button_init_struct);
}
/**
* @brief initialize uart
* @param baudrate: uart baudrate
* @retval none
*/
void uart_print_init(uint32_t baudrate) {
gpio_init_type gpio_init_struct;
/* enable the uart and gpio clock */
crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);
crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);
gpio_default_para_init(&gpio_init_struct);
/* configure the uart tx pin */
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(PRINT_UART_TX_GPIO, &gpio_init_struct);
gpio_pin_mux_config(PRINT_UART_TX_GPIO, PRINT_UART_TX_PIN_SOURCE, PRINT_UART_TX_PIN_MUX_NUM);
/* configure uart param */
usart_init(PRINT_UART, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
usart_transmitter_enable(PRINT_UART, TRUE);
usart_enable(PRINT_UART, TRUE);
}
// Get characters from UART. Return number of read bytes
int board_uart_read(uint8_t *buf, int len) {
(void) buf;
(void) len;
return 0;
}
// Send characters to UART. Return number of sent bytes
int board_uart_write(void const *buf, int len) {
#if CFG_TUSB_OS == OPT_OS_NONE
int txsize = len;
u16 timeout = 0xffff;
while (txsize--) {
while (usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) {
timeout--;
if (timeout == 0) {
return 0;
}
}
PRINT_UART->dt = (*((uint8_t const *) buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
int inHandlerMode(void) {
return __get_IPSR();
}
void usb_gpio_config(void) {
gpio_init_type gpio_init_struct;
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
/* dp and dm */
gpio_init_struct.gpio_pins = GPIO_PINS_11 | GPIO_PINS_12;
gpio_init(GPIOA, &gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_14 | GPIO_PINS_15;
gpio_init(GPIOB, &gpio_init_struct);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE11, GPIO_MUX_10);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE12, GPIO_MUX_10);
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE14, GPIO_MUX_12);
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE15, GPIO_MUX_12);
}
void board_led_write(bool state) {
gpio_bits_write(LED_PORT, LED_PIN, state ^ (!LED_STATE_ON));
}
uint32_t board_button_read(void) {
return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN);
}
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
(void) max_len;
volatile uint32_t *at32_uuid = ((volatile uint32_t *) 0x1FFFF7E8);
uint32_t *id32 = (uint32_t *) (uintptr_t) id;
uint8_t const len = 12;
id32[0] = at32_uuid[0];
id32[1] = at32_uuid[1];
id32[2] = at32_uuid[2];
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
void SVC_Handler(void) {
}
void PendSV_Handler(void) {
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f435_437/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f435_437)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_exint.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
BOARD_TUD_RHPORT=1
BOARD_TUH_RHPORT=0
BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED
BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f435_437/family.mk
================================================
AT32_FAMILY = at32f435_437
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS_GCC += \
-flto
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F435_437 \
-DBOARD_TUD_RHPORT=1 \
-DBOARD_TUH_RHPORT=0 \
-DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED \
-DBOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED \
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_exint.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
flash: flash-atlink
================================================
FILE: hw/bsp/at32f45x/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
// Include MCU header
#include "at32f45x.h"
#endif
/* Cortex-M4 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ system_core_clock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
#ifdef __RX__
/* Renesas RX series */
#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
#define vTickISR INT_Excep_CMT0_CMI0
#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
#else
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
#if defined(__NVIC_PRIO_BITS)
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
#define configPRIO_BITS __NVIC_PRIO_BITS
#elif defined(__ECLIC_INTCTLBITS)
// RISC-V Bumblebee core from nuclei
#define configPRIO_BITS __ECLIC_INTCTLBITS
#elif defined(__IASMARM__)
// FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
// Therefore we will hard coded it to minimum value of 2 to get pass ci build.
// IAR user must update this to correct value of the target MCU
#message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
#define configPRIO_BITS 2
#else
#error "FreeRTOS configPRIO_BITS to be defined"
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<dt = (*((uint8_t const *) buf) & 0x01FF);
buf++;
}
return len;
#else
(void) buf;
(void) len;
return 0;
#endif
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
void SVC_Handler(void) {
}
void PendSV_Handler(void) {
}
#endif
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void);
void _init(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(const char *file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
e.g.: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/at32f45x/family.cmake
================================================
include_guard()
set(AT32_FAMILY at32f45x)
set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries)
string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s)
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf)
#------------------------------------
# BOARD_TARGET
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c
${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${AT32_SDK_LIB}/cmsis/cm4/core_support
${AT32_SDK_LIB}/cmsis/cm4/device_support
${AT32_SDK_LIB}/drivers/inc
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/at32f45x/family.mk
================================================
AT32_FAMILY = at32f45x
AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS_GCC += \
-flto
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_AT32F45X \
LDFLAGS_GCC += \
-flto --specs=nosys.specs -nostdlib -nostartfiles
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \
$(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(AT32_SDK_LIB)/drivers/inc \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \
$(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support
SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s
SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s
LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld
LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf
flash: flash-atlink
================================================
FILE: hw/bsp/board.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2018, hathach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "board_api.h"
//--------------------------------------------------------------------+
// newlib read()/write() retarget
//--------------------------------------------------------------------+
#ifdef __ICCARM__
#define sys_write __write
#define sys_read __read
#elif defined(__MSP430__) || defined(__RX__) || TU_CHECK_MCU(OPT_MCU_NUC120, OPT_MCU_NUC121, OPT_MCU_NUC126, OPT_MCU_NUC505)
#define sys_write write
#define sys_read read
#else
#define sys_write _write
#define sys_read _read
#endif
int sys_write(int fhdl, const char *buf, size_t count) TU_ATTR_USED;
int sys_read(int fhdl, char *buf, size_t count) TU_ATTR_USED;
#if defined(LOGGER_RTT)
// Logging with RTT
// If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead
#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM)
#include "SEGGER_RTT.h"
int sys_write(int fhdl, const char *buf, size_t count) {
(void) fhdl;
return (int) SEGGER_RTT_Write(0, buf, (int) count);
}
int sys_read(int fhdl, char *buf, size_t count) {
(void) fhdl;
int rd = (int) SEGGER_RTT_Read(0, buf, count);
return (rd > 0) ? rd : -1;
}
#endif
#elif defined(LOGGER_SWO)
#define ITM_BASE 0xE0000000
#define ITM_STIM0 (*((volatile uint8_t*)(ITM_BASE + 0)))
#define ITM_TER *((volatile uint32_t*)(ITM_BASE + 0xE00))
#define ITM_TCR *((volatile uint32_t*)(ITM_BASE + 0xE80))
#define ITM_TCR_ITMENA (1 << 0)
// Logging with SWO for ARM Cortex-M
int sys_write (int fhdl, const char *buf, size_t count) {
(void) fhdl;
uint8_t const* buf8 = (uint8_t const*) buf;
if ((ITM_TCR & ITM_TCR_ITMENA) && (ITM_TER & 1ul)) {
for(size_t i=0; i < count; i++) {
while (!(ITM_STIM0 & 1ul)) {
asm("nop");
}
ITM_STIM0 = buf8[i];
}
}
return (int) count;
}
int sys_read (int fhdl, char *buf, size_t count) {
(void) fhdl;
(void) buf;
(void) count;
return 0;
}
#else
// Default logging with on-board UART
int sys_write (int fhdl, const char *buf, size_t count) {
(void) fhdl;
return board_uart_write(buf, (int) count);
}
int sys_read (int fhdl, char *buf, size_t count) {
(void) fhdl;
int rd = board_uart_read((uint8_t*) buf, (int) count);
return (rd > 0) ? rd : -1;
}
#endif
// Clang use picolibc
#if defined(__clang__)
static int cl_putc(char c, FILE *f) {
(void) f;
return sys_write(0, &c, 1);
}
static int cl_getc(FILE* f) {
(void) f;
char c;
return sys_read(0, &c, 1) > 0 ? c : -1;
}
static FILE __stdio = FDEV_SETUP_STREAM(cl_putc, cl_getc, NULL, _FDEV_SETUP_RW);
FILE *const stdin = &__stdio;
__strong_reference(stdin, stdout);
__strong_reference(stdin, stderr);
#endif
//--------------------------------------------------------------------+
// Weak board API (to be optionally implemented by board)
//--------------------------------------------------------------------+
TU_ATTR_WEAK size_t board_get_unique_id(uint8_t id[], size_t max_len) {
(void) max_len;
// fixed serial string is 01234567889ABCDEF
uint32_t* uid32 = (uint32_t*) (uintptr_t)id;
uid32[0] = 0x67452301u;
uid32[1] = 0xEFCDAB89u;
return 8;
}
TU_ATTR_WEAK void board_init_after_tusb(void) {
// nothing to do
}
TU_ATTR_WEAK void board_reset_to_bootloader(void) {
// not implemented
}
//--------------------------------------------------------------------+
// Board API
//--------------------------------------------------------------------+
int board_getchar(void) {
char c;
return (sys_read(0, &c, 1) > 0) ? (int) c : (-1);
}
void board_putchar(int c) {
(void) sys_write(0, (const char*)&c, 1);
}
//--------------------------------------------------------------------
// FreeRTOS hooks
//--------------------------------------------------------------------
#if CFG_TUSB_OS == OPT_OS_FREERTOS && !defined(ESP_PLATFORM)
#include "FreeRTOS.h"
#include "task.h"
void vApplicationMallocFailedHook(void); // missing prototype
void vApplicationMallocFailedHook(void) {
taskDISABLE_INTERRUPTS();
TU_ASSERT(false, );
}
void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) {
(void) pxTask;
(void) pcTaskName;
taskDISABLE_INTERRUPTS();
TU_ASSERT(false, );
}
/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
* implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
* used by the Idle task. */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
/* If the buffers to be provided to the Idle task are declared inside this
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
* application must provide an implementation of vApplicationGetTimerTaskMemory()
* to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) {
/* If the buffers to be provided to the Timer task are declared inside this
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
/* Pass out a pointer to the StaticTask_t structure in which the Timer
task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#if CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X
void vApplicationSetupTimerInterrupt(void);
#include "iodefine.h"
void vApplicationSetupTimerInterrupt(void) {
/* Enable CMT0 */
unsigned short oldPRCR = SYSTEM.PRCR.WORD;
SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
MSTP(CMT0) = 0;
SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR;
CMT0.CMCNT = 0;
CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128);
CMT0.CMCR.WORD = TU_BIT(6) | 2;
IR(CMT0, CMI0) = 0;
IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY;
IEN(CMT0, CMI0) = 1;
CMT.CMSTR0.BIT.STR0 = 1;
}
#endif
#endif
//--------------------------------------------------------------------
// ThreadX hooks for ARM Cortex-M
//--------------------------------------------------------------------
#if CFG_TUSB_OS == OPT_OS_THREADX && defined(__ARM_ARCH)
#include "tx_api.h"
#include "tx_initialize.h"
// Newlib linker symbol: end of statically allocated RAM (start of heap)
extern ULONG _end;
// CMSIS standard variable for system clock frequency
extern uint32_t SystemCoreClock;
// Cortex-M SysTick registers (fixed addresses on all Cortex-M)
#define _TX_SYST_CSR (*((volatile uint32_t *)0xE000E010U))
#define _TX_SYST_RVR (*((volatile uint32_t *)0xE000E014U))
#define _TX_SYST_CVR (*((volatile uint32_t *)0xE000E018U))
// SCB->SHP[10] = PendSV priority, [11] = SysTick priority (byte access at SCB base + 0xD22)
#define _TX_SCB_SHPR3 (*((volatile uint32_t *)0xE000ED20U))
VOID _tx_initialize_low_level(VOID) {
// Set the first available memory address for tx_application_define
_tx_initialize_unused_memory = (VOID *)(&_end);
// Configure SysTick for ThreadX tick rate: enable with processor clock + interrupt
_TX_SYST_RVR = (SystemCoreClock / TX_TIMER_TICKS_PER_SECOND) - 1u;
_TX_SYST_CVR = 0u;
_TX_SYST_CSR = 0x07u; // CLKSOURCE=1, TICKINT=1, ENABLE=1
// SHPR3 bits[31:24] = SysTick priority, bits[23:16] = PendSV priority
// PendSV must be lowest priority (0xFF). SysTick must be higher than PendSV (0x40)
// so SysTick can preempt the PendSV scheduler idle loop (__tx_ts_wait) to tick the timer.
_TX_SCB_SHPR3 = (_TX_SCB_SHPR3 & 0x0000FFFFU) | 0x40FF0000U;
}
// Weak callback for board-specific SysTick work (e.g. HAL_IncTick on STM32)
void osal_threadx_tick_cb(void);
TU_ATTR_WEAK void osal_threadx_tick_cb(void) { }
// SysTick drives the ThreadX timer tick
extern void _tx_timer_interrupt(void);
void SysTick_Handler(void);
void SysTick_Handler(void) {
osal_threadx_tick_cb();
_tx_timer_interrupt();
}
#endif
================================================
FILE: hw/bsp/board_api.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef BOARD_API_H_
#define BOARD_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include
#include
#include
#include
#include
#include "tusb.h"
#if CFG_TUSB_OS == OPT_OS_ZEPHYR
#include
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
#ifdef ESP_PLATFORM
// ESP-IDF need "freertos/" prefix in include path.
// CFG_TUSB_OS_INC_PATH should be defined accordingly.
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#else
#include "FreeRTOS.h"
#include "semphr.h"
#include "queue.h"
#include "task.h"
#include "timers.h"
#endif
#endif
// Define the default baudrate
#ifndef CFG_BOARD_UART_BAUDRATE
#define CFG_BOARD_UART_BAUDRATE 115200 ///< Default baud rate
#endif
//--------------------------------------------------------------------+
// Board Porting API
// For simplicity, only one LED and one Button are used
//--------------------------------------------------------------------+
// Initialize on-board peripherals : led, button, uart and USB
void board_init(void);
// Init board after tinyusb is initialized
void board_init_after_tusb(void);
// Jump to bootloader
void board_reset_to_bootloader(void);
// Turn LED on or off
void board_led_write(bool state);
// Control led pattern using phase duration in ms.
// For each phase, LED is toggle then repeated, board_led_task() is required to be called
//void board_led_pattern(uint32_t const phase_ms[], uint8_t count);
// Get the current state of button
// a '1' means active (pressed), a '0' means inactive.
uint32_t board_button_read(void);
// Get board unique ID for USB serial number. Return number of bytes. Note max_len is typically 16
size_t board_get_unique_id(uint8_t id[], size_t max_len);
// Get characters from UART. Return number of read bytes
int board_uart_read(uint8_t *buf, int len);
// Send characters to UART. Return number of sent bytes
int board_uart_write(void const *buf, int len);
//--------------------------------------------------------------------+
// Helper functions
//--------------------------------------------------------------------+
static inline void board_led_on(void) {
board_led_write(true);
}
static inline void board_led_off(void) {
board_led_write(false);
}
// Get USB Serial number string from unique ID if available. Return number of character.
// Input is string descriptor from index 1 (index 0 is type + len)
static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars) {
uint8_t uid[16] TU_ATTR_ALIGNED(4);
size_t uid_len;
// TODO work with make, but not working with esp32s3 cmake
uid_len = board_get_unique_id(uid, sizeof(uid));
if ( uid_len > max_chars / 2u ) {
uid_len = max_chars / 2u;
}
for ( size_t i = 0; i < uid_len; i++ ) {
for ( size_t j = 0; j < 2; j++ ) {
const unsigned char nibble_to_hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
const uint8_t nibble = (uint8_t) ((uid[i] >> (j * 4u)) & 0xfu);
desc_str1[i * 2 + (1 - j)] = nibble_to_hex[nibble]; // UTF-16-LE
}
}
return 2 * uid_len;
}
// TODO remove
static inline void board_delay(uint32_t ms) {
uint32_t start_ms = tusb_time_millis_api();
while ( tusb_time_millis_api() - start_ms < ms ) {
// take chance to run usb background
#if CFG_TUD_ENABLED
tud_task();
#endif
#if CFG_TUH_ENABLED
tuh_task();
#endif
}
}
// stdio getchar() is blocking, this is non-blocking version
int board_getchar(void);
void board_putchar(int c);
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.cmake
================================================
set(CMAKE_SYSTEM_CPU arm1176jzf-s CACHE INTERNAL "System Processor")
#set(SUFFIX "")
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
BCM_VERSION=2835
)
endfunction()
================================================
FILE: hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Raspberry Pi Zero
url: https://www.raspberrypi.org/products/raspberry-pi-zero/
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.mk
================================================
CPU_CORE = arm1176jzf-s
CFLAGS += -DBCM_VERSION=2835 \
-DCFG_TUSB_MCU=OPT_MCU_BCM2835
SUFFIX =
================================================
FILE: hw/bsp/broadcom_32bit/family.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
manufacturer: Raspberry Pi
*/
#include "bsp/board_api.h"
#include "board.h"
// Suppress warning caused by mcu driver
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
#include "broadcom/cpu.h"
#include "broadcom/gpio.h"
#include "broadcom/interrupts.h"
#include "broadcom/mmu.h"
#include "broadcom/caches.h"
#include "broadcom/vcmailbox.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
// LED
#define LED_PIN 18
#define LED_STATE_ON 1
// UART TX
#define UART_TX_PIN 14
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_IRQHandler(void) {
tud_int_handler(0);
}
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
void board_init(void) {
setup_mmu_flat_map();
init_caches();
// LED
gpio_set_function(LED_PIN, GPIO_FUNCTION_OUTPUT);
gpio_set_pull(LED_PIN, BP_PULL_NONE);
board_led_write(true);
// Uart
COMPLETE_MEMORY_READS;
AUX->ENABLES_b.UART_1 = true;
UART1->IER = 0;
UART1->CNTL = 0;
UART1->LCR_b.DATA_SIZE = UART1_LCR_DATA_SIZE_MODE_8BIT;
UART1->MCR = 0;
UART1->IER = 0;
uint32_t source_clock = vcmailbox_get_clock_rate_measured(VCMAILBOX_CLOCK_CORE);
UART1->BAUD = ((source_clock / (115200 * 8)) - 1);
UART1->CNTL |= UART1_CNTL_TX_ENABLE_Msk;
COMPLETE_MEMORY_READS;
gpio_set_function(UART_TX_PIN, GPIO_FUNCTION_ALT5);
// Turn on USB peripheral.
vcmailbox_set_power_state(VCMAILBOX_DEVICE_USB_HCD, true);
// Timer 1/1024 second tick
SYSTMR->CS_b.M1 = 1;
SYSTMR->C1 = SYSTMR->CLO + 977;
BP_EnableIRQ(TIMER_1_IRQn);
BP_SetPriority(USB_IRQn, 0x00);
BP_ClearPendingIRQ(USB_IRQn);
BP_EnableIRQ(USB_IRQn);
BP_EnableIRQs();
}
void board_led_write(bool state) {
gpio_set_value(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON));
}
uint32_t board_button_read(void) {
return 0;
}
int board_uart_read(uint8_t* buf, int len) {
(void) buf;
(void) len;
return 0;
}
int board_uart_write(void const* buf, int len) {
for (int i = 0; i < len; i++) {
const char* cbuf = buf;
while (!UART1->STAT_b.TX_READY) {}
if (cbuf[i] == '\n') {
UART1->IO = '\r';
while (!UART1->STAT_b.TX_READY) {}
}
UART1->IO = cbuf[i];
}
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void TIMER_1_IRQHandler(void) {
system_ticks++;
SYSTMR->C1 += 977;
SYSTMR->CS_b.M1 = 1;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
#endif
void HardFault_Handler(void) {
// asm("bkpt");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void) {
}
================================================
FILE: hw/bsp/broadcom_32bit/family.cmake
================================================
include_guard()
set(SDK_DIR ${TOP}/hw/mcu/broadcom)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS BCM2835 CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${SDK_DIR}/broadcom/link.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(STARTUP_FILE_GNU ${SDK_DIR}/broadcom/boot.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
#------------------------------------
# Startup & Linker script
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SDK_DIR}/broadcom/gen/interrupt_handlers.c
${SDK_DIR}/broadcom/gpio.c
${SDK_DIR}/broadcom/interrupts.c
${SDK_DIR}/broadcom/mmu.c
${SDK_DIR}/broadcom/caches.c
${SDK_DIR}/broadcom/vcmailbox.c
)
target_compile_options(${BOARD_TARGET} PUBLIC
-O0
-ffreestanding
-mgeneral-regs-only
-fno-exceptions
-std=c17
)
target_include_directories(${BOARD_TARGET} PUBLIC
${SDK_DIR}
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_BCM2835)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
"LINKER:--entry=_start"
--specs=nosys.specs
-nostartfiles
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
"LINKER:--entry=_start"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes")
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/broadcom_32bit/family.mk
================================================
MCU_DIR = hw/mcu/broadcom
include $(TOP)/$(BOARD_PATH)/board.mk
CFLAGS += \
-Wall \
-O0 \
-ffreestanding \
-nostdlib \
-nostartfiles \
-mgeneral-regs-only \
-fno-exceptions \
-std=c17
CROSS_COMPILE = arm-none-eabi-
# mcu driver cause following warnings
CFLAGS_GCC += -Wno-error=cast-qual -Wno-error=redundant-decls
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(MCU_DIR)/broadcom/gen/interrupt_handlers.c \
$(MCU_DIR)/broadcom/gpio.c \
$(MCU_DIR)/broadcom/interrupts.c \
$(MCU_DIR)/broadcom/mmu.c \
$(MCU_DIR)/broadcom/caches.c \
$(MCU_DIR)/broadcom/vcmailbox.c
LD_FILE = $(MCU_DIR)/broadcom/link$(SUFFIX).ld
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(MCU_DIR)
SRC_S += $(MCU_DIR)/broadcom/boot$(SUFFIX).s
$(BUILD)/kernel$(SUFFIX).img: $(BUILD)/$(PROJECT).elf
$(OBJCOPY) -O binary $^ $@
# Copy to kernel to netboot drive or SD card
# Change destinaation to fit your need
flash: $(BUILD)/kernel$(SUFFIX).img
@$(CP) $< /home/$(USER)/Documents/code/pi_tinyusb/boot_cpy
================================================
FILE: hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.cmake
================================================
set(CMAKE_SYSTEM_CPU cortex-a72 CACHE INTERNAL "System Processor")
set(BCM_VERSION 2711)
function(update_board TARGET)
endfunction()
================================================
FILE: hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Raspberry CM4
url: https://www.raspberrypi.org/products/compute-module-4
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.mk
================================================
CPU_CORE = cortex-a72
CFLAGS += -DBCM_VERSION=2711 \
-DCFG_TUSB_MCU=OPT_MCU_BCM2711
================================================
FILE: hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.cmake
================================================
set(CMAKE_SYSTEM_CPU cortex-a53 CACHE INTERNAL "System Processor")
set(BCM_VERSION 2837)
function(update_board TARGET)
endfunction()
================================================
FILE: hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Raspberry Zero2
url: https://www.raspberrypi.org/products/raspberry-pi-zero-2-w
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.mk
================================================
CPU_CORE = cortex-a53
CFLAGS += -DBCM_VERSION=2837 \
-DCFG_TUSB_MCU=OPT_MCU_BCM2837
================================================
FILE: hw/bsp/broadcom_64bit/family.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
manufacturer: Raspberry Pi
*/
#include "bsp/board_api.h"
#include "board.h"
// Suppress warning caused by mcu driver
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
#include "broadcom/cpu.h"
#include "broadcom/gpio.h"
#include "broadcom/interrupts.h"
#include "broadcom/mmu.h"
#include "broadcom/caches.h"
#include "broadcom/vcmailbox.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
// LED
#define LED_PIN 18
#define LED_STATE_ON 1
// UART TX
#define UART_TX_PIN 14
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_IRQHandler(void) {
tud_int_handler(0);
}
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
void board_init(void) {
setup_mmu_flat_map();
init_caches();
// LED
gpio_set_function(LED_PIN, GPIO_FUNCTION_OUTPUT);
gpio_set_pull(LED_PIN, BP_PULL_NONE);
board_led_write(true);
// Uart
COMPLETE_MEMORY_READS;
AUX->ENABLES_b.UART_1 = true;
UART1->IER = 0;
UART1->CNTL = 0;
UART1->LCR_b.DATA_SIZE = UART1_LCR_DATA_SIZE_MODE_8BIT;
UART1->MCR = 0;
UART1->IER = 0;
uint32_t source_clock = vcmailbox_get_clock_rate_measured(VCMAILBOX_CLOCK_CORE);
UART1->BAUD = ((source_clock / (115200 * 8)) - 1);
UART1->CNTL |= UART1_CNTL_TX_ENABLE_Msk;
COMPLETE_MEMORY_READS;
gpio_set_function(UART_TX_PIN, GPIO_FUNCTION_ALT5);
// Turn on USB peripheral.
vcmailbox_set_power_state(VCMAILBOX_DEVICE_USB_HCD, true);
// Timer 1/1024 second tick
SYSTMR->CS_b.M1 = 1;
SYSTMR->C1 = SYSTMR->CLO + 977;
BP_EnableIRQ(TIMER_1_IRQn);
BP_SetPriority(USB_IRQn, 0x00);
BP_ClearPendingIRQ(USB_IRQn);
BP_EnableIRQ(USB_IRQn);
BP_EnableIRQs();
}
void board_led_write(bool state) {
gpio_set_value(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON));
}
uint32_t board_button_read(void) {
return 0;
}
int board_uart_read(uint8_t* buf, int len) {
(void) buf;
(void) len;
return 0;
}
int board_uart_write(void const* buf, int len) {
for (int i = 0; i < len; i++) {
const char* cbuf = buf;
while (!UART1->STAT_b.TX_READY) {}
if (cbuf[i] == '\n') {
UART1->IO = '\r';
while (!UART1->STAT_b.TX_READY) {}
}
UART1->IO = cbuf[i];
}
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void TIMER_1_IRQHandler(void) {
system_ticks++;
SYSTMR->C1 += 977;
SYSTMR->CS_b.M1 = 1;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
#endif
void HardFault_Handler(void) {
// asm("bkpt");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void) {
}
================================================
FILE: hw/bsp/broadcom_64bit/family.cmake
================================================
include_guard()
set(SDK_DIR ${TOP}/hw/mcu/broadcom)
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/aarch64_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS BCM2711 BCM2835 CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${SDK_DIR}/broadcom/link8.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
set(STARTUP_FILE_GNU ${SDK_DIR}/broadcom/boot8.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
#------------------------------------
# Board Target
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SDK_DIR}/broadcom/gen/interrupt_handlers.c
${SDK_DIR}/broadcom/gpio.c
${SDK_DIR}/broadcom/interrupts.c
${SDK_DIR}/broadcom/mmu.c
${SDK_DIR}/broadcom/caches.c
${SDK_DIR}/broadcom/vcmailbox.c
)
target_compile_options(${BOARD_TARGET} PUBLIC
-O0
-ffreestanding
-mgeneral-regs-only
-fno-exceptions
-std=c17
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
BCM_VERSION=${BCM_VERSION}
)
target_include_directories(${BOARD_TARGET} PUBLIC
${SDK_DIR}
${CMSIS_5}/CMSIS/Core_A/Include
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_BCM${BCM_VERSION})
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
"LINKER:--entry=_start"
--specs=nosys.specs
-nostartfiles
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
"LINKER:--entry=_start"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes")
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/broadcom_64bit/family.mk
================================================
MCU_DIR = hw/mcu/broadcom
include $(TOP)/$(BOARD_PATH)/board.mk
CFLAGS += \
-Wall \
-O0 \
-ffreestanding \
-nostdlib \
-nostartfiles \
--specs=nosys.specs \
-mgeneral-regs-only \
-std=c17
CROSS_COMPILE = aarch64-none-elf-
# mcu driver cause following warnings
CFLAGS_GCC += -Wno-error=cast-qual -Wno-error=redundant-decls
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
$(MCU_DIR)/broadcom/gen/interrupt_handlers.c \
$(MCU_DIR)/broadcom/gpio.c \
$(MCU_DIR)/broadcom/interrupts.c \
$(MCU_DIR)/broadcom/mmu.c \
$(MCU_DIR)/broadcom/caches.c \
$(MCU_DIR)/broadcom/vcmailbox.c
LD_FILE = $(MCU_DIR)/broadcom/link8.ld
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(MCU_DIR) \
$(TOP)/lib/CMSIS_5/CMSIS/Core_A/Include
SRC_S += $(MCU_DIR)/broadcom/boot8.s
$(BUILD)/kernel8.img: $(BUILD)/$(PROJECT).elf
$(OBJCOPY) -O binary $^ $@
# Copy to kernel to netboot drive or SD card
# Change destinaation to fit your need
flash: $(BUILD)/kernel8.img
@$(CP) $< /home/$(USER)/Documents/code/pi_tinyusb/boot_cpy
================================================
FILE: hw/bsp/ch32f20x/boards/ch32f205r-r0/board.cmake
================================================
set(MCU_VARIANT D8C)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
CH32F20x_D8C
)
endfunction()
================================================
FILE: hw/bsp/ch32f20x/boards/ch32f205r-r0/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2023, Denis Krasutski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* metadata:
name: CH32F205r-r0
url: https://github.com/openwch/ch32f20x
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
// LED: need to wire pin LED1 to PC0 in the P1 header
#define LED_PORT GPIOC
#define LED_PIN GPIO_Pin_1
#define LED_STATE_ON 0
#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE)
// Button: need to wire pin KEY to PC1 in the P1 header
#define BUTTON_PORT GPIOC
#define BUTTON_PIN GPIO_Pin_0
#define BUTTON_STATE_ACTIVE 0
#define BUTTON_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE)
// UART
#define UART_DEV USART2
#define UART_DEV_IRQn USART2_IRQn
#define UART_DEV_IRQHandler USART2_IRQHandler
#define UART_DEV_GPIO_PORT GPIOA
#define UART_DEV_TX_PIN GPIO_Pin_2
#define UART_DEV_CLK_EN() do { \
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); \
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); \
} while(0)
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/ch32f20x/boards/ch32f205r-r0/board.mk
================================================
LD_FILE = $(FAMILY_PATH)/ch32f205.ld
SRC_S += \
$(FAMILY_PATH)/startup_gcc_ch32f20x_d8c.s
CFLAGS += \
-DCH32F20x_D8C
================================================
FILE: hw/bsp/ch32f20x/ch32f205.ld
================================================
ENTRY(Reset_Handler)
_Min_Heap_Size = 0x200;
_Min_Stack_Size = 0x400;
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
}
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
.text :
{
. = ALIGN(4);
_stext = .;
*(.text)
*(.text*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .;
} >FLASH
.rodata :
{
. = ALIGN(4);
*(.rodata)
*(.rodata*)
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
_sidata = LOADADDR(.data);
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} >RAM AT> FLASH
. = ALIGN(4);
.bss :
{
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
} >RAM
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
__HeapStart = .;
. = . + _Min_Heap_Size;
__HeapEnd = .;
__StackLimit = .;
. = . + _Min_Stack_Size;
__StackTop = .;
. = ALIGN(4);
} >RAM
_estack = __StackTop;
_sstack = __StackLimit;
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
================================================
FILE: hw/bsp/ch32f20x/ch32f20x_conf.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32f20x_conf.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Library configuration file.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32F20x_CONF_H
#define __CH32F20x_CONF_H
#include "ch32f20x_adc.h"
#include "ch32f20x_bkp.h"
#include "ch32f20x_can.h"
#include "ch32f20x_crc.h"
#include "ch32f20x_dac.h"
#include "ch32f20x_dbgmcu.h"
#include "ch32f20x_dma.h"
#include "ch32f20x_exti.h"
#include "ch32f20x_flash.h"
#include "ch32f20x_fsmc.h"
#include "ch32f20x_gpio.h"
#include "ch32f20x_i2c.h"
#include "ch32f20x_iwdg.h"
#include "ch32f20x_pwr.h"
#include "ch32f20x_rcc.h"
#include "ch32f20x_rtc.h"
#include "ch32f20x_sdio.h"
#include "ch32f20x_spi.h"
#include "ch32f20x_tim.h"
#include "ch32f20x_usart.h"
#include "ch32f20x_wwdg.h"
#include "ch32f20x_it.h"
#include "ch32f20x_misc.h"
#endif /* __CH32F20x_CONF_H */
================================================
FILE: hw/bsp/ch32f20x/ch32f20x_it.c
================================================
#include "ch32f20x_it.h"
#include "ch32f20x.h"
/* -------------------------------------------------------------------------- */
void NMI_Handler(void) {
}
/* -------------------------------------------------------------------------- */
void MemManage_Handler(void) {
}
/* -------------------------------------------------------------------------- */
void BusFault_Handler(void) {
}
/* -------------------------------------------------------------------------- */
void UsageFault_Handler(void) {
}
/* -------------------------------------------------------------------------- */
void DebugMon_Handler(void) {
}
/* -------------------------------------------------------------------------- */
================================================
FILE: hw/bsp/ch32f20x/ch32f20x_it.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32f20x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains the headers of the interrupt handlers.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32F20xIT_H
#define __CH32F20xIT_H
#include "ch32f20x.h"
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void DebugMon_Handler(void);
void USBHS_IRQHandler(void);
void SysTick_Handler(void);
#endif /* __CH32F20xIT_H */
================================================
FILE: hw/bsp/ch32f20x/core_cm3.h
================================================
/* There is core_cm3.h wrapper just to avoid warnings from CMSIS headers */
/* if you want use original file add to make file:
INC += \
$(TOP)/$(CH32F20X_SDK_SRC)/CMSIS
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include <../../CMSIS/core_cm3.h>
#pragma GCC diagnostic pop
================================================
FILE: hw/bsp/ch32f20x/debug_uart.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Denis Krasutski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include
#include "board.h"
#include "debug_uart.h"
#define UART_RINGBUFFER_SIZE_TX 64
#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)
static char tx_buf[UART_RINGBUFFER_SIZE_TX];
static unsigned int tx_produce = 0;
static volatile unsigned int tx_consume = 0;
void UART_DEV_IRQHandler(void)
{
if(USART_GetITStatus(UART_DEV, USART_IT_TC) != RESET) {
USART_ClearITPendingBit(UART_DEV, USART_IT_TC);
if(tx_consume != tx_produce) {
USART_SendData(UART_DEV, tx_buf[tx_consume]);
tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX;
}
}
}
void uart_write(char c)
{
unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX;
NVIC_DisableIRQ(UART_DEV_IRQn);
if((tx_consume != tx_produce) || (USART_GetFlagStatus(UART_DEV, USART_FLAG_TXE) == RESET)) {
tx_buf[tx_produce] = c;
tx_produce = tx_produce_next;
} else {
USART_SendData(UART_DEV, c);
}
NVIC_EnableIRQ(UART_DEV_IRQn);
}
void uart_sync(void)
{
while(tx_consume != tx_produce) {
//Waiting for transfer complete
}
}
void usart_printf_init(uint32_t baudrate)
{
tx_produce = 0;
tx_consume = 0;
UART_DEV_CLK_EN();
GPIO_InitTypeDef gpio_config = {
.GPIO_Pin = UART_DEV_TX_PIN,
.GPIO_Speed = GPIO_Speed_50MHz,
.GPIO_Mode = GPIO_Mode_AF_PP,
};
GPIO_Init(UART_DEV_GPIO_PORT, &gpio_config);
USART_InitTypeDef uart_config = {
.USART_BaudRate = baudrate,
.USART_WordLength = USART_WordLength_8b,
.USART_StopBits = USART_StopBits_1,
.USART_Parity = USART_Parity_No,
.USART_HardwareFlowControl = USART_HardwareFlowControl_None,
.USART_Mode = USART_Mode_Tx,
};
USART_Init(UART_DEV, &uart_config);
USART_ITConfig(UART_DEV, USART_IT_TC, ENABLE);
USART_Cmd(UART_DEV, ENABLE);
NVIC_InitTypeDef nvic_config = {
.NVIC_IRQChannel = UART_DEV_IRQn,
.NVIC_IRQChannelPreemptionPriority = 1,
.NVIC_IRQChannelSubPriority = 3,
.NVIC_IRQChannelCmd = ENABLE,
};
NVIC_Init(&nvic_config);
}
================================================
FILE: hw/bsp/ch32f20x/debug_uart.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Denis Krasutski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include
void uart_write(char c);
void uart_sync(void);
void usart_printf_init(uint32_t baudrate);
================================================
FILE: hw/bsp/ch32f20x/family.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Denis Krasutski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
manufacturer: WCH
*/
#include "stdio.h"
#include "debug_uart.h"
#include "ch32f20x.h"
#include "ch32f20x_it.h"
#include "bsp/board_api.h"
#include "board.h"
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USBHS_IRQHandler(void)
{
tud_int_handler(0);
}
void board_init(void) {
/* Disable interrupts during init */
__disable_irq();
#if CFG_TUSB_OS == OPT_OS_NONE
SysTick_Config(SystemCoreClock / 1000);
#endif
#if CFG_TUSB_OS == OPT_OS_FREERTOS
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
NVIC_SetPriority(USBHS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
#endif
usart_printf_init(115200);
// USB HS Clock config
RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY);
RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE);
RCC_USBHSConfig(RCC_USBPLL_Div2);
RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M);
RCC_USBHSPHYPLLALIVEcmd(ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
// LED
LED_CLOCK_EN();
GPIO_InitTypeDef led_pin_config = {
.GPIO_Pin = LED_PIN,
.GPIO_Mode = GPIO_Mode_Out_OD,
.GPIO_Speed = GPIO_Speed_50MHz,
};
GPIO_Init(LED_PORT, &led_pin_config);
// Button
BUTTON_CLOCK_EN();
GPIO_InitTypeDef button_pin_config = {
.GPIO_Pin = BUTTON_PIN,
.GPIO_Mode = GPIO_Mode_IPU,
.GPIO_Speed = GPIO_Speed_50MHz,
};
GPIO_Init(BUTTON_PORT, &button_pin_config);
/* Enable interrupts globally */
__enable_irq();
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void)
{
system_ticks++;
}
uint32_t tusb_time_millis_api(void)
{
return system_ticks;
}
#endif
void HardFault_Handler(void)
{
__asm("BKPT #0\n");
}
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
void board_led_write(bool state)
{
GPIO_WriteBit(LED_PORT, LED_PIN, state);
}
uint32_t board_button_read(void)
{
return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN);
}
int board_uart_read(uint8_t *buf, int len)
{
(void) buf;
(void) len;
return 0;
}
int board_uart_write(void const *buf, int len)
{
int txsize = len;
while ( txsize-- )
{
uart_write(*(uint8_t const*) buf);
buf++;
}
return len;
}
================================================
FILE: hw/bsp/ch32f20x/family.cmake
================================================
include_guard()
set(CH32_FAMILY ch32f20x)
set(SDK_DIR ${TOP}/hw/mcu/wch/${CH32_FAMILY})
set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m3 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS CH32F20X CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/ch32f205.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
if (NOT DEFINED STARTUP_FILE_GNU)
set(STARTUP_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/startup_gcc_ch32f20x_d8c.s)
endif ()
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
#------------------------------------
# Board Target
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SDK_SRC_DIR}/StdPeriphDriver/src/${CH32_FAMILY}_gpio.c
${SDK_SRC_DIR}/StdPeriphDriver/src/${CH32_FAMILY}_misc.c
${SDK_SRC_DIR}/StdPeriphDriver/src/${CH32_FAMILY}_rcc.c
${SDK_SRC_DIR}/StdPeriphDriver/src/${CH32_FAMILY}_usart.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${SDK_SRC_DIR}/StdPeriphDriver/inc
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_CH32F20X)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/wch/dcd_ch32_usbhs.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes")
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_stlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/ch32f20x/family.mk
================================================
# Submodules
CH32F20X_SDK = hw/mcu/wch/ch32f20x
# WCH-SDK paths
CH32F20X_SDK_SRC = $(CH32F20X_SDK)/EVT/EXAM/SRC
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m3
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_CH32F20X \
-DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
SRC_C += \
src/portable/wch/dcd_ch32_usbhs.c \
$(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_gpio.c \
$(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_misc.c \
$(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_rcc.c \
$(CH32F20X_SDK_SRC)/StdPeriphDriver/src/ch32f20x_usart.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(CH32F20X_SDK_SRC)/StdPeriphDriver/inc
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM3
flash: flash-stlink
================================================
FILE: hw/bsp/ch32f20x/startup_gcc_ch32f20x_d8c.s
================================================
/**
******************************************************************************
* @file startup_gcc_ch32f20x_d8c.s
* @author Denis Krasutski
* @brief CH32F205 Devices vector table
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M3 processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
*/
.syntax unified
.cpu cortex-m3
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section. defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* set stack pointer */
ldr sp, =_estack
/* Call the clock system initialization function.*/
bl SystemInit
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero fill the bss segment. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/*******************************************************************************
External Interrupts
*******************************************************************************/
.word WWDG_IRQHandler
.word PVD_IRQHandler
.word TAMPER_IRQHandler
.word RTC_IRQHandler
.word FLASH_IRQHandler
.word RCC_IRQHandler
.word EXTI0_IRQHandler
.word EXTI1_IRQHandler
.word EXTI2_IRQHandler
.word EXTI3_IRQHandler
.word EXTI4_IRQHandler
.word DMA1_Channel1_IRQHandler
.word DMA1_Channel2_IRQHandler
.word DMA1_Channel3_IRQHandler
.word DMA1_Channel4_IRQHandler
.word DMA1_Channel5_IRQHandler
.word DMA1_Channel6_IRQHandler
.word DMA1_Channel7_IRQHandler
.word ADC1_2_IRQHandler
.word USB_HP_CAN1_TX_IRQHandler
.word USB_LP_CAN1_RX0_IRQHandler
.word CAN1_RX1_IRQHandler
.word CAN1_SCE_IRQHandler
.word EXTI9_5_IRQHandler
.word TIM1_BRK_IRQHandler
.word TIM1_UP_IRQHandler
.word TIM1_TRG_COM_IRQHandler
.word TIM1_CC_IRQHandler
.word TIM2_IRQHandler
.word TIM3_IRQHandler
.word TIM4_IRQHandler
.word I2C1_EV_IRQHandler
.word I2C1_ER_IRQHandler
.word I2C2_EV_IRQHandler
.word I2C2_ER_IRQHandler
.word SPI1_IRQHandler
.word SPI2_IRQHandler
.word USART1_IRQHandler
.word USART2_IRQHandler
.word USART3_IRQHandler
.word EXTI15_10_IRQHandler
.word RTCAlarm_IRQHandler
.word 0
.word TIM8_BRK_IRQHandler
.word TIM8_UP_IRQHandler
.word TIM8_TRG_COM_IRQHandler
.word TIM8_CC_IRQHandler
.word RNG_IRQHandler
.word FSMC_IRQHandler
.word SDIO_IRQHandler
.word TIM5_IRQHandler
.word SPI3_IRQHandler
.word UART4_IRQHandler
.word UART5_IRQHandler
.word TIM6_IRQHandler
.word TIM7_IRQHandler
.word DMA2_Channel1_IRQHandler
.word DMA2_Channel2_IRQHandler
.word DMA2_Channel3_IRQHandler
.word DMA2_Channel4_IRQHandler
.word DMA2_Channel5_IRQHandler
.word ETH_IRQHandler
.word ETH_WKUP_IRQHandler
.word CAN2_TX_IRQHandler
.word CAN2_RX0_IRQHandler
.word CAN2_RX1_IRQHandler
.word CAN2_SCE_IRQHandler
.word OTG_FS_IRQHandler
.word USBHSWakeup_IRQHandler
.word USBHS_IRQHandler
.word DVP_IRQHandler
.word UART6_IRQHandler
.word UART7_IRQHandler
.word UART8_IRQHandler
.word TIM9_BRK_IRQHandler
.word TIM9_UP_IRQHandler
.word TIM9_TRG_COM_IRQHandler
.word TIM9_CC_IRQHandler
.word TIM10_BRK_IRQHandler
.word TIM10_UP_IRQHandler
.word TIM10_TRG_COM_IRQHandler
.word TIM10_CC_IRQHandler
.word DMA2_Channel6_IRQHandler
.word DMA2_Channel7_IRQHandler
.word DMA2_Channel8_IRQHandler
.word DMA2_Channel9_IRQHandler
.word DMA2_Channel10_IRQHandler
.word DMA2_Channel11_IRQHandler
/*******************************************************************************
*
* Provide weak aliases
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_IRQHandler
.thumb_set PVD_IRQHandler,Default_Handler
.weak TAMPER_IRQHandler
.thumb_set TAMPER_IRQHandler,Default_Handler
.weak RTC_IRQHandler
.thumb_set RTC_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Channel1_IRQHandler
.thumb_set DMA1_Channel1_IRQHandler,Default_Handler
.weak DMA1_Channel2_IRQHandler
.thumb_set DMA1_Channel2_IRQHandler,Default_Handler
.weak DMA1_Channel3_IRQHandler
.thumb_set DMA1_Channel3_IRQHandler,Default_Handler
.weak DMA1_Channel4_IRQHandler
.thumb_set DMA1_Channel4_IRQHandler,Default_Handler
.weak DMA1_Channel5_IRQHandler
.thumb_set DMA1_Channel5_IRQHandler,Default_Handler
.weak DMA1_Channel6_IRQHandler
.thumb_set DMA1_Channel6_IRQHandler,Default_Handler
.weak DMA1_Channel7_IRQHandler
.thumb_set DMA1_Channel7_IRQHandler,Default_Handler
.weak ADC1_2_IRQHandler
.thumb_set ADC1_2_IRQHandler,Default_Handler
.weak USB_HP_CAN1_TX_IRQHandler
.thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler
.weak USB_LP_CAN1_RX0_IRQHandler
.thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler
.weak CAN1_RX1_IRQHandler
.thumb_set CAN1_RX1_IRQHandler,Default_Handler
.weak CAN1_SCE_IRQHandler
.thumb_set CAN1_SCE_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_IRQHandler
.thumb_set TIM1_BRK_IRQHandler,Default_Handler
.weak TIM1_UP_IRQHandler
.thumb_set TIM1_UP_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_IRQHandler
.thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTCAlarm_IRQHandler
.thumb_set RTCAlarm_IRQHandler,Default_Handler
.weak TIM8_BRK_IRQHandler
.thumb_set TIM8_BRK_IRQHandler,Default_Handler
.weak TIM8_UP_IRQHandler
.thumb_set TIM8_UP_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_IRQHandler
.thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak RNG_IRQHandler
.thumb_set RNG_IRQHandler,Default_Handler
.weak FSMC_IRQHandler
.thumb_set FSMC_IRQHandler,Default_Handler
.weak SDIO_IRQHandler
.thumb_set SDIO_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak TIM6_IRQHandler
.thumb_set TIM6_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Channel1_IRQHandler
.thumb_set DMA2_Channel1_IRQHandler,Default_Handler
.weak DMA2_Channel2_IRQHandler
.thumb_set DMA2_Channel2_IRQHandler,Default_Handler
.weak DMA2_Channel3_IRQHandler
.thumb_set DMA2_Channel3_IRQHandler,Default_Handler
.weak DMA2_Channel4_IRQHandler
.thumb_set DMA2_Channel4_IRQHandler,Default_Handler
.weak DMA2_Channel5_IRQHandler
.thumb_set DMA2_Channel5_IRQHandler,Default_Handler
.weak ETH_IRQHandler
.thumb_set ETH_IRQHandler,Default_Handler
.weak ETH_WKUP_IRQHandler
.thumb_set ETH_WKUP_IRQHandler,Default_Handler
.weak CAN2_TX_IRQHandler
.thumb_set CAN2_TX_IRQHandler,Default_Handler
.weak CAN2_RX0_IRQHandler
.thumb_set CAN2_RX0_IRQHandler,Default_Handler
.weak CAN2_RX1_IRQHandler
.thumb_set CAN2_RX1_IRQHandler,Default_Handler
.weak CAN2_SCE_IRQHandler
.thumb_set CAN2_SCE_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak USBHSWakeup_IRQHandler
.thumb_set USBHSWakeup_IRQHandler,Default_Handler
.weak USBHS_IRQHandler
.thumb_set USBHS_IRQHandler,Default_Handler
.weak DVP_IRQHandler
.thumb_set DVP_IRQHandler,Default_Handler
.weak UART6_IRQHandler
.thumb_set UART6_IRQHandler,Default_Handler
.weak UART7_IRQHandler
.thumb_set UART7_IRQHandler,Default_Handler
.weak UART8_IRQHandler
.thumb_set UART8_IRQHandler,Default_Handler
.weak TIM9_BRK_IRQHandler
.thumb_set TIM9_BRK_IRQHandler,Default_Handler
.weak TIM9_UP_IRQHandler
.thumb_set TIM9_UP_IRQHandler,Default_Handler
.weak TIM9_TRG_COM_IRQHandler
.thumb_set TIM9_TRG_COM_IRQHandler,Default_Handler
.weak TIM9_CC_IRQHandler
.thumb_set TIM9_CC_IRQHandler,Default_Handler
.weak TIM10_BRK_IRQHandler
.thumb_set TIM10_BRK_IRQHandler,Default_Handler
.weak TIM10_UP_IRQHandler
.thumb_set TIM10_UP_IRQHandler,Default_Handler
.weak TIM10_TRG_COM_IRQHandler
.thumb_set TIM10_TRG_COM_IRQHandler,Default_Handler
.weak TIM10_CC_IRQHandler
.thumb_set TIM10_CC_IRQHandler,Default_Handler
.weak DMA2_Channel6_IRQHandler
.thumb_set DMA2_Channel6_IRQHandler,Default_Handler
.weak DMA2_Channel7_IRQHandler
.thumb_set DMA2_Channel7_IRQHandler,Default_Handler
.weak DMA2_Channel8_IRQHandler
.thumb_set DMA2_Channel8_IRQHandler,Default_Handler
.weak DMA2_Channel9_IRQHandler
.thumb_set DMA2_Channel9_IRQHandler,Default_Handler
.weak DMA2_Channel10_IRQHandler
.thumb_set DMA2_Channel10_IRQHandler,Default_Handler
.weak DMA2_Channel11_IRQHandler
.thumb_set DMA2_Channel11_IRQHandler,Default_Handler
================================================
FILE: hw/bsp/ch32f20x/system_ch32f20x.c
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32f20x.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : CH32F20x Device Peripheral Access Layer System Source File.
* For CH32F208 HSE = 32Mhz
* For others HSE = 8Mhz
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "ch32f20x.h"
/*
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
* reset the HSI is used as SYSCLK source).
* If none of the define below is enabled, the HSI is used as System clock source.
*/
//#define SYSCLK_FREQ_HSE HSE_VALUE
//#define SYSCLK_FREQ_48MHz_HSE 48000000
//#define SYSCLK_FREQ_56MHz_HSE 56000000
//#define SYSCLK_FREQ_72MHz_HSE 72000000
#define SYSCLK_FREQ_96MHz_HSE 96000000
//#define SYSCLK_FREQ_120MHz_HSE 120000000
//#define SYSCLK_FREQ_144MHz_HSE 144000000
//#define SYSCLK_FREQ_HSI HSI_VALUE
//#define SYSCLK_FREQ_48MHz_HSI 48000000
//#define SYSCLK_FREQ_56MHz_HSI 56000000
//#define SYSCLK_FREQ_72MHz_HSI 72000000
//#define SYSCLK_FREQ_96MHz_HSI 96000000
//#define SYSCLK_FREQ_120MHz_HSI 120000000
//#define SYSCLK_FREQ_144MHz_HSI 144000000
/* Uncomment the following line if you need to relocate your vector Table in Internal SRAM */
/* #define VECT_TAB_SRAM */
/* Vector Table base offset field This value must be a multiple of 0x200 */
#define VECT_TAB_OFFSET 0x0
/* Clock Definitions */
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSI; /* System Clock Frequency (Core Clock) */
#else
uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
#endif
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/* system_private_function_proto_types */
static void SetSysClock( void );
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSE
static void SetSysClockTo48_HSE( void );
#elif defined SYSCLK_FREQ_56MHz_HSE
static void SetSysClockTo56_HSE( void );
#elif defined SYSCLK_FREQ_72MHz_HSE
static void SetSysClockTo72_HSE( void );
#elif defined SYSCLK_FREQ_96MHz_HSE
static void SetSysClockTo96_HSE( void );
#elif defined SYSCLK_FREQ_120MHz_HSE
static void SetSysClockTo120_HSE( void );
#elif defined SYSCLK_FREQ_144MHz_HSE
static void SetSysClockTo144_HSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSI
static void SetSysClockTo48_HSI( void );
#elif defined SYSCLK_FREQ_56MHz_HSI
static void SetSysClockTo56_HSI( void );
#elif defined SYSCLK_FREQ_72MHz_HSI
static void SetSysClockTo72_HSI( void );
#elif defined SYSCLK_FREQ_96MHz_HSI
static void SetSysClockTo96_HSI( void );
#elif defined SYSCLK_FREQ_120MHz_HSI
static void SetSysClockTo120_HSI( void );
#elif defined SYSCLK_FREQ_144MHz_HSI
static void SetSysClockTo144_HSI( void );
#endif
/*********************************************************************
* @fn SystemInit
*
* @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
* the PLL and update the SystemCoreClock variable.
*
* @return none
*/
void SystemInit( void )
{
RCC->CTLR |= ( uint32_t )0x00000001;
#ifdef CH32F20x_D8C
RCC->CFGR0 &= ( uint32_t )0xF8FF0000;
#else
RCC->CFGR0 &= ( uint32_t )0xF0FF0000;
#endif
RCC->CTLR &= ( uint32_t )0xFEF6FFFF;
RCC->CTLR &= ( uint32_t )0xFFFBFFFF;
RCC->CFGR0 &= ( uint32_t )0xFF80FFFF;
#ifdef CH32F20x_D8C
RCC->CTLR &= ( uint32_t )0xEBFFFFFF;
RCC->INTR = 0x00FF0000;
RCC->CFGR2 = 0x00000000;
#else
RCC->INTR = 0x009F0000;
#endif
SetSysClock();
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
/*********************************************************************
* @fn SystemCoreClockUpdate
*
* @brief Update SystemCoreClock variable according to Clock Register Values.
*
* @return none
*/
void SystemCoreClockUpdate( void )
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0;
uint8_t Pll_6_5 = 0;
#if defined (CH32F20x_D8C)
uint8_t Pll2mull = 0;
#endif
tmp = RCC->CFGR0 & RCC_SWS;
switch( tmp )
{
case 0x00:
SystemCoreClock = HSI_VALUE;
break;
case 0x04:
SystemCoreClock = HSE_VALUE;
break;
case 0x08:
pllmull = RCC->CFGR0 & RCC_PLLMULL;
pllsource = RCC->CFGR0 & RCC_PLLSRC;
pllmull = ( pllmull >> 18 ) + 2;
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
if( pllmull == 17 )
{
pllmull = 18;
}
#else
if( pllmull == 2 )
{
pllmull = 18;
}
if( pllmull == 15 )
{
pllmull = 13; /* *6.5 */
Pll_6_5 = 1;
}
if( pllmull == 16 )
{
pllmull = 15;
}
if( pllmull == 17 )
{
pllmull = 16;
}
#endif
if( pllsource == 0x00 )
{
if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE) SystemCoreClock = HSI_VALUE * pllmull;
else SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
else
{
#if defined (CH32F20x_D8C)
if(RCC->CFGR2 & (1<<16)){ /* PLL2 */
SystemCoreClock = HSE_VALUE/(((RCC->CFGR2 & 0xF0)>>4) + 1); /* PREDIV2 */
Pll2mull = (uint8_t)((RCC->CFGR2 & 0xF00)>>8);
if(Pll2mull == 0) SystemCoreClock = (SystemCoreClock * 5)>>1;
else if(Pll2mull == 1) SystemCoreClock = (SystemCoreClock * 25)>>1;
else if(Pll2mull == 15) SystemCoreClock = SystemCoreClock * 20;
else SystemCoreClock = SystemCoreClock * (Pll2mull + 2);
SystemCoreClock = SystemCoreClock/((RCC->CFGR2 & 0xF) + 1); /* PREDIV1 */
}
else{/* HSE */
SystemCoreClock = HSE_VALUE/((RCC->CFGR2 & 0xF) + 1); /* PREDIV1 */
}
SystemCoreClock = SystemCoreClock * pllmull;
#else
#if defined (CH32F20x_D8W)
if((RCC->CFGR0 & (3<<22)) == (3<<22))
{
SystemCoreClock = ((HSE_VALUE>>1)) * pllmull;
}
else
#endif
if( ( RCC->CFGR0 & RCC_PLLXTPRE ) != ( uint32_t )RESET )
{
#ifdef CH32F20x_D8W
SystemCoreClock = ( ( HSE_VALUE >> 2 ) >> 1 ) * pllmull;
#else
SystemCoreClock = ( HSE_VALUE >> 1 ) * pllmull;
#endif
}
else
{
#ifdef CH32F20x_D8W
SystemCoreClock = ( HSE_VALUE >> 2 ) * pllmull;
#else
SystemCoreClock = HSE_VALUE * pllmull;
#endif
}
#endif
}
if( Pll_6_5 == 1 ) SystemCoreClock = ( SystemCoreClock / 2 );
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
tmp = AHBPrescTable[( ( RCC->CFGR0 & RCC_HPRE ) >> 4 )];
SystemCoreClock >>= tmp;
}
/*********************************************************************
* @fn SetSysClock
*
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClock( void )
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_48MHz_HSE
SetSysClockTo48_HSE();
#elif defined SYSCLK_FREQ_56MHz_HSE
SetSysClockTo56_HSE();
#elif defined SYSCLK_FREQ_72MHz_HSE
SetSysClockTo72_HSE();
#elif defined SYSCLK_FREQ_96MHz_HSE
SetSysClockTo96_HSE();
#elif defined SYSCLK_FREQ_120MHz_HSE
SetSysClockTo120_HSE();
#elif defined SYSCLK_FREQ_144MHz_HSE
SetSysClockTo144_HSE();
#elif defined SYSCLK_FREQ_48MHz_HSI
SetSysClockTo48_HSI();
#elif defined SYSCLK_FREQ_56MHz_HSI
SetSysClockTo56_HSI();
#elif defined SYSCLK_FREQ_72MHz_HSI
SetSysClockTo72_HSI();
#elif defined SYSCLK_FREQ_96MHz_HSI
SetSysClockTo96_HSI();
#elif defined SYSCLK_FREQ_120MHz_HSI
SetSysClockTo120_HSI();
#elif defined SYSCLK_FREQ_144MHz_HSI
SetSysClockTo144_HSI();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
* source (default after reset)
*/
}
#ifdef SYSCLK_FREQ_HSE
/*********************************************************************
* @fn SetSysClockToHSE
*
* @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockToHSE( void )
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
}
while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
{
HSEStatus = ( uint32_t )0x01;
}
else
{
HSEStatus = ( uint32_t )0x00;
}
if( HSEStatus == ( uint32_t )0x01 )
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV1;
/* Select HSE as system clock source
* CH32F20x_D6 (HSE=8Mhz)
* CH32F20x_D8 (HSE=8Mhz)
* CH32F20x_D8W (HSE=32Mhz)
*/
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_HSE;
/* Wait till HSE is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x04 )
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSE
/*********************************************************************
* @fn SetSysClockTo48_HSE
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSE( void )
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
}
while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
{
HSEStatus = ( uint32_t )0x01;
}
else
{
HSEStatus = ( uint32_t )0x00;
}
if( HSEStatus == ( uint32_t )0x01 )
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz(HSE=32Mhz)
*/
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_56MHz_HSE
/*********************************************************************
* @fn SetSysClockTo56_HSE
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSE( void )
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
}
while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
{
HSEStatus = ( uint32_t )0x01;
}
else
{
HSEStatus = ( uint32_t )0x00;
}
if( HSEStatus == ( uint32_t )0x01 )
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz(HSE=32Mhz)
*/
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_72MHz_HSE
/*********************************************************************
* @fn SetSysClockTo72_HSE
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSE( void )
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
}
while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
{
HSEStatus = ( uint32_t )0x01;
}
else
{
HSEStatus = ( uint32_t )0x00;
}
if( HSEStatus == ( uint32_t )0x01 )
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz(HSE=32Mhz)
*/
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_96MHz_HSE
/*********************************************************************
* @fn SetSysClockTo96_HSE
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_HSE( void )
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
}
while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
{
HSEStatus = ( uint32_t )0x01;
}
else
{
HSEStatus = ( uint32_t )0x00;
}
if( HSEStatus == ( uint32_t )0x01 )
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz(HSE=32Mhz)
*/
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_120MHz_HSE
/*********************************************************************
* @fn SetSysClockTo120_HSE
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
#if defined (CH32F20x_D8W)
RCC->CFGR0 |= (uint32_t)(3<<22);
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
#else
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
#endif
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz(HSE=32Mhz)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_144MHz_HSE
/*********************************************************************
* @fn SetSysClockTo144_HSE
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_HSE( void )
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ( ( uint32_t )RCC_HSEON );
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
}
while( ( HSEStatus == 0 ) && ( StartUpCounter != HSE_STARTUP_TIMEOUT ) );
if( ( RCC->CTLR & RCC_HSERDY ) != RESET )
{
HSEStatus = ( uint32_t )0x01;
}
else
{
HSEStatus = ( uint32_t )0x00;
}
if( HSEStatus == ( uint32_t )0x01 )
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz(HSE=32Mhz)
*/
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSI
/*********************************************************************
* @fn SetSysClockTo48_HSI
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSI( void )
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
#elif defined SYSCLK_FREQ_56MHz_HSI
/*********************************************************************
* @fn SetSysClockTo56_HSI
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSI( void )
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 7 = 56 MHz */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
#elif defined SYSCLK_FREQ_72MHz_HSI
/*********************************************************************
* @fn SetSysClockTo72_HSI
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSI( void )
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
#elif defined SYSCLK_FREQ_96MHz_HSI
/*********************************************************************
* @fn SetSysClockTo96_HSI
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_HSI( void )
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 12 = 96 MHz */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
#elif defined SYSCLK_FREQ_120MHz_HSI
/*********************************************************************
* @fn SetSysClockTo120_HSI
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 15 = 120 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_144MHz_HSI
/*********************************************************************
* @fn SetSysClockTo144_HSI
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_HSI( void )
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= ( uint32_t )RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= ( uint32_t )RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 18 = 144 MHz */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL ) );
#if defined (CH32F20x_D6) || defined (CH32F20x_D8) || defined (CH32F20x_D8W)
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18 );
#else
RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18_EXTEN );
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while( ( RCC->CTLR & RCC_PLLRDY ) == 0 )
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_SW ) );
RCC->CFGR0 |= ( uint32_t )RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while( ( RCC->CFGR0 & ( uint32_t )RCC_SWS ) != ( uint32_t )0x08 )
{
}
}
#endif
================================================
FILE: hw/bsp/ch32f20x/system_ch32f20x.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32f20x.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : CH32F20x Device Peripheral Access Layer System Header File.
*******************************************************************************/
#ifndef __SYSTEM_CH32F20x_H
#define __SYSTEM_CH32F20x_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
/* System_Exported_Functions */
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
#ifdef __cplusplus
}
#endif
#endif /*__CH32F20x_SYSTEM_H */
================================================
FILE: hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake
================================================
set(LD_FLASH_SIZE 64K)
set(LD_RAM_SIZE 20K)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
CFG_EXAMPLE_MSC_DUAL_READONLY
)
endfunction()
================================================
FILE: hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h
================================================
/* metadata:
name: CH32V103R-R1-1v1
url: https://github.com/openwch/ch32v103/tree/main/SCHPCB/CH32V103R-R1-1v1
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_10
#define LED_STATE_ON 0
#define BUTTON_PORT GPIOA
#define BUTTON_PIN GPIO_Pin_1
#define BUTTON_STATE_ACTIVE 0
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk
================================================
CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY
LDFLAGS += \
-Wl,--defsym=__FLASH_SIZE=64K \
-Wl,--defsym=__RAM_SIZE=20K \
================================================
FILE: hw/bsp/ch32v10x/ch32v10x_conf.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v10x_conf.h
* Author : WCH
* Version : V1.0.0
* Date : 2020/04/30
* Description : Library configuration file.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32V10x_CONF_H
#define __CH32V10x_CONF_H
#include "ch32v10x_adc.h"
#include "ch32v10x_bkp.h"
#include "ch32v10x_crc.h"
#include "ch32v10x_dbgmcu.h"
#include "ch32v10x_dma.h"
#include "ch32v10x_exti.h"
#include "ch32v10x_flash.h"
#include "ch32v10x_gpio.h"
#include "ch32v10x_i2c.h"
#include "ch32v10x_iwdg.h"
#include "ch32v10x_pwr.h"
#include "ch32v10x_rcc.h"
#include "ch32v10x_rtc.h"
#include "ch32v10x_spi.h"
#include "ch32v10x_tim.h"
#include "ch32v10x_usart.h"
#include "ch32v10x_wwdg.h"
#include "ch32v10x_usb.h"
#include "ch32v10x_usb_host.h"
#include "ch32v10x_it.h"
#include "ch32v10x_misc.h"
#endif /* __CH32V10x_CONF_H */
================================================
FILE: hw/bsp/ch32v10x/ch32v10x_it.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v10x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/20
* Description : This file contains the headers of the interrupt handlers.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32V10x_IT_H
#define __CH32V10x_IT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v10x.h"
void USBHD_IRQHandler(void);
void USBWakeUp_IRQHandler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __CH32V10x_IT_H */
================================================
FILE: hw/bsp/ch32v10x/family.c
================================================
/* metadata:
manufacturer: WCH
*/
#include
// https://github.com/openwch/ch32v307/pull/90
// https://github.com/openwch/ch32v20x/pull/12
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
#include "ch32v10x.h"
#include "ch32v10x_it.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "bsp/board_api.h"
#include "board.h"
__attribute__((interrupt)) __attribute__((used))
void USBHD_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_USBFS
tud_int_handler(0);
#endif
}
__attribute__((interrupt)) __attribute__((used))
void USBWakeUp_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_USBFS
tud_int_handler(0);
#endif
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
__attribute__((interrupt)) __attribute__((used))
void SysTick_Handler(void) {
SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0;
SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0;
system_ticks++;
}
static uint32_t SysTick_Config(uint32_t ticks) {
NVIC_EnableIRQ(SysTicK_IRQn);
SysTick->CTLR = 0;
SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0;
SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0;
SysTick->CMPLR0 = (u8)(ticks & 0xFF);
SysTick->CMPLR1 = (u8)(ticks >> 8);
SysTick->CMPLR2 = (u8)(ticks >> 16);
SysTick->CMPLR3 = (u8)(ticks >> 24);
SysTick->CMPHR0 = SysTick->CMPHR1 = SysTick->CMPHR2 = SysTick->CMPHR3 = 0;
SysTick->CTLR = 1;
return 0;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
#endif
void board_init(void) {
__disable_irq();
#if CFG_TUSB_OS == OPT_OS_NONE
SysTick_Config(SystemCoreClock / 1000);
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
EXTEN->EXTEN_CTR |= EXTEN_USBFS_IO_EN;
uint8_t usb_div;
switch (SystemCoreClock) {
case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break;
case 72000000: usb_div = RCC_USBCLKSource_PLLCLK_1Div5; break;
default: TU_ASSERT(0,); break;
}
RCC_USBCLKConfig(usb_div);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE);
#ifdef LED_PIN
GPIO_InitTypeDef led_init = {
.GPIO_Pin = LED_PIN,
.GPIO_Mode = GPIO_Mode_Out_OD,
.GPIO_Speed = GPIO_Speed_50MHz,
};
GPIO_Init(LED_PORT, &led_init);
#endif
#ifdef BUTTON_PIN
GPIO_InitTypeDef button_init = {
.GPIO_Pin = BUTTON_PIN,
.GPIO_Mode = GPIO_Mode_IPU,
.GPIO_Speed = GPIO_Speed_50MHz,
};
GPIO_Init(BUTTON_PORT, &button_init);
#endif
// UART TX is PA9
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_InitTypeDef usart_init = {
.GPIO_Pin = GPIO_Pin_9,
.GPIO_Speed = GPIO_Speed_50MHz,
.GPIO_Mode = GPIO_Mode_AF_PP,
};
GPIO_Init(GPIOA, &usart_init);
USART_InitTypeDef usart = {
.USART_BaudRate = 115200,
.USART_WordLength = USART_WordLength_8b,
.USART_StopBits = USART_StopBits_1,
.USART_Parity = USART_Parity_No,
.USART_Mode = USART_Mode_Tx,
.USART_HardwareFlowControl = USART_HardwareFlowControl_None,
};
USART_Init(USART1, &usart);
USART_Cmd(USART1, ENABLE);
__enable_irq();
board_led_write(true);
}
void board_led_write(bool state) {
GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
}
uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN);
}
int board_uart_read(uint8_t *buf, int len) {
(void) buf;
(void) len;
return 0;
}
int board_uart_write(void const *buf, int len) {
const char *bufc = (const char *) buf;
for (int i = 0; i < len; i++) {
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, *bufc++);
}
return len;
}
================================================
FILE: hw/bsp/ch32v10x/family.cmake
================================================
include_guard()
#set(UF2_FAMILY_ID 0x699b62ec)
set(CH32_FAMILY ch32v10x)
set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v103)
set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS CH32V103 CACHE INTERNAL "")
set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg")
#------------------------------------
# Startup & Linker script
#------------------------------------
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${CH32_FAMILY}.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
if (NOT DEFINED STARTUP_FILE_GNU)
set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}.S)
endif ()
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
#------------------------------------
# Board Target
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SDK_SRC_DIR}/Core/core_riscv.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${SDK_SRC_DIR}/Core
${SDK_SRC_DIR}/Peripheral/inc
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
)
update_board(${BOARD_TARGET})
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_compile_options(${BOARD_TARGET} PUBLIC -mcmodel=medany)
endif()
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_CH32V103)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/wch/dcd_ch32_usbfs.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE}
-Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE}
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
message(FATAL_ERROR "Clang is not supported")
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_openocd_wch(${TARGET})
#family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
endfunction()
================================================
FILE: hw/bsp/ch32v10x/family.mk
================================================
# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable
#CROSS_COMPILE ?= riscv32-unknown-elf-
# Toolchain from https://nucleisys.com/download.php
#CROSS_COMPILE ?= riscv-nuclei-elf-
# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
CROSS_COMPILE ?= riscv-none-elf-
CH32_FAMILY = ch32v10x
SDK_DIR = hw/mcu/wch/ch32v103
SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= rv32imac-ilp32
# Port0 use FSDev, Port1 use USBFS
PORT ?= 0
CFLAGS += \
-mcmodel=medany \
-ffat-lto-objects \
-flto \
-DCFG_TUSB_MCU=OPT_MCU_CH32V103
# https://github.com/openwch/ch32v20x/pull/12
CFLAGS += -Wno-error=strict-prototypes
LDFLAGS_GCC += \
-nostdlib -nostartfiles \
--specs=nosys.specs --specs=nano.specs \
LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld
SRC_C += \
src/portable/wch/dcd_ch32_usbfs.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \
SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}.S
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(SDK_SRC_DIR)/Core \
$(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
flash: flash-openocd-wch
================================================
FILE: hw/bsp/ch32v10x/linker/ch32v10x.ld
================================================
/* Define default values if not already defined */
__FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K;
__RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE
}
ENTRY( _start )
__stack_size = 2048;
PROVIDE( _stack_size = __stack_size );
SECTIONS
{
.init :
{
_sinit = .;
. = ALIGN(4);
KEEP(*(SORT_NONE(.init)))
. = ALIGN(4);
_einit = .;
} >FLASH AT>FLASH
.vector :
{
*(.vector);
. = ALIGN(64);
} >FLASH AT>FLASH
.text :
{
. = ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata*)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
} >FLASH AT>FLASH
.fini :
{
KEEP(*(SORT_NONE(.fini)))
. = ALIGN(4);
} >FLASH AT>FLASH
PROVIDE( _etext = . );
PROVIDE( _eitcm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH AT>FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH AT>FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH AT>FLASH
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >FLASH AT>FLASH
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >FLASH AT>FLASH
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
} >RAM AT>FLASH
.dlalign :
{
. = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
.data :
{
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4);
PROVIDE( _edata = .);
} >RAM AT>FLASH
.bss :
{
. = ALIGN(4);
PROVIDE( _sbss = .);
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss*)
*(.gnu.linkonce.b.*)
*(COMMON*)
. = ALIGN(4);
PROVIDE( _ebss = .);
} >RAM AT>FLASH
PROVIDE( _end = _ebss);
PROVIDE( end = . );
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
{
PROVIDE( _heap_end = . );
. = ALIGN(4);
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
} >RAM
}
================================================
FILE: hw/bsp/ch32v10x/system_ch32v10x.c
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v10x.c
* Author : WCH
* Version : V1.0.0
* Date : 2020/04/30
* Description : CH32V10x Device Peripheral Access Layer System Source File.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "ch32v10x.h"
/*
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
* reset the HSI is used as SYSCLK source).
* If none of the define below is enabled, the HSI is used as System clock source.
*/
//#define SYSCLK_FREQ_HSE HSE_VALUE
//#define SYSCLK_FREQ_48MHz_HSE 48000000
//#define SYSCLK_FREQ_56MHz_HSE 56000000
#define SYSCLK_FREQ_72MHz_HSE 72000000
//#define SYSCLK_FREQ_HSI HSI_VALUE
//#define SYSCLK_FREQ_48MHz_HSI 48000000
//#define SYSCLK_FREQ_56MHz_HSI 56000000
//#define SYSCLK_FREQ_72MHz_HSI 72000000
/* Clock Definitions */
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
#else
uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
#endif
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/* ch32v10x_system_private_function_proto_types */
static void SetSysClock(void);
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSE
static void SetSysClockTo48_HSE( void );
#elif defined SYSCLK_FREQ_56MHz_HSE
static void SetSysClockTo56_HSE( void );
#elif defined SYSCLK_FREQ_72MHz_HSE
static void SetSysClockTo72_HSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSI
static void SetSysClockTo48_HSI( void );
#elif defined SYSCLK_FREQ_56MHz_HSI
static void SetSysClockTo56_HSI( void );
#elif defined SYSCLK_FREQ_72MHz_HSI
static void SetSysClockTo72_HSI( void );
#endif
/*********************************************************************
* @fn SystemInit
*
* @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
* the PLL and update the SystemCoreClock variable.
*
* @return none
*/
void SystemInit(void)
{
RCC->CTLR |= (uint32_t)0x00000001;
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
RCC->CTLR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
RCC->INTR = 0x009F0000;
SetSysClock();
}
/*********************************************************************
* @fn SystemCoreClockUpdate
*
* @brief Update SystemCoreClock variable according to Clock Register Values.
*
* @return none
*/
void SystemCoreClockUpdate(void)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0;
tmp = RCC->CFGR0 & RCC_SWS;
switch(tmp)
{
case 0x00:
SystemCoreClock = HSI_VALUE;
break;
case 0x04:
SystemCoreClock = HSE_VALUE;
break;
case 0x08:
pllmull = RCC->CFGR0 & RCC_PLLMULL;
pllsource = RCC->CFGR0 & RCC_PLLSRC;
pllmull = (pllmull >> 18) + 2;
if(pllsource == 0x00)
{
if( EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE )
{
SystemCoreClock = ( HSI_VALUE ) * pllmull;
}
else
{
SystemCoreClock = ( HSI_VALUE >> 1 ) * pllmull;
}
}
else
{
if((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
{
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
}
else
{
SystemCoreClock = HSE_VALUE * pllmull;
}
}
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
SystemCoreClock >>= tmp;
}
/*********************************************************************
* @fn SetSysClock
*
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClock(void)
{
//GPIO_IPD_Unused();
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_48MHz_HSE
SetSysClockTo48_HSE();
#elif defined SYSCLK_FREQ_56MHz_HSE
SetSysClockTo56_HSE();
#elif defined SYSCLK_FREQ_72MHz_HSE
SetSysClockTo72_HSE();
#elif defined SYSCLK_FREQ_48MHz_HSI
SetSysClockTo48_HSI();
#elif defined SYSCLK_FREQ_56MHz_HSI
SetSysClockTo56_HSI();
#elif defined SYSCLK_FREQ_72MHz_HSI
SetSysClockTo72_HSI();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
* source (default after reset)
*/
}
#ifdef SYSCLK_FREQ_HSE
/*********************************************************************
* @fn SetSysClockToHSE
*
* @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockToHSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
/* Flash 0 wait state */
FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
/* Select HSE as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
/* Wait till HSE is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSE
/*********************************************************************
* @fn SetSysClockTo48_HSE
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
/* Flash 1 wait state */
FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL6);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_56MHz_HSE
/*********************************************************************
* @fn SetSysClockTo56_HSE
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL7);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_72MHz_HSE
/*********************************************************************
* @fn SetSysClockTo72_HSE
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL9);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSI
/*********************************************************************
* @fn SetSysClockTo48_HSI
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* Enable Prefetch Buffer */
FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
/* Flash 1 wait state */
FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_56MHz_HSI
/*********************************************************************
* @fn SetSysClockTo56_HSI
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* Enable Prefetch Buffer */
FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
/* Flash 1 wait state */
FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 7 = 56 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_72MHz_HSI
/*********************************************************************
* @fn SetSysClockTo72_HSI
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* Enable Prefetch Buffer */
FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
/* Flash 1 wait state */
FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#endif
================================================
FILE: hw/bsp/ch32v10x/system_ch32v10x.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v10x.h
* Author : WCH
* Version : V1.0.0
* Date : 2020/04/30
* Description : CH32V10x Device Peripheral Access Layer System Header File.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __SYSTEM_CH32V10x_H
#define __SYSTEM_CH32V10x_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
/* System_Exported_Functions */
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
#ifdef __cplusplus
}
#endif
#endif /*__CH32V10x_SYSTEM_H */
================================================
FILE: hw/bsp/ch32v10x/wch-riscv.cfg
================================================
adapter driver wlinke
adapter speed 6000
transport select sdi
wlink_set_address 0x00000000
set _CHIPNAME wch_riscv
sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0
echo "Ready for Remote Connections"
================================================
FILE: hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake
================================================
set(MCU_VARIANT D6)
# 64KB zero-wait, 224KB total flash
#set(LD_FLASH_SIZE 64K)
set(LD_FLASH_SIZE 224K)
set(LD_RAM_SIZE 20K)
# set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/${CH32_FAMILY}_tinyuf2.ld)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
SYSCLK_FREQ_144MHz_HSE=144000000
CFG_EXAMPLE_MSC_DUAL_READONLY
)
endfunction()
================================================
FILE: hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h
================================================
/* metadata:
name: CH32V203C-R0-1v0
url: https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_0
#define LED_STATE_ON 0
#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
#define LED_MODE GPIO_Mode_Out_OD
#define UART_DEV USART1
#define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
#define UART_TX_PIN GPIO_Pin_9
#define UART_RX_PIN GPIO_Pin_10
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.mk
================================================
MCU_VARIANT = D6
CFLAGS += \
-DSYSCLK_FREQ_144MHz_HSE=144000000 \
-DCH32_FLASH_ENHANCE_READ_MODE=1 \
-DCFG_EXAMPLE_MSC_DUAL_READONLY \
# 64KB zero-wait, 224KB total flash
LDFLAGS += \
-Wl,--defsym=__FLASH_SIZE=224K \
-Wl,--defsym=__RAM_SIZE=20K \
================================================
FILE: hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake
================================================
set(MCU_VARIANT D6)
# 32KB zero-wait, 224KB total flash
#set(LD_FLASH_SIZE 32K)
set(LD_FLASH_SIZE 224K)
set(LD_RAM_SIZE 10K)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
SYSCLK_FREQ_144MHz_HSI=144000000
CFG_EXAMPLE_MSC_DUAL_READONLY
)
endfunction()
================================================
FILE: hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h
================================================
/* metadata:
name: CH32V203G-R0-1v0
url: https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_0
#define LED_STATE_ON 0
#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
#define LED_MODE GPIO_Mode_Out_OD
#define UART_DEV USART2
#define UART_CLOCK_EN() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE)
#define UART_TX_PIN GPIO_Pin_2
#define UART_RX_PIN GPIO_Pin_3
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.mk
================================================
MCU_VARIANT = D6
CFLAGS += \
-DSYSCLK_FREQ_144MHz_HSI=144000000 \
-DCH32_FLASH_ENHANCE_READ_MODE=1 \
-DCFG_EXAMPLE_MSC_DUAL_READONLY \
# 32KB zero-wait, 224KB total flash
LDFLAGS += \
-Wl,--defsym=__FLASH_SIZE=224K \
-Wl,--defsym=__RAM_SIZE=10K \
================================================
FILE: hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake
================================================
set(MCU_VARIANT D6)
# 64KB zero-wait, 224KB total flash
set(LD_FLASH_SIZE 64K)
#set(LD_FLASH_SIZE 224K)
set(LD_RAM_SIZE 20K)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
SYSCLK_FREQ_144MHz_HSE=144000000
CFG_EXAMPLE_MSC_DUAL_READONLY
)
endfunction()
================================================
FILE: hw/bsp/ch32v20x/boards/nanoch32v203/board.h
================================================
/* metadata:
name: nanoCH32V203
url: https://github.com/wuxx/nanoCH32V203
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_15
#define LED_STATE_ON 0
#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
#define LED_MODE GPIO_Mode_Out_OD
#define UART_DEV USART1
#define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
#define UART_TX_PIN GPIO_Pin_9
#define UART_RX_PIN GPIO_Pin_10
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/ch32v20x/boards/nanoch32v203/board.mk
================================================
MCU_VARIANT = D6
CFLAGS += \
-DSYSCLK_FREQ_144MHz_HSE=144000000 \
-DCH32_FLASH_ENHANCE_READ_MODE=1 \
-DCFG_EXAMPLE_MSC_DUAL_READONLY \
# 64KB zero-wait , 224KB total flash
LDFLAGS += \
-Wl,--defsym=__FLASH_SIZE=224K \
-Wl,--defsym=__RAM_SIZE=20K \
================================================
FILE: hw/bsp/ch32v20x/ch32v20x_conf.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_conf.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : Library configuration file.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32V20x_CONF_H
#define __CH32V20x_CONF_H
#include "ch32v20x_adc.h"
#include "ch32v20x_bkp.h"
#include "ch32v20x_can.h"
#include "ch32v20x_crc.h"
#include "ch32v20x_dbgmcu.h"
#include "ch32v20x_dma.h"
#include "ch32v20x_exti.h"
#include "ch32v20x_flash.h"
#include "ch32v20x_gpio.h"
#include "ch32v20x_i2c.h"
#include "ch32v20x_iwdg.h"
#include "ch32v20x_pwr.h"
#include "ch32v20x_rcc.h"
#include "ch32v20x_rtc.h"
#include "ch32v20x_spi.h"
#include "ch32v20x_tim.h"
#include "ch32v20x_usart.h"
#include "ch32v20x_wwdg.h"
#include "ch32v20x_it.h"
#include "ch32v20x_misc.h"
#endif /* __CH32V20x_CONF_H */
================================================
FILE: hw/bsp/ch32v20x/ch32v20x_it.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : This file contains the headers of the interrupt handlers.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32V20x_IT_H
#define __CH32V20x_IT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
void USB_LP_CAN1_RX0_IRQHandler(void);
void USB_HP_CAN1_TX_IRQHandler(void);
void USBWakeUp_IRQHandler(void);
void USBHD_IRQHandler(void);
void USBHDWakeUp_IRQHandler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __CH32V20x_IT_H */
================================================
FILE: hw/bsp/ch32v20x/family.c
================================================
/* metadata:
manufacturer: WCH
*/
#include
// https://github.com/openwch/ch32v307/pull/90
// https://github.com/openwch/ch32v20x/pull/12
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
#include "ch32v20x.h"
#include "ch32v20x_it.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "bsp/board_api.h"
#include "board.h"
/* CH32v203 depending on variants can support 2 USB IPs: FSDEV (port0) and USBFS (port1).
* By default, we use FSDEV, but you can explicitly select by define:
* - CFG_TUD_WCH_USBIP_FSDEV
* - CFG_TUD_WCH_USBIP_USBFS
*/
// Port0: USBD (fsdev)
__attribute__((interrupt)) __attribute__((used)) void USB_LP_CAN1_RX0_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_FSDEV
tud_int_handler(0);
#endif
}
__attribute__((interrupt)) __attribute__((used)) void USB_HP_CAN1_TX_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_FSDEV
tud_int_handler(0);
#endif
}
__attribute__((interrupt)) __attribute__((used)) void USBWakeUp_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_FSDEV
tud_int_handler(0);
#endif
}
// Port1: USBFS
__attribute__((interrupt)) __attribute__((used)) void USBHD_IRQHandler(void) {
#if CFG_TUD_ENABLED && CFG_TUD_WCH_USBIP_USBFS
tud_int_handler(1);
#endif
#if CFG_TUH_ENABLED
tuh_int_handler(1);
#endif
}
__attribute__((interrupt)) __attribute__((used)) void USBHDWakeUp_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_USBFS
tud_int_handler(0);
#endif
}
//--------------------------------------------------------------------+
// Board API
//--------------------------------------------------------------------+
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
__attribute__((interrupt)) void SysTick_Handler(void) {
SysTick->SR = 0;
system_ticks++;
}
static uint32_t SysTick_Config(uint32_t ticks) {
NVIC_EnableIRQ(SysTicK_IRQn);
SysTick->CTLR = 0;
SysTick->SR = 0;
SysTick->CNT = 0;
SysTick->CMP = ticks - 1;
SysTick->CTLR = 0xF;
return 0;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
#endif
void board_init(void) {
__disable_irq();
#if CFG_TUSB_OS == OPT_OS_NONE
SysTick_Config(SystemCoreClock / 1000);
#endif
LED_CLOCK_EN();
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = LED_PIN,
.GPIO_Mode = LED_MODE,
.GPIO_Speed = GPIO_Speed_10MHz,
};
GPIO_Init(LED_PORT, &GPIO_InitStructure);
#ifdef UART_DEV
UART_CLOCK_EN();
GPIO_InitTypeDef usart_init = {
.GPIO_Pin = UART_TX_PIN | UART_RX_PIN,
.GPIO_Speed = GPIO_Speed_50MHz,
.GPIO_Mode = GPIO_Mode_AF_PP,
};
GPIO_Init(GPIOA, &usart_init);
USART_InitTypeDef usart = {
.USART_BaudRate = 115200,
.USART_WordLength = USART_WordLength_8b,
.USART_StopBits = USART_StopBits_1,
.USART_Parity = USART_Parity_No,
.USART_Mode = USART_Mode_Tx | USART_Mode_Rx,
.USART_HardwareFlowControl = USART_HardwareFlowControl_None,
};
USART_Init(UART_DEV, &usart);
USART_Cmd(UART_DEV, ENABLE);
#endif
// USB init
uint8_t usb_div;
switch (SystemCoreClock) {
case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break;
case 96000000: usb_div = RCC_USBCLKSource_PLLCLK_Div2; break;
case 144000000: usb_div = RCC_USBCLKSource_PLLCLK_Div3; break;
default: TU_ASSERT(0,); break;
}
RCC_USBCLKConfig(usb_div);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); // FSDEV
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); // USB FS
__enable_irq();
}
void board_reset_to_bootloader(void) {
// board_led_write(true);
//
// __disable_irq();
//
// #if CFG_TUD_ENABLED
// tud_deinit(0);
// RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB, ENABLE);
// RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB, DISABLE);
// #endif
//
// SysTick->CTLR = 0;
// for (int i = WWDG_IRQn; i< DMA1_Channel8_IRQn; i++) {
// NVIC_DisableIRQ(i);
// }
//
// __enable_irq();
//
// // define function pointer to BOOT ROM address
// void (*bootloader_entry)(void) = (void (*)(void))0x1FFF8000;
//
// bootloader_entry();
//
// board_led_write(false);
// while(1) { }
}
void board_led_write(bool state) {
GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
}
uint32_t board_button_read(void) {
return false;
}
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
(void) max_len;
volatile uint32_t* ch32_uuid = ((volatile uint32_t*) 0x1FFFF7E8UL);
uint32_t* serial_32 = (uint32_t*) (uintptr_t) id;
serial_32[0] = ch32_uuid[0];
serial_32[1] = ch32_uuid[1];
serial_32[2] = ch32_uuid[2];
return 12;
}
int board_uart_read(uint8_t *buf, int len) {
#ifdef UART_DEV
int count;
for (count = 0; count < len; count++) {
if (USART_GetFlagStatus(UART_DEV, USART_FLAG_RXNE) == RESET) {
break;
}
buf[count] = USART_ReceiveData(UART_DEV);
}
return count;
#else
(void) buf; (void) len;
return 0;
#endif
}
int board_uart_write(void const *buf, int len) {
#ifdef UART_DEV
const char *bufc = (const char *) buf;
for (int i = 0; i < len; i++) {
while (USART_GetFlagStatus(UART_DEV, USART_FLAG_TC) == RESET);
USART_SendData(UART_DEV, *bufc++);
}
#else
(void) buf; (void) len;
#endif
return len;
}
================================================
FILE: hw/bsp/ch32v20x/family.cmake
================================================
include_guard()
set(UF2_FAMILY_ID 0x699b62ec)
set(CH32_FAMILY ch32v20x)
set(SDK_DIR ${TOP}/hw/mcu/wch/${CH32_FAMILY})
set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS CH32V20X CACHE INTERNAL "")
set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg")
# Port0 use FSDev, Port1 use USBFS
if (NOT DEFINED RHPORT_DEVICE)
set(RHPORT_DEVICE 0)
endif ()
# only port1 support host mode
set(RHPORT_HOST 1)
#------------------------------------
# Startup & Linker script
#------------------------------------
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${CH32_FAMILY}.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
if (NOT DEFINED STARTUP_FILE_GNU)
set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S)
endif ()
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
#------------------------------------
# Board Target
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SDK_SRC_DIR}/Core/core_riscv.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_flash.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${SDK_SRC_DIR}/Core
${SDK_SRC_DIR}/Peripheral/inc
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CH32V20x_${MCU_VARIANT}
BOARD_TUD_RHPORT=${RHPORT_DEVICE}
BOARD_TUH_RHPORT=${RHPORT_HOST}
)
if (RHPORT_DEVICE EQUAL 0)
target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUD_WCH_USBIP_FSDEV=1)
elseif (RHPORT_DEVICE EQUAL 1)
target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUH_WCH_USBIP_USBFS=1)
else()
message(FATAL_ERROR "Invalid RHPORT_DEVICE ${RHPORT_DEVICE}")
endif()
update_board(${BOARD_TARGET})
if (LD_FLASH_SIZE STREQUAL 224K)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CH32_FLASH_ENHANCE_READ_MODE=1
)
endif()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_compile_options(${TARGET} PUBLIC -mcmodel=medany)
endif()
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_CH32V20X)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/wch/dcd_ch32_usbfs.c
${TOP}/src/portable/wch/hcd_ch32_usbfs.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
-nostartfiles
--specs=nosys.specs --specs=nano.specs
-Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE}
-Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE}
"LINKER:--script=${LD_FILE_GNU}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
message(FATAL_ERROR "Clang is not supported")
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_openocd_wch(${TARGET})
family_flash_wlink_rs(${TARGET})
#family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
endfunction()
================================================
FILE: hw/bsp/ch32v20x/family.mk
================================================
# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable
#CROSS_COMPILE ?= riscv32-unknown-elf-
# Toolchain from https://nucleisys.com/download.php
#CROSS_COMPILE ?= riscv-nuclei-elf-
# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
CROSS_COMPILE ?= riscv-none-elf-
CH32_FAMILY = ch32v20x
SDK_DIR = hw/mcu/wch/ch32v20x
SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= rv32imac-ilp32
# Port0 use FSDev, Port1 use USBFS
PORT ?= 0
CFLAGS += \
-mcmodel=medany \
-ffat-lto-objects \
-flto \
-DCH32V20x_${MCU_VARIANT} \
-DCFG_TUSB_MCU=OPT_MCU_CH32V20X
# https://github.com/openwch/ch32v20x/pull/12
CFLAGS += -Wno-error=strict-prototypes
ifeq ($(PORT),0)
$(info "Using FSDEV driver")
CFLAGS += -DCFG_TUD_WCH_USBIP_FSDEV=1
$(info "Using USBFS Host driver")
CFLAGS += -DCFG_TUH_WCH_USBIP_USBFS=1
else
$(info "Using USBFS driver")
CFLAGS += -DCFG_TUD_WCH_USBIP_USBFS=1
endif
LDFLAGS_GCC += \
-nostdlib -nostartfiles \
--specs=nosys.specs --specs=nano.specs \
LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld
SRC_C += \
src/portable/wch/dcd_ch32_usbfs.c \
src/portable/wch/hcd_ch32_usbfs.c \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \
SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(SDK_SRC_DIR)/Core \
$(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
flash: flash-wlink-rs
#flash: flash-openocd-wch
================================================
FILE: hw/bsp/ch32v20x/linker/ch32v20x.ld
================================================
/* Define default values if not already defined */
__flash_size = DEFINED(__FLASH_SIZE) ? __FLASH_SIZE : 64K;
__ram_size = DEFINED(__RAM_SIZE) ? __RAM_SIZE : 20K;
__stack_size = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 2048;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_size
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __ram_size
}
ENTRY( _start )
PROVIDE( _stack_size = __stack_size );
SECTIONS
{
.init :
{
_sinit = .;
. = ALIGN(4);
KEEP(*(SORT_NONE(.init)))
. = ALIGN(4);
_einit = .;
} >FLASH AT>FLASH
.vector :
{
*(.vector);
. = ALIGN(64);
} >FLASH AT>FLASH
.text :
{
. = ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata*)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
} >FLASH AT>FLASH
.fini :
{
KEEP(*(SORT_NONE(.fini)))
. = ALIGN(4);
} >FLASH AT>FLASH
PROVIDE( _etext = . );
PROVIDE( _eitcm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH AT>FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH AT>FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH AT>FLASH
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >FLASH AT>FLASH
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >FLASH AT>FLASH
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
} >RAM AT>FLASH
.dlalign :
{
. = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
.data :
{
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4);
PROVIDE( _edata = .);
} >RAM AT>FLASH
.bss :
{
. = ALIGN(4);
PROVIDE( _sbss = .);
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss*)
*(.gnu.linkonce.b.*)
*(COMMON*)
. = ALIGN(4);
PROVIDE( _ebss = .);
} >RAM AT>FLASH
PROVIDE( _end = _ebss);
PROVIDE( end = . );
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
{
PROVIDE( _heap_end = . );
. = ALIGN(4);
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
} >RAM
}
================================================
FILE: hw/bsp/ch32v20x/system_ch32v20x.c
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v20x.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V20x Device Peripheral Access Layer System Source File.
* For HSE = 32Mhz (CH32V208x/CH32V203RBT6)
* For HSE = 8Mhz (other CH32V203x)
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "ch32v20x.h"
/*
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
* reset the HSI is used as SYSCLK source).
* If none of the define below is enabled, the HSI is used as System clock source.
*/
//#define SYSCLK_FREQ_HSE HSE_VALUE
// #define SYSCLK_FREQ_48MHz_HSE 48000000
//#define SYSCLK_FREQ_56MHz_HSE 56000000
// #define SYSCLK_FREQ_72MHz_HSE 72000000
// #define SYSCLK_FREQ_96MHz_HSE 96000000
//#define SYSCLK_FREQ_120MHz_HSE 120000000
//#define SYSCLK_FREQ_144MHz_HSE 144000000
//#define SYSCLK_FREQ_HSI HSI_VALUE
//#define SYSCLK_FREQ_48MHz_HSI 48000000
//#define SYSCLK_FREQ_56MHz_HSI 56000000
//#define SYSCLK_FREQ_72MHz_HSI 72000000
//#define SYSCLK_FREQ_96MHz_HSI 96000000
//#define SYSCLK_FREQ_120MHz_HSI 120000000
//#define SYSCLK_FREQ_144MHz_HSI 144000000
/* Clock Definitions */
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSI; /* System Clock Frequency (Core Clock) */
#else
uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
#endif
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/* system_private_function_proto_types */
static void SetSysClock(void);
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSE
static void SetSysClockTo48_HSE( void );
#elif defined SYSCLK_FREQ_56MHz_HSE
static void SetSysClockTo56_HSE( void );
#elif defined SYSCLK_FREQ_72MHz_HSE
static void SetSysClockTo72_HSE( void );
#elif defined SYSCLK_FREQ_96MHz_HSE
static void SetSysClockTo96_HSE( void );
#elif defined SYSCLK_FREQ_120MHz_HSE
static void SetSysClockTo120_HSE( void );
#elif defined SYSCLK_FREQ_144MHz_HSE
static void SetSysClockTo144_HSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSI
static void SetSysClockTo48_HSI( void );
#elif defined SYSCLK_FREQ_56MHz_HSI
static void SetSysClockTo56_HSI( void );
#elif defined SYSCLK_FREQ_72MHz_HSI
static void SetSysClockTo72_HSI( void );
#elif defined SYSCLK_FREQ_96MHz_HSI
static void SetSysClockTo96_HSI( void );
#elif defined SYSCLK_FREQ_120MHz_HSI
static void SetSysClockTo120_HSI( void );
#elif defined SYSCLK_FREQ_144MHz_HSI
static void SetSysClockTo144_HSI( void );
#endif
/*********************************************************************
* @fn SystemInit
*
* @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
* the PLL and update the SystemCoreClock variable.
*
* @return none
*/
void SystemInit (void)
{
// Enable Flash enhance read mode for full 224KB
#if defined(CH32_FLASH_ENHANCE_READ_MODE) && CH32_FLASH_ENHANCE_READ_MODE == 1
FLASH->KEYR = 0x45670123; // FLASH_Unlock_Fast();
FLASH->KEYR = 0xCDEF89AB;
FLASH->CTLR |= (1 << 24); // Enhanced Read Mode
FLASH->CTLR |= (1 << 15); // FLASH_Lock_Fast();
#endif
RCC->CTLR |= (uint32_t)0x00000001;
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
RCC->CTLR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
RCC->INTR = 0x009F0000;
SetSysClock();
}
/*********************************************************************
* @fn SystemCoreClockUpdate
*
* @brief Update SystemCoreClock variable according to Clock Register Values.
*
* @return none
*/
void SystemCoreClockUpdate (void)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0;
tmp = RCC->CFGR0 & RCC_SWS;
switch (tmp)
{
case 0x00:
SystemCoreClock = HSI_VALUE;
break;
case 0x04:
SystemCoreClock = HSE_VALUE;
break;
case 0x08:
pllmull = RCC->CFGR0 & RCC_PLLMULL;
pllsource = RCC->CFGR0 & RCC_PLLSRC;
pllmull = ( pllmull >> 18) + 2;
if(pllmull == 17) pllmull = 18;
if (pllsource == 0x00)
{
if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){
SystemCoreClock = HSI_VALUE * pllmull;
}
else{
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
}
else
{
#if defined (CH32V20x_D8W)
if((RCC->CFGR0 & (3<<22)) == (3<<22))
{
SystemCoreClock = ((HSE_VALUE>>1)) * pllmull;
}
else
#endif
if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
{
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
SystemCoreClock = ((HSE_VALUE>>2) >> 1) * pllmull;
#else
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
#endif
}
else
{
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
SystemCoreClock = (HSE_VALUE>>2) * pllmull;
#else
SystemCoreClock = HSE_VALUE * pllmull;
#endif
}
}
if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2);
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
SystemCoreClock >>= tmp;
}
/*********************************************************************
* @fn SetSysClock
*
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_48MHz_HSE
SetSysClockTo48_HSE();
#elif defined SYSCLK_FREQ_56MHz_HSE
SetSysClockTo56_HSE();
#elif defined SYSCLK_FREQ_72MHz_HSE
SetSysClockTo72_HSE();
#elif defined SYSCLK_FREQ_96MHz_HSE
SetSysClockTo96_HSE();
#elif defined SYSCLK_FREQ_120MHz_HSE
SetSysClockTo120_HSE();
#elif defined SYSCLK_FREQ_144MHz_HSE
SetSysClockTo144_HSE();
#elif defined SYSCLK_FREQ_48MHz_HSI
SetSysClockTo48_HSI();
#elif defined SYSCLK_FREQ_56MHz_HSI
SetSysClockTo56_HSI();
#elif defined SYSCLK_FREQ_72MHz_HSI
SetSysClockTo72_HSI();
#elif defined SYSCLK_FREQ_96MHz_HSI
SetSysClockTo96_HSI();
#elif defined SYSCLK_FREQ_120MHz_HSI
SetSysClockTo120_HSI();
#elif defined SYSCLK_FREQ_144MHz_HSI
SetSysClockTo144_HSI();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
* source (default after reset)
*/
}
#ifdef SYSCLK_FREQ_HSE
/*********************************************************************
* @fn SetSysClockToHSE
*
* @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockToHSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
/* Select HSE as system clock source
* CH32V20x_D6 (HSE=8MHZ)
* CH32V20x_D8 (HSE=32MHZ)
* CH32V20x_D8W (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
/* Wait till HSE is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSE
/*********************************************************************
* @fn SetSysClockTo48_HSE
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_56MHz_HSE
/*********************************************************************
* @fn SetSysClockTo56_HSE
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_72MHz_HSE
/*********************************************************************
* @fn SetSysClockTo72_HSE
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_96MHz_HSE
/*********************************************************************
* @fn SetSysClockTo96_HSE
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_120MHz_HSE
/*********************************************************************
* @fn SetSysClockTo120_HSE
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
#if defined (CH32V20x_D8W)
RCC->CFGR0 |= (uint32_t)(3<<22);
/* HCLK = SYSCLK/2 */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
#else
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
#endif
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 15 = 120 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_144MHz_HSE
/*********************************************************************
* @fn SetSysClockTo144_HSE
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSI
/*********************************************************************
* @fn SetSysClockTo48_HSI
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_56MHz_HSI
/*********************************************************************
* @fn SetSysClockTo56_HSI
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 7 = 48 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_72MHz_HSI
/*********************************************************************
* @fn SetSysClockTo72_HSI
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_96MHz_HSI
/*********************************************************************
* @fn SetSysClockTo96_HSI
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 12 = 96 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_120MHz_HSI
/*********************************************************************
* @fn SetSysClockTo120_HSI
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 15 = 120 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_144MHz_HSI
/*********************************************************************
* @fn SetSysClockTo144_HSI
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 18 = 144 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#endif
================================================
FILE: hw/bsp/ch32v20x/system_ch32v20x.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v20x.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V20x Device Peripheral Access Layer System Header File.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __SYSTEM_ch32v20x_H
#define __SYSTEM_ch32v20x_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
/* System_Exported_Functions */
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
#ifdef __cplusplus
}
#endif
#endif /*__CH32V20x_SYSTEM_H */
================================================
FILE: hw/bsp/ch32v20x/wch-riscv.cfg
================================================
adapter driver wlinke
adapter speed 6000
transport select sdi
wlink_set_address 0x00000000
set _CHIPNAME wch_riscv
sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0
echo "Ready for Remote Connections"
================================================
FILE: hw/bsp/ch32v30x/boards/ch32v307v_r1_1v0/board.cmake
================================================
set(LD_FLASH_SIZE 256K)
set(LD_RAM_SIZE 64K)
function(update_board TARGET)
endfunction()
================================================
FILE: hw/bsp/ch32v30x/boards/ch32v307v_r1_1v0/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Ha Thach (tinyusb.org) for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* metadata:
name: CH32V307V-R1-1v0
url: https://github.com/openwch/ch32v307/tree/main/SCHPCB/CH32V307V-R1-1v0
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
// LED: need to wire pin LED1 to PC0 in the J3 header
#define LED_PORT GPIOC
#define LED_PIN GPIO_Pin_0
#define LED_STATE_ON 0
#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE)
// Button: need to wire pin KEY to PC1 in the J3 header
#define BUTTON_PORT GPIOC
#define BUTTON_PIN GPIO_Pin_1
#define BUTTON_STATE_ACTIVE 0
#define BUTTON_CLOCK_EN() do { } while(0) // same as LED clock, no need to do anything
// TODO UART port
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/ch32v30x/boards/ch32v307v_r1_1v0/board.mk
================================================
LDFLAGS += \
-Wl,--defsym=__FLASH_SIZE=256K \
-Wl,--defsym=__RAM_SIZE=64K \
================================================
FILE: hw/bsp/ch32v30x/boards/nanoch32v305/board.cmake
================================================
set(LD_FLASH_SIZE 128K)
set(LD_RAM_SIZE 32K)
function(update_board TARGET)
endfunction()
================================================
FILE: hw/bsp/ch32v30x/boards/nanoch32v305/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Ha Thach (tinyusb.org) for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* metadata:
name: nanoCH32V305
url: https://github.com/wuxx/nanoCH32V305
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_3
#define LED_STATE_ON 0
#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
// TODO UART port
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/ch32v30x/boards/nanoch32v305/board.mk
================================================
LDFLAGS += \
-Wl,--defsym=__FLASH_SIZE=128K \
-Wl,--defsym=__RAM_SIZE=32K \
================================================
FILE: hw/bsp/ch32v30x/ch32v30x_conf.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v30x_conf.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : Library configuration file.
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
#ifndef __CH32V30x_CONF_H
#define __CH32V30x_CONF_H
#include "ch32v30x_adc.h"
#include "ch32v30x_bkp.h"
#include "ch32v30x_can.h"
#include "ch32v30x_crc.h"
#include "ch32v30x_dac.h"
#include "ch32v30x_dbgmcu.h"
#include "ch32v30x_dma.h"
#include "ch32v30x_exti.h"
#include "ch32v30x_flash.h"
#include "ch32v30x_fsmc.h"
#include "ch32v30x_gpio.h"
#include "ch32v30x_i2c.h"
#include "ch32v30x_iwdg.h"
#include "ch32v30x_pwr.h"
#include "ch32v30x_rcc.h"
#include "ch32v30x_rtc.h"
#include "ch32v30x_sdio.h"
#include "ch32v30x_spi.h"
#include "ch32v30x_tim.h"
#include "ch32v30x_usart.h"
#include "ch32v30x_wwdg.h"
#include "ch32v30x_it.h"
#include "ch32v30x_misc.h"
#endif /* __CH32V30x_CONF_H */
================================================
FILE: hw/bsp/ch32v30x/ch32v30x_it.c
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v30x_it.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : Main Interrupt Service Routines.
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
#include "ch32v30x_it.h"
void NMI_Handler(void) __attribute__((naked));
void HardFault_Handler(void) __attribute__((naked));
/*********************************************************************
* @fn NMI_Handler
*
* @brief This function handles NMI exception.
*
* @return none
*/
void NMI_Handle(void){
__asm volatile ("call NMI_Handler_impl; mret");
}
__attribute__((used)) void NMI_Handler_impl(void)
{
}
/*********************************************************************
* @fn HardFault_Handler
*
* @brief This function handles Hard Fault exception.
*
* @return none
*/
void HardFault_Handler(void){
__asm volatile ("call HardFault_Handler_impl; mret");
}
__attribute__((used)) void HardFault_Handler_impl(void)
{
while (1)
{
}
}
================================================
FILE: hw/bsp/ch32v30x/ch32v30x_it.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v30x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : This file contains the headers of the interrupt handlers.
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
#ifndef __CH32V30x_IT_H
#define __CH32V30x_IT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v30x.h"
void USBHS_IRQHandler(void);
void OTG_FS_IRQHandler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __CH32V30x_IT_H */
================================================
FILE: hw/bsp/ch32v30x/debug_uart.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Greg Davill
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include "debug_uart.h"
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
#include
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#define UART_RINGBUFFER_SIZE_TX 128
#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)
static char tx_buf[UART_RINGBUFFER_SIZE_TX];
static unsigned int tx_produce;
static volatile unsigned int tx_consume;
void USART1_IRQHandler(void) __attribute__((naked));
void USART1_IRQHandler(void) {
__asm volatile ("call USART1_IRQHandler_impl; mret");
}
void USART1_IRQHandler_impl(void) __attribute__((used)) ;
void USART1_IRQHandler_impl(void)
{
if(USART_GetITStatus(USART1, USART_IT_TC) != RESET)
{
USART_ClearITPendingBit(USART1, USART_IT_TC);
if(tx_consume != tx_produce) {
USART_SendData(USART1, tx_buf[tx_consume]);
tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX;
}
}
}
void uart_write(char c)
{
unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX;
NVIC_DisableIRQ(USART1_IRQn);
if((tx_consume != tx_produce) || (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)) {
tx_buf[tx_produce] = c;
tx_produce = tx_produce_next;
} else {
USART_SendData(USART1, c);
}
NVIC_EnableIRQ(USART1_IRQn);
}
void uart_sync(void)
{
while(tx_consume != tx_produce);
}
void usart_printf_init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
tx_produce = 0;
tx_consume = 0;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_TC, ENABLE);
USART_Cmd(USART1, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure = { 0 };
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
================================================
FILE: hw/bsp/ch32v30x/debug_uart.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Greg Davill
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include
void uart_write(char c);
void uart_sync(void);
void usart_printf_init(uint32_t baudrate);
================================================
FILE: hw/bsp/ch32v30x/family.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Greg Davill
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
manufacturer: WCH
*/
#include "stdio.h"
// https://github.com/openwch/ch32v307/pull/90
// https://github.com/openwch/ch32v20x/pull/12
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
#include "debug_uart.h"
#include "ch32v30x.h"
#include "ch32v30x_it.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "bsp/board_api.h"
#include "board.h"
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
// TODO maybe having FS as port0, HS as port1
__attribute__((interrupt)) void USBHS_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_USBHS
tud_int_handler(0);
#endif
}
__attribute__((interrupt)) void OTG_FS_IRQHandler(void) {
#if CFG_TUD_WCH_USBIP_USBFS
tud_int_handler(0);
#endif
}
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
static uint32_t SysTick_Config(uint32_t ticks) {
NVIC_EnableIRQ(SysTicK_IRQn);
SysTick->CTLR = 0;
SysTick->SR = 0;
SysTick->CNT = 0;
SysTick->CMP = ticks - 1;
SysTick->CTLR = 0xF;
return 0;
}
void board_init(void) {
/* Disable interrupts during init */
__disable_irq();
#if CFG_TUSB_OS == OPT_OS_NONE
SysTick_Config(SystemCoreClock / 1000);
#endif
usart_printf_init(CFG_BOARD_UART_BAUDRATE);
#ifdef CH32V30x_D8C
// v305/v307: Highspeed USB
RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY);
RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE);
RCC_USBHSConfig(RCC_USBPLL_Div2);
RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M);
RCC_USBHSPHYPLLALIVEcmd(ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
#endif
// Fullspeed USB
uint8_t otg_div;
switch (SystemCoreClock) {
case 48000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div1; break;
case 96000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div2; break;
case 144000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div3; break;
default: TU_ASSERT(0,); break;
}
RCC_OTGFSCLKConfig(otg_div);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure = {0};
// LED
LED_CLOCK_EN();
GPIO_InitStructure.GPIO_Pin = LED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT, &GPIO_InitStructure);
// Button
#ifdef BUTTON_PORT
BUTTON_CLOCK_EN();
GPIO_InitStructure.GPIO_Pin = BUTTON_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BUTTON_PORT, &GPIO_InitStructure);
#endif
/* Enable interrupts globally */
__enable_irq();
board_delay(2);
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
__attribute__((interrupt)) void SysTick_Handler(void) {
SysTick->SR = 0;
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
#endif
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
void board_led_write(bool state) {
GPIO_WriteBit(LED_PORT, LED_PIN, state);
}
uint32_t board_button_read(void) {
#ifdef BUTTON_PORT
return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN);
#else
return false;
#endif
}
int board_uart_read(uint8_t* buf, int len) {
(void) buf;
(void) len;
return 0;
}
int board_uart_write(void const* buf, int len) {
int txsize = len;
const char* bufc = (const char*) buf;
while (txsize--) {
uart_write(*bufc++);
}
uart_sync();
return len;
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(char* file, uint32_t line) {
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line
number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line)
*/
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/ch32v30x/family.cmake
================================================
include_guard()
set(CH32_FAMILY ch32v30x)
set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v307)
set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS CH32V307 CACHE INTERNAL "")
set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg")
# default to highspeed, used to select USBFS / USBHS driver
if (NOT DEFINED SPEED)
set(SPEED high)
endif()
#------------------------------------
# Startup & Linker script
#------------------------------------
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/ch32v30x.ld)
endif ()
set(LD_FILE_Clang ${LD_FILE_GNU})
if (NOT DEFINED STARTUP_FILE_GNU)
set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_D8C.S)
endif ()
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
#------------------------------------
# Board Target
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SDK_SRC_DIR}/Core/core_riscv.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${CH32_FAMILY}_it.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${SDK_SRC_DIR}/Core
${SDK_SRC_DIR}/Peripheral/inc
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
)
if (SPEED STREQUAL high)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CFG_TUD_WCH_USBIP_USBHS=1
# BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
)
else ()
target_compile_definitions(${BOARD_TARGET} PUBLIC
CFG_TUD_WCH_USBIP_USBFS=1
)
endif ()
update_board(${BOARD_TARGET})
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${BOARD_TARGET} PUBLIC
-msmall-data-limit=8
-mno-save-restore
-fmessage-length=0
-fsigned-char
)
endif ()
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_CH32V307)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/wch/dcd_ch32_usbhs.c
${TOP}/src/portable/wch/dcd_ch32_usbfs.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
-nostartfiles
--specs=nosys.specs --specs=nano.specs
-Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE}
-Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE}
"LINKER:--script=${LD_FILE_GNU}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
message(FATAL_ERROR "Clang is not supported")
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_openocd_wch(${TARGET})
family_flash_wlink_rs(${TARGET})
endfunction()
================================================
FILE: hw/bsp/ch32v30x/family.mk
================================================
# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable
#CROSS_COMPILE ?= riscv32-unknown-elf-
# Toolchain from https://nucleisys.com/download.php
#CROSS_COMPILE ?= riscv-nuclei-elf-
# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
CROSS_COMPILE ?= riscv-none-elf-
CH32_FAMILY = ch32v30x
SDK_DIR = hw/mcu/wch/ch32v307
SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= rv32imac-ilp32
# default to use high speed port, unless specified in board.mk or command line
SPEED ?= high
CFLAGS += \
-flto \
-msmall-data-limit=8 \
-mno-save-restore \
-fmessage-length=0 \
-fsigned-char \
-DCFG_TUSB_MCU=OPT_MCU_CH32V307 \
# https://github.com/openwch/ch32v307/pull/90
CFLAGS += -Wno-error=strict-prototypes
ifeq ($(SPEED),high)
$(info "Using USBHS driver for HighSpeed mode")
CFLAGS += -DCFG_TUD_WCH_USBIP_USBHS=1
else
$(info "Using USBFS driver for FullSpeed mode")
CFLAGS += -DCFG_TUD_WCH_USBIP_USBFS=1
endif
LDFLAGS_GCC += \
-nostdlib -nostartfiles \
--specs=nosys.specs --specs=nano.specs \
SRC_C += \
src/portable/wch/dcd_ch32_usbhs.c \
src/portable/wch/dcd_ch32_usbfs.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c
SRC_S += \
$(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}_D8C.S
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/$(SDK_SRC_DIR)/Core \
$(TOP)/$(SDK_SRC_DIR)/Peripheral/inc
LD_FILE ?= $(FAMILY_PATH)/linker/ch32v30x.ld
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
flash: flash-openocd-wch
================================================
FILE: hw/bsp/ch32v30x/linker/ch32v30x.ld
================================================
/* Define default values if not already defined */
__flash_size = DEFINED(__FLASH_SIZE) ? __FLASH_SIZE : 128K;
__ram_size = DEFINED(__RAM_SIZE) ? __RAM_SIZE : 32K;
__stack_size = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 2048;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_size
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __ram_size
}
ENTRY( _start )
PROVIDE( _stack_size = __stack_size );
SECTIONS
{
.init :
{
_sinit = .;
. = ALIGN(4);
KEEP(*(SORT_NONE(.init)))
. = ALIGN(4);
_einit = .;
} >FLASH AT>FLASH
.vector :
{
*(.vector);
. = ALIGN(64);
} >FLASH AT>FLASH
.text :
{
. = ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
} >FLASH AT>FLASH
.fini :
{
KEEP(*(SORT_NONE(.fini)))
. = ALIGN(4);
} >FLASH AT>FLASH
PROVIDE( _etext = . );
PROVIDE( _eitcm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH AT>FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH AT>FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH AT>FLASH
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >FLASH AT>FLASH
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >FLASH AT>FLASH
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
} >RAM AT>FLASH
.dlalign :
{
. = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
.data :
{
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4);
PROVIDE( _edata = .);
} >RAM AT>FLASH
.bss :
{
. = ALIGN(4);
PROVIDE( _sbss = .);
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss*)
*(.gnu.linkonce.b.*)
*(COMMON*)
. = ALIGN(4);
PROVIDE( _ebss = .);
} >RAM AT>FLASH
PROVIDE( _end = _ebss);
PROVIDE( end = . );
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
{
PROVIDE( _heap_end = . );
. = ALIGN(4);
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
__freertos_irq_stack_top = .;
} >RAM
}
================================================
FILE: hw/bsp/ch32v30x/system_ch32v30x.c
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v30x.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V30x Device Peripheral Access Layer System Source File.
* For HSE = 8Mhz
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*********************************************************************************/
#include "ch32v30x.h"
/*
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
* reset the HSI is used as SYSCLK source).
* If none of the define below is enabled, the HSI is used as System clock source.
*/
// #define SYSCLK_FREQ_HSE HSE_VALUE
/* #define SYSCLK_FREQ_24MHz 24000000 */
//#define SYSCLK_FREQ_48MHz 48000000
/* #define SYSCLK_FREQ_56MHz 56000000 */
//#define SYSCLK_FREQ_72MHz 72000000
//#define SYSCLK_FREQ_96MHz 96000000
//#define SYSCLK_FREQ_120MHz 120000000
#define SYSCLK_FREQ_144MHz 144000000
/* Clock Definitions */
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz; /* System Clock Frequency (Core Clock) */
#else /* HSI Selected as System Clock source */
uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
#endif
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/* system_private_function_proto_types */
static void SetSysClock(void);
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHz
static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_48MHz
static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
static void SetSysClockTo56(void);
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
#elif defined SYSCLK_FREQ_96MHz
static void SetSysClockTo96(void);
#elif defined SYSCLK_FREQ_120MHz
static void SetSysClockTo120(void);
#elif defined SYSCLK_FREQ_144MHz
static void SetSysClockTo144(void);
#endif
/*********************************************************************
* @fn SystemInit
*
* @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
* the PLL and update the SystemCoreClock variable.
*
* @return none
*/
void SystemInit (void)
{
RCC->CTLR |= (uint32_t)0x00000001;
#ifdef CH32V30x_D8C
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR0 &= (uint32_t)0xF0FF0000;
#endif
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
RCC->CTLR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
#ifdef CH32V30x_D8C
RCC->CTLR &= (uint32_t)0xEBFFFFFF;
RCC->INTR = 0x00FF0000;
RCC->CFGR2 = 0x00000000;
#else
RCC->INTR = 0x009F0000;
#endif
SetSysClock();
}
/*********************************************************************
* @fn SystemCoreClockUpdate
*
* @brief Update SystemCoreClock variable according to Clock Register Values.
*
* @return none
*/
void SystemCoreClockUpdate (void)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0;
tmp = RCC->CFGR0 & RCC_SWS;
switch (tmp)
{
case 0x00:
SystemCoreClock = HSI_VALUE;
break;
case 0x04:
SystemCoreClock = HSE_VALUE;
break;
case 0x08:
pllmull = RCC->CFGR0 & RCC_PLLMULL;
pllsource = RCC->CFGR0 & RCC_PLLSRC;
pllmull = ( pllmull >> 18) + 2;
#ifdef CH32V30x_D8
if(pllmull == 17) pllmull = 18;
#else
if(pllmull == 2) pllmull = 18;
if(pllmull == 15){
pllmull = 13; /* *6.5 */
Pll_6_5 = 1;
}
if(pllmull == 16) pllmull = 15;
if(pllmull == 17) pllmull = 16;
#endif
if (pllsource == 0x00)
{
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
else
{
if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
{
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
}
else
{
SystemCoreClock = HSE_VALUE * pllmull;
}
}
if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2);
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
SystemCoreClock >>= tmp;
}
/*********************************************************************
* @fn SetSysClock
*
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#elif defined SYSCLK_FREQ_96MHz
SetSysClockTo96();
#elif defined SYSCLK_FREQ_120MHz
SetSysClockTo120();
#elif defined SYSCLK_FREQ_144MHz
SetSysClockTo144();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
* source (default after reset)
*/
}
#ifdef SYSCLK_FREQ_HSE
/*********************************************************************
* @fn SetSysClockToHSE
*
* @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockToHSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
/* Select HSE as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
/* Wait till HSE is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_24MHz
/*********************************************************************
* @fn SetSysClockTo24
*
* @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo24(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
#ifdef CH32V30x_D8
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL3);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL3_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz
/*********************************************************************
* @fn SetSysClockTo48
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
#ifdef CH32V30x_D8
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_56MHz
/*********************************************************************
* @fn SetSysClockTo56
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
#ifdef CH32V30x_D8
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_72MHz
/*********************************************************************
* @fn SetSysClockTo72
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
#ifdef CH32V30x_D8
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_96MHz
/*********************************************************************
* @fn SetSysClockTo96
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 12 = 96 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
#ifdef CH32V30x_D8
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_120MHz
/*********************************************************************
* @fn SetSysClockTo120
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 15 = 120 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
#ifdef CH32V30x_D8
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_144MHz
/*********************************************************************
* @fn SetSysClockTo144
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 18 = 144 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
#ifdef CH32V30x_D8
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18);
#else
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18_EXTEN);
#endif
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#endif
================================================
FILE: hw/bsp/ch32v30x/system_ch32v30x.h
================================================
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v30x.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V30x Device Peripheral Access Layer System Header File.
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
#ifndef __SYSTEM_CH32V30x_H
#define __SYSTEM_CH32V30x_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
/* System_Exported_Functions */
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
#ifdef __cplusplus
}
#endif
#endif /*__CH32V30x_SYSTEM_H */
================================================
FILE: hw/bsp/ch32v30x/wch-riscv.cfg
================================================
adapter driver wlinke
adapter speed 6000
transport select sdi
wlink_set_address 0x00000000
set _CHIPNAME wch_riscv
sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0
echo "Ready for Remote Connections"
================================================
FILE: hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
#include "nuttx/config.h"
#endif
/* Cortex-M4F port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE (1024)
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configRECORD_STACK_HIGH_ADDRESS 1
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header
// CXD56 (Cortex-M4F) has 3 priority bits
#define configPRIO_BITS 3
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<
#define LED_PIN PIN_I2S1_BCK
#define BUTTON_PIN PIN_HIF_IRQ_OUT
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: hw/bsp/cxd56/boards/spresense/board.mk
================================================
# Spresense board configuration
SERIAL ?= /dev/ttyUSB0
# flash
flash: $(BUILD)/$(PROJECT).spk
@echo FLASH $<
@$(PYTHON) $(TOP)/hw/mcu/sony/cxd56/tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $<
================================================
FILE: hw/bsp/cxd56/family.c
================================================
/*
* The MIT License (MIT)
*
* Copyright 2019 Sony Semiconductor Solutions Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include
#include
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "bsp/board_api.h"
#include "board.h"
// Initialize on-board peripherals : led, button, uart and USB
void board_init(void)
{
boardctl(BOARDIOC_INIT, 0);
board_gpio_write(PIN_I2S1_BCK, -1);
board_gpio_config(PIN_I2S1_BCK, 0, false, true, PIN_FLOAT);
board_gpio_write(PIN_HIF_IRQ_OUT, -1);
board_gpio_config(PIN_HIF_IRQ_OUT, 0, true, true, PIN_FLOAT);
};
void board_late_initialize(void) {
}
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
// Turn LED on or off
void board_led_write(bool state)
{
board_gpio_write(LED_PIN, state);
}
// Get the current state of button
// a '1' means active (pressed), a '0' means inactive.
uint32_t board_button_read(void)
{
if (board_gpio_read(BUTTON_PIN))
{
return 0;
}
return 1;
}
// Get characters from UART
int board_uart_read(uint8_t *buf, int len)
{
int r = read(0, buf, len);
return r;
}
// Send characters to UART
int board_uart_write(void const *buf, int len)
{
int r = write(1, buf, len);
return r;
}
// Get current milliseconds
uint32_t tusb_time_millis_api(void)
{
struct timespec tp;
/* Wait until RTC is available */
while (g_rtc_enabled == false);
if (clock_gettime(CLOCK_MONOTONIC, &tp))
{
return 0;
}
return (((uint64_t)tp.tv_sec) * 1000 + tp.tv_nsec / 1000000);
}
================================================
FILE: hw/bsp/cxd56/family.cmake
================================================
include_guard()
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
set(SDK_DIR ${TOP}/hw/mcu/sony/cxd56/spresense-exported-sdk)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS CXD56 CACHE INTERNAL "")
# Detect platform for mkspk tool
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk)
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk)
else()
set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk.exe)
endif()
#------------------------------------
# Startup & Linker script
#------------------------------------
set(LD_FILE_GNU ${SDK_DIR}/nuttx/scripts/ramconfig.ld)
set(LD_FILE_Clang ${LD_FILE_GNU})
#------------------------------------
# BOARD Target
#------------------------------------
function(family_add_board BOARD_TARGET)
# Spresense uses NuttX libraries
add_library(${BOARD_TARGET} INTERFACE)
target_include_directories(${BOARD_TARGET} INTERFACE
${SDK_DIR}/nuttx/include
${SDK_DIR}/nuttx/arch
${SDK_DIR}/nuttx/arch/chip
${SDK_DIR}/nuttx/arch/os
${SDK_DIR}/sdk/include
)
target_compile_definitions(${BOARD_TARGET} INTERFACE
CONFIG_HAVE_DOUBLE
main=spresense_main
)
target_compile_options(${BOARD_TARGET} INTERFACE
-pipe
-std=gnu11
-fno-builtin
-fno-strength-reduce
-fomit-frame-pointer
-Wno-error=undef
-Wno-error=cast-align
-Wno-error=unused-parameter
-Wno-error=shadow
-Wno-error=redundant-decls
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_CXD56)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/sony/cxd56/dcd_cxd56.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
target_link_libraries(${TARGET} PUBLIC
${SDK_DIR}/nuttx/libs/libapps.a
${SDK_DIR}/nuttx/libs/libnuttx.a
gcc # Compiler runtime support for FP operations like __aeabi_dmul
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-Xlinker --entry=__start
-nostartfiles
-nodefaultlibs
-Wl,--gc-sections
-u spresense_main
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
-Xlinker --entry=__start
-nostartfiles
-nodefaultlibs
-u spresense_main
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Build mkspk tool
add_custom_command(OUTPUT ${MKSPK}
COMMAND $(MAKE) -C ${TOP}/hw/mcu/sony/cxd56/mkspk
COMMENT "Building mkspk tool"
)
# Create .spk file
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.spk
COMMAND ${MKSPK} -c 2 $ nuttx ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.spk
DEPENDS ${TARGET} ${MKSPK}
COMMENT "Creating ${TARGET}.spk"
)
endfunction()
================================================
FILE: hw/bsp/cxd56/family.mk
================================================
include $(TOP)/$(BOARD_PATH)/board.mk
# Platforms are: Linux, Darwin, MSYS, CYGWIN
PLATFORM := $(firstword $(subst _, ,$(shell uname -s 2>/dev/null)))
ifeq ($(PLATFORM),Darwin)
# macOS
MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk
else ifeq ($(PLATFORM),Linux)
# Linux
MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk
else
# Cygwin/MSYS2
MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk.exe
endif
CFLAGS += \
-DCONFIG_HAVE_DOUBLE \
-Dmain=spresense_main \
-pipe \
-std=gnu11 \
-fno-strength-reduce \
-fomit-frame-pointer \
-Wno-error=undef \
-Wno-error=cast-align \
-Wno-error=unused-parameter \
-DCFG_TUSB_MCU=OPT_MCU_CXD56 \
CPU_CORE ?= cortex-m4
# suppress following warnings from mcu driver
# lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration
CFLAGS += -Wno-error=shadow -Wno-error=redundant-decls
LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
SPRESENSE_SDK = $(TOP)/hw/mcu/sony/cxd56/spresense-exported-sdk
SRC_C += src/portable/sony/cxd56/dcd_cxd56.c
INC += \
$(SPRESENSE_SDK)/nuttx/include \
$(SPRESENSE_SDK)/nuttx/arch \
$(SPRESENSE_SDK)/nuttx/arch/chip \
$(SPRESENSE_SDK)/nuttx/arch/os \
$(SPRESENSE_SDK)/sdk/include \
$(TOP)/$(BOARD_PATH)
LIBS += \
$(SPRESENSE_SDK)/nuttx/libs/libapps.a \
$(SPRESENSE_SDK)/nuttx/libs/libnuttx.a \
LD_FILE = hw/mcu/sony/cxd56/spresense-exported-sdk/nuttx/scripts/ramconfig.ld
LDFLAGS += \
-Xlinker --entry=__start \
-nostartfiles \
-nodefaultlibs \
-Wl,--gc-sections \
-u spresense_main
$(MKSPK): $(BUILD)/$(PROJECT).elf
$(MAKE) -C $(TOP)/hw/mcu/sony/cxd56/mkspk
$(BUILD)/$(PROJECT).spk: $(MKSPK)
@echo CREATE $@
@$(MKSPK) -c 2 $(BUILD)/$(PROJECT).elf nuttx $@
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F
================================================
FILE: hw/bsp/da1469x/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
#include "DA1469xAB.h"
#endif
/* Cortex M23/M33 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE (1024)
#define configRUN_FREERTOS_SECURE_ONLY 1
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configRECORD_STACK_HIGH_ADDRESS 1
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header
#define configPRIO_BITS 4
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<
#include
#define LED_STATE_OFF (1-LED_STATE_ON)
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_IRQHandler(void) {
tud_int_handler(0);
}
// DA146xx driver function that must be called whenever VBUS changes.
extern void tusb_vbus_changed(bool present);
#if defined(NEED_VBUS_MONITOR) && CFG_TUD_ENABLED
// VBUS change interrupt handler
void VBUS_IRQHandler(void) {
bool present = (CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0;
// Clear VBUS interrupt
CRG_TOP->VBUS_IRQ_CLEAR_REG = 1;
tusb_vbus_changed(present);
}
#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
void UnhandledIRQ(void) {
CRG_TOP->SYS_CTRL_REG = 0x80;
__BKPT(1);
while (1);
}
void board_init(void) {
// LED
hal_gpio_init_out(LED_PIN, LED_STATE_ON);
hal_gpio_init_out(1, 0);
hal_gpio_init_out(2, 0);
hal_gpio_init_out(3, 0);
hal_gpio_init_out(4, 0);
hal_gpio_init_out(5, 0);
// Button
hal_gpio_init_in(BUTTON_PIN, BUTTON_STATE_ACTIVE ? HAL_GPIO_PULL_DOWN : HAL_GPIO_PULL_UP);
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
#if CFG_TUD_ENABLED
#ifdef NEED_VBUS_MONITOR
// Setup interrupt for both connect and disconnect
CRG_TOP->VBUS_IRQ_MASK_REG = CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_FALL_Msk |
CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_RISE_Msk;
NVIC_SetPriority(VBUS_IRQn, 2);
// Trigger interrupt at the start to inform driver about VBUS state at start
// otherwise it could go unnoticed.
NVIC_SetPendingIRQ(VBUS_IRQn);
NVIC_EnableIRQ(VBUS_IRQn);
#else
// This board is USB powered there is no need to monitor VBUS line. Notify driver that VBUS is present.
tusb_vbus_changed(true);
#endif
/* Setup USB IRQ */
NVIC_SetPriority(USB_IRQn, 2);
NVIC_EnableIRQ(USB_IRQn);
/* Use PLL96 / 2 clock not HCLK */
CRG_TOP->CLK_CTRL_REG &= ~CRG_TOP_CLK_CTRL_REG_USB_CLK_SRC_Msk;
mcu_gpio_set_pin_function(14, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
mcu_gpio_set_pin_function(15, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
#endif
}
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
void board_led_write(bool state) {
hal_gpio_write(LED_PIN, state ? LED_STATE_ON : LED_STATE_OFF);
}
uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == hal_gpio_read(BUTTON_PIN);
}
int board_uart_read(uint8_t* buf, int len) {
(void) buf;
(void) len;
return 0;
}
int board_uart_write(void const* buf, int len) {
(void) buf;
(void) len;
return 0;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void) {
system_ticks++;
}
uint32_t tusb_time_millis_api(void) {
return system_ticks;
}
#endif
================================================
FILE: hw/bsp/da1469x/family.cmake
================================================
include_guard()
set(MCU_DIR ${TOP}/hw/mcu/dialog/da1469x)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
set(CMAKE_SYSTEM_CPU cortex-m33-nodsp CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS DA1469X CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
if (NOT DEFINED LD_FILE_GNU)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/da1469x.ld)
endif ()
if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID})
set(STARTUP_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/gcc_startup_da1469x.S)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
endif ()
#------------------------------------
# Board Target
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${MCU_DIR}/src/system_da1469x.c
${MCU_DIR}/src/da1469x_clock.c
${MCU_DIR}/src/hal_gpio.c
)
target_compile_options(${BOARD_TARGET} PUBLIC -mthumb-interwork)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CORE_M33
CFG_TUD_ENDPOINT0_SIZE=8
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
${MCU_DIR}/include
${MCU_DIR}/SDK_10.0.8.105/sdk/bsp/include
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_flash_jlink_dialog TARGET)
set(JLINKEXE JLinkExe)
set(JLINK_IF swd)
# mkimage from sdk
set(MKIMAGE $ENV{HOME}/code/tinyusb-mcu-driver/dialog/SDK_10.0.8.105/binaries/mkimage)
file(GENERATE OUTPUT $/version.h
CONTENT "#define SW_VERSION \"v_1.0.0.1\"
#define SW_VERSION_DATE \"2024-07-17 17:55\""
)
file(GENERATE OUTPUT $/${TARGET}.jlink
CONTENT "r
halt
loadfile $/${TARGET}-image.bin 0x16000000
r
go
exit"
)
add_custom_target(${TARGET}-image
DEPENDS ${TARGET}
COMMAND ${MKIMAGE} da1469x $/${TARGET}.bin $/version.h $/${TARGET}.bin.img
COMMAND cp ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/product_header.dump $/${TARGET}-image.bin
COMMAND cat $/${TARGET}.bin.img >> $/${TARGET}-image.bin
)
add_custom_target(${TARGET}-jlink
DEPENDS ${TARGET}-image
COMMAND ${JLINKEXE} -device ${JLINK_DEVICE} -if ${JLINK_IF} -JTAGConf -1,-1 -speed auto -CommandFile $/${TARGET}.jlink
)
endfunction()
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_DA1469X)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/dialog/da146xx/dcd_da146xx.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
--specs=nosys.specs --specs=nano.specs
-nostartfiles
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes")
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink_dialog(${TARGET})
endfunction()
================================================
FILE: hw/bsp/da1469x/family.mk
================================================
MCU_DIR = hw/mcu/dialog/da1469x
include $(TOP)/$(BOARD_PATH)/board.mk
CFLAGS += \
-flto \
-mthumb \
-mthumb-interwork \
-mabi=aapcs \
-mcpu=cortex-m33+nodsp \
-mfloat-abi=hard \
-mfpu=fpv5-sp-d16 \
-DCORE_M33 \
-DCFG_TUSB_MCU=OPT_MCU_DA1469X \
-DCFG_TUD_ENDPOINT0_SIZE=8\
LDFLAGS_GCC += \
-nostdlib \
--specs=nosys.specs --specs=nano.specs
# All source paths should be relative to the top level.
LD_FILE = $(FAMILY_PATH)/linker/da1469x.ld
# While this is for da1469x chip, there is chance that da1468x chip family will also work
SRC_C += \
src/portable/dialog/da146xx/dcd_da146xx.c \
${MCU_DIR}/src/system_da1469x.c \
${MCU_DIR}/src/da1469x_clock.c \
${MCU_DIR}/src/hal_gpio.c \
SRC_S += $(FAMILY_PATH)/gcc_startup_da1469x.S
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/${MCU_DIR}/include \
$(TOP)/${MCU_DIR}/SDK_10.0.8.105/sdk/bsp/include
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure
# flash using jlink but with some twists
flash: flash-dialog
# SDK_BINARY_PATH is the path to the SDK binary files
SDK_BINARY_PATH = $(HOME)/code/tinyusb-mcu-driver/dialog/SDK_10.0.8.105/binaries
MKIMAGE = $(SDK_BINARY_PATH)/mkimage
$(BUILD)/$(PROJECT)-image.bin: $(BUILD)/$(PROJECT).bin
@echo '#define SW_VERSION "v_1.0.0.1"' >$(BUILD)/version.h
@echo '#define SW_VERSION_DATE "'`date +"%Y-%m-%d %H:%M"`'"' >> $(BUILD)/version.h
$(MKIMAGE) da1469x $^ $(BUILD)/version.h $^.img
cp $(TOP)/$(FAMILY_PATH)/product_header.dump $(BUILD)/$(PROJECT)-image.bin
cat $^.img >> $(BUILD)/$(PROJECT)-image.bin
flash-dialog: $(BUILD)/$(PROJECT)-image.bin
@echo r > $(BUILD)/$(BOARD).jlink
@echo halt >> $(BUILD)/$(BOARD).jlink
@echo loadfile $^ 0x16000000 >> $(BUILD)/$(BOARD).jlink
@echo r >> $(BUILD)/$(BOARD).jlink
@echo go >> $(BUILD)/$(BOARD).jlink
@echo exit >> $(BUILD)/$(BOARD).jlink
$(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $(BUILD)/$(BOARD).jlink
================================================
FILE: hw/bsp/da1469x/gcc_startup_da1469x.S
================================================
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "syscfg/syscfg.h"
.syntax unified
.arch armv7-m
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0xC00
#endif
.equ SYS_CTRL_REG, 0x50000024
.equ CACHE_FLASH_REG, 0x100C0040
.equ RESET_STAT_REG, 0x500000BC
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
.section .heap
.align 3
#ifdef __HEAP_SIZE
.equ Heap_Size, __HEAP_SIZE
#else
.equ Heap_Size, 0
#endif
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.if Heap_Size
.space Heap_Size
.endif
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .isr_vector
.align 2
.globl __isr_vector
__isr_vector:
.long __StackTop
.long Reset_Handler
/* Cortex-M33 interrupts */
.long NMI_Handler
.long HardFault_Handler
.long MemoryManagement_Handler
.long BusFault_Handler
.long UsageFault_Handler
.long SecureFault_Handler
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler
.long DebugMonitor_Handler
.long 0 /* Reserved */
.long PendSV_Handler
.long SysTick_Handler
/* DA1469x interrupts */
.long SENSOR_NODE_IRQHandler
.long DMA_IRQHandler
.long CHARGER_STATE_IRQHandler
.long CHARGER_ERROR_IRQHandler
.long CMAC2SYS_IRQHandler
.long UART_IRQHandler
.long UART2_IRQHandler
.long UART3_IRQHandler
.long I2C_IRQHandler
.long I2C2_IRQHandler
.long SPI_IRQHandler
.long SPI2_IRQHandler
.long PCM_IRQHandler
.long SRC_IN_IRQHandler
.long SRC_OUT_IRQHandler
.long USB_IRQHandler
.long TIMER_IRQHandler
.long TIMER2_IRQHandler
.long RTC_IRQHandler
.long KEY_WKUP_GPIO_IRQHandler
.long PDC_IRQHandler
.long VBUS_IRQHandler
.long MRM_IRQHandler
.long MOTOR_CONTROLLER_IRQHandler
.long TRNG_IRQHandler
.long DCDC_IRQHandler
.long XTAL32M_RDY_IRQHandler
.long ADC_IRQHandler
.long ADC2_IRQHandler
.long CRYPTO_IRQHandler
.long CAPTIMER1_IRQHandler
.long RFDIAG_IRQHandler
.long LCD_CONTROLLER_IRQHandler
.long PLL_LOCK_IRQHandler
.long TIMER3_IRQHandler
.long TIMER4_IRQHandler
.long LRA_IRQHandler
.long RTC_EVENT_IRQHandler
.long GPIO_P0_IRQHandler
.long GPIO_P1_IRQHandler
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.size __isr_vector, . - __isr_vector
.text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Make sure interrupt vector is remapped at 0x0 */
ldr r1, =SYS_CTRL_REG
ldrh r2, [r1, #0]
orrs r2, r2, #8
strh r2, [r1, #0]
#if !MYNEWT_VAL(RAM_RESIDENT)
/*
* Flash is remapped at 0x0 with an offset, i.e. 0x0 does not correspond to
* 0x16000000 but to start of an image on flash. This is calculated from product
* header by 1st state bootloader and configured in CACHE_FLASH_REG. We need to
* retrieve proper offset value for calculations later.
*/
ldr r1, =CACHE_FLASH_REG
ldr r4, [r1, #0]
mov r2, r4
mov r3, #0xFFFF
bic r4, r4, r3 /* CACHE_FLASH_REG[FLASH_REGION_BASE] */
mov r3, #0xFFF0
and r2, r2, r3 /* CACHE_FLASH_REG[FLASH_REGION_OFFSET] */
lsr r2, r2, #2
orr r4, r4, r2
/* Copy ISR vector from flash to RAM */
ldr r1, =__isr_vector_start /* src ptr */
ldr r2, =__isr_vector_end /* src end */
ldr r3, =__intvect_start__ /* dst ptr */
/* Make sure we copy from QSPIC address range, not from remapped range */
cmp r1, r4
itt lt
addlt r1, r1, r4
addlt r2, r2, r4
.loop_isr_copy:
cmp r1, r2
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r3], #4
blt .loop_isr_copy
/* Copy QSPI code from flash to RAM */
ldr r1, =__text_ram_addr /* src ptr */
ldr r2, =__text_ram_start__ /* ptr */
ldr r3, =__text_ram_end__ /* dst end */
.loop_code_text_ram_copy:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .loop_code_text_ram_copy
/* Copy data from flash to RAM */
ldr r1, =__etext /* src ptr */
ldr r2, =__data_start__ /* dst ptr */
ldr r3, =__data_end__ /* dst end */
.loop_data_copy:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .loop_data_copy
#endif
/* Clear BSS */
movs r0, 0
ldr r1, =__bss_start__
ldr r2, =__bss_end__
.loop_bss_clear:
cmp r1, r2
itt lt
strlt r0, [r1], #4
blt .loop_bss_clear
ldr r0, =__HeapBase
ldr r1, =__HeapLimit
/* Call static constructors */
bl __libc_init_array
bl SystemInit
bl main
.pool
.size Reset_Handler, . - Reset_Handler
/* Default interrupt handler */
.type Default_Handler, %function
Default_Handler:
ldr r1, =SYS_CTRL_REG
ldrh r2, [r1, #0]
orrs r2, r2, #0x80 /* DEBUGGER_ENABLE */
strh r2, [r1, #0]
b .
.size Default_Handler, . - Default_Handler
/* Default handlers for all interrupts */
.macro IRQ handler
.weak \handler
.set \handler, Default_Handler
.endm
/* Cortex-M33 interrupts */
IRQ NMI_Handler
IRQ HardFault_Handler
IRQ MemoryManagement_Handler
IRQ BusFault_Handler
IRQ UsageFault_Handler
IRQ SecureFault_Handler
IRQ SVC_Handler
IRQ DebugMonitor_Handler
IRQ PendSV_Handler
IRQ SysTick_Handler
/* DA1469x interrupts */
IRQ SENSOR_NODE_IRQHandler
IRQ DMA_IRQHandler
IRQ CHARGER_STATE_IRQHandler
IRQ CHARGER_ERROR_IRQHandler
IRQ CMAC2SYS_IRQHandler
IRQ UART_IRQHandler
IRQ UART2_IRQHandler
IRQ UART3_IRQHandler
IRQ I2C_IRQHandler
IRQ I2C2_IRQHandler
IRQ SPI_IRQHandler
IRQ SPI2_IRQHandler
IRQ PCM_IRQHandler
IRQ SRC_IN_IRQHandler
IRQ SRC_OUT_IRQHandler
IRQ USB_IRQHandler
IRQ TIMER_IRQHandler
IRQ TIMER2_IRQHandler
IRQ RTC_IRQHandler
IRQ KEY_WKUP_GPIO_IRQHandler
IRQ PDC_IRQHandler
IRQ VBUS_IRQHandler
IRQ MRM_IRQHandler
IRQ MOTOR_CONTROLLER_IRQHandler
IRQ TRNG_IRQHandler
IRQ DCDC_IRQHandler
IRQ XTAL32M_RDY_IRQHandler
IRQ ADC_IRQHandler
IRQ ADC2_IRQHandler
IRQ CRYPTO_IRQHandler
IRQ CAPTIMER1_IRQHandler
IRQ RFDIAG_IRQHandler
IRQ LCD_CONTROLLER_IRQHandler
IRQ PLL_LOCK_IRQHandler
IRQ TIMER3_IRQHandler
IRQ TIMER4_IRQHandler
IRQ LRA_IRQHandler
IRQ RTC_EVENT_IRQHandler
IRQ GPIO_P0_IRQHandler
IRQ GPIO_P1_IRQHandler
IRQ RESERVED40_IRQHandler
IRQ RESERVED41_IRQHandler
IRQ RESERVED42_IRQHandler
IRQ RESERVED43_IRQHandler
IRQ RESERVED44_IRQHandler
IRQ RESERVED45_IRQHandler
IRQ RESERVED46_IRQHandler
IRQ RESERVED47_IRQHandler
.end
================================================
FILE: hw/bsp/da1469x/linker/da1469x.ld
================================================
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
MEMORY
{
/*
* Flash is remapped at 0x0 by 1st stage bootloader, but this is done with
* an offset derived from image header thus it is safer to use remapped
* address space at 0x0 instead of QSPI_M address space at 0x16000000.
* Bootloader partition is 32K, but 9K is currently reserved for product
* header (8K) and image header (1K).
* First 512 bytes of SYSRAM are remapped at 0x0 and used as ISR vector
* (there's no need to reallocate ISR vector) and thus cannot be used by
* application.
*/
FLASH (r) : ORIGIN = (0x00000000), LENGTH = (1024 * 1024)
RAM (rw) : ORIGIN = (0x20000000), LENGTH = (512 * 1024)
}
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __HeapBase
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
* __bssnz_start__
* __bssnz_end__
*/
ENTRY(Reset_Handler)
SECTIONS
{
__text = .;
.text :
{
__isr_vector_start = .;
KEEP(*(.isr_vector))
/* ISR vector shall have exactly 512 bytes */
. = __isr_vector_start + 0x200;
__isr_vector_end = .;
*(.text)
*(.text.*)
*(.libcmac.rom)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
*(.eh_frame*)
. = ALIGN(4);
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} > FLASH
__exidx_start = .;
.ARM :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
. = ALIGN(4);
} > FLASH
__exidx_end = .;
.intvect :
{
. = ALIGN(4);
__intvect_start__ = .;
. = . + (__isr_vector_end - __isr_vector_start);
. = ALIGN(4);
} > RAM
.sleep_state (NOLOAD) :
{
. = ALIGN(4);
*(sleep_state)
} > RAM
/* This section will be zeroed by RTT package init */
.rtt (NOLOAD):
{
. = ALIGN(4);
*(.rtt)
. = ALIGN(4);
} > RAM
__text_ram_addr = LOADADDR(.text_ram);
.text_ram :
{
. = ALIGN(4);
__text_ram_start__ = .;
*(.text_ram*)
. = ALIGN(4);
__text_ram_end__ = .;
} > RAM AT > FLASH
__etext = LOADADDR(.data);
.data :
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
*(.preinit_array)
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
*(SORT(.init_array.*))
*(.init_array)
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE_HIDDEN (__fini_array_end = .);
*(.jcr)
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM AT > FLASH
.bssnz :
{
. = ALIGN(4);
__bssnz_start__ = .;
*(.bss.core.nz*)
. = ALIGN(4);
__bssnz_end__ = .;
} > RAM
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.cmac (NOLOAD) :
{
. = ALIGN(0x400);
*(.libcmac.ram)
} > RAM
/* Heap starts after BSS */
. = ALIGN(8);
__HeapBase = .;
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
*(.stack*)
} > RAM
_ram_start = ORIGIN(RAM);
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Top of head is the bottom of the stack */
__HeapLimit = __StackLimit;
end = __HeapLimit;
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__HeapBase <= __HeapLimit, "region RAM overflowed with stack")
/* Check that intvect is at the beginning of RAM */
ASSERT(__intvect_start__ == ORIGIN(RAM), "intvect is not at beginning of RAM")
}
================================================
FILE: hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h
================================================
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
// skip if included from IAR assembler
#ifndef __IASMARM__
#include "em_device.h"
#endif
/* Cortex-M4F port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE (1024)
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 4
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configRECORD_STACK_HIGH_ADDRESS 1
#define configUSE_TRACE_FACILITY 1 // legacy trace
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 0
#define INCLUDE_xTimerPendFunctionCall 0
/* FreeRTOS hooks to NVIC vectors */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define vPortSVCHandler SVC_Handler
//--------------------------------------------------------------------+
// Interrupt nesting behavior configuration.
//--------------------------------------------------------------------+
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header
// EFM32GG12B has 3 priority bits
#define configPRIO_BITS 3
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<PWRCTRL = (immediate_switch ? EMU_PWRCTRL_IMMEDIATEPWRSWITCH : 0) | EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD;
}
static void emu_reg_init(float target_voltage)
{
if(target_voltage < 2300.f || target_voltage >= 3800.f)
return;
uint8_t level = ((target_voltage - 2300.f) / 100.f);
EMU->R5VCTRL = EMU_R5VCTRL_INPUTMODE_AUTO;
EMU->R5VOUTLEVEL = level; /* Reg output to 3.3V*/
}
static void emu_dcdc_init(float target_voltage, float max_ln_current, float max_lp_current, float max_reverse_current)
{
if(target_voltage < 1800.f || target_voltage >= 3000.f)
return;
if(max_ln_current <= 0.f || max_ln_current > 200.f)
return;
if(max_lp_current <= 0.f || max_lp_current > 10000.f)
return;
if(max_reverse_current < 0.f || max_reverse_current > 160.f)
return;
// Low Power & Low Noise current limit
uint8_t lp_bias = 0;
if(max_lp_current < 75.f)
lp_bias = 0;
else if(max_lp_current < 500.f)
lp_bias = 1;
else if(max_lp_current < 2500.f)
lp_bias = 2;
else
lp_bias = 3;
EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_LPCMPBIASEM234H_MASK) | ((uint32_t)lp_bias << _EMU_DCDCMISCCTRL_LPCMPBIASEM234H_SHIFT);
EMU->DCDCMISCCTRL |= EMU_DCDCMISCCTRL_LNFORCECCM; // Force CCM to prevent reverse current
EMU->DCDCLPCTRL |= EMU_DCDCLPCTRL_LPVREFDUTYEN; // Enable duty cycling of the bias for LP mode
EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK) | 4; // Set RCO Band to 7MHz
uint8_t fet_count = 0;
if(max_ln_current < 20.f)
fet_count = 4;
else if(max_ln_current >= 20.f && max_ln_current < 40.f)
fet_count = 8;
else
fet_count = 16;
EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_NFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT);
EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_PFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT);
uint8_t ln_current_limit = (((max_ln_current + 40.f) * 1.5f) / (5.f * fet_count)) - 1;
uint8_t lp_current_limit = 1; // Recommended value
EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LNCLIMILIMSEL_MASK | _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_MASK)) | ((uint32_t)ln_current_limit << _EMU_DCDCMISCCTRL_LNCLIMILIMSEL_SHIFT) | ((uint32_t)lp_current_limit << _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_SHIFT);
uint8_t z_det_limit = ((max_reverse_current + 40.f) * 1.5f) / (2.5f * fet_count);
EMU->DCDCZDETCTRL = (EMU->DCDCZDETCTRL & ~_EMU_DCDCZDETCTRL_ZDETILIMSEL_MASK) | ((uint32_t)z_det_limit << _EMU_DCDCZDETCTRL_ZDETILIMSEL_SHIFT);
EMU->DCDCCLIMCTRL |= EMU_DCDCCLIMCTRL_BYPLIMEN; // Enable bypass current limiter to prevent overcurrent when switching modes
// Output Voltage
if(target_voltage > 1800.f)
{
float max_vout = 3000.f;
float min_vout = 1800.f;
float diff_vout = max_vout - min_vout;
uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_SHIFT;
uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_SHIFT;
uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout;
ln_vref += ln_vref_low;
EMU->DCDCLNVCTRL = (ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT) | EMU_DCDCLNVCTRL_LNATT;
uint8_t lp_vref_low = 0;
uint8_t lp_vref_high = 0;
switch(lp_bias)
{
case 0:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT;
}
break;
case 1:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT;
}
break;
case 2:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT;
}
break;
case 3:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT;
}
break;
}
uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout;
lp_vref += lp_vref_low;
EMU->DCDCLPVCTRL = (lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT) | EMU_DCDCLPVCTRL_LPATT;
}
else
{
float max_vout = 1800.f;
float min_vout = 1200.f;
float diff_vout = max_vout - min_vout;
uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_SHIFT;
uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_SHIFT;
uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout;
ln_vref += ln_vref_low;
EMU->DCDCLNVCTRL = ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT;
uint8_t lp_vref_low = 0;
uint8_t lp_vref_high = 0;
switch(lp_bias)
{
case 0:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT;
}
break;
case 1:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT;
}
break;
case 2:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT;
}
break;
case 3:
{
lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT;
lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT;
}
break;
}
uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout;
lp_vref += lp_vref_low;
EMU->DCDCLPVCTRL = lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT;
}
EMU->DCDCLPCTRL = (EMU->DCDCLPCTRL & ~_EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_MASK) | (((DEVINFO->DCDCLPCMPHYSSEL1 & (((uint32_t)0xFF) << (lp_bias * 8))) >> (lp_bias * 8)) << _EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_SHIFT);
while(EMU->DCDCSYNC & EMU_DCDCSYNC_DCDCCTRLBUSY); // Wait for configuration to write
// Calibration
//EMU->DCDCLNCOMPCTRL = 0x57204077; // Compensation for 1uF DCDC capacitor
EMU->DCDCLNCOMPCTRL = 0xB7102137; // Compensation for 4.7uF DCDC capacitor
// Enable DCDC converter
EMU->DCDCCTRL = EMU_DCDCCTRL_DCDCMODEEM4_EM4LOWPOWER | EMU_DCDCCTRL_DCDCMODEEM23_EM23LOWPOWER | EMU_DCDCCTRL_DCDCMODE_LOWNOISE;
// Switch digital domain to DVDD
EMU->PWRCTRL = EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD;
}
static void cmu_hfxo_startup_calib(uint16_t ib_trim, uint16_t c_tune)
{
if(CMU->STATUS & CMU_STATUS_HFXOENS)
return;
CMU->HFXOSTARTUPCTRL = (CMU->HFXOSTARTUPCTRL & ~(_CMU_HFXOSTARTUPCTRL_CTUNE_MASK | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT) & _CMU_HFXOSTARTUPCTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK);
}
static void cmu_hfxo_steady_calib(uint16_t ib_trim, uint16_t c_tune)
{
if(CMU->STATUS & CMU_STATUS_HFXOENS)
return;
CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL & ~(_CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK);
}
static void cmu_hfrco_calib(uint32_t calibration)
{
if(CMU->STATUS & CMU_STATUS_DPLLENS)
return;
while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY);
CMU->HFRCOCTRL = calibration;
while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY);
}
static void cmu_ushfrco_calib(uint8_t enable, uint32_t calibration)
{
if(CMU->USBCRCTRL & CMU_USBCRCTRL_USBCREN)
return;
if(!enable)
{
CMU->OSCENCMD = CMU_OSCENCMD_USHFRCODIS;
while(CMU->STATUS & CMU_STATUS_USHFRCOENS);
return;
}
while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY);
CMU->USHFRCOCTRL = calibration | CMU_USHFRCOCTRL_FINETUNINGEN;
while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY);
if(enable && !(CMU->STATUS & CMU_STATUS_USHFRCOENS))
{
CMU->OSCENCMD = CMU_OSCENCMD_USHFRCOEN;
while(!(CMU->STATUS & CMU_STATUS_USHFRCORDY));
}
}
static void cmu_auxhfrco_calib(uint8_t enable, uint32_t calibration)
{
if(!enable)
{
CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCODIS;
while(CMU->STATUS & CMU_STATUS_AUXHFRCOENS);
return;
}
while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY);
CMU->AUXHFRCOCTRL = calibration;
while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY);
if(enable && !(CMU->STATUS & CMU_STATUS_AUXHFRCOENS))
{
CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY));
}
}
static void cmu_init(void)
{
// Change SDIO clock to HFXO if HFRCO selected and disable it
CMU->SDIOCTRL = CMU_SDIOCTRL_SDIOCLKDIS | CMU_SDIOCTRL_SDIOCLKSEL_HFXO;
while(CMU->STATUS & CMU_STATUS_SDIOCLKENS);
// Change QSPI clock to HFXO if HFRCO selected and disable it
CMU->QSPICTRL = CMU_QSPICTRL_QSPI0CLKDIS | CMU_QSPICTRL_QSPI0CLKSEL_HFXO;
while(CMU->STATUS & CMU_STATUS_QSPI0CLKENS);
// Disable DPLL if enabled
if(CMU->STATUS & CMU_STATUS_DPLLENS)
{
CMU->OSCENCMD = CMU_OSCENCMD_DPLLDIS;
while(CMU->STATUS & CMU_STATUS_DPLLENS);
}
// Disable HFXO if enabled
if(CMU->STATUS & CMU_STATUS_HFXOENS)
{
CMU->OSCENCMD = CMU_OSCENCMD_HFXODIS;
while(CMU->STATUS & CMU_STATUS_HFXOENS);
}
// Setup HFXO
CMU->HFXOCTRL = CMU_HFXOCTRL_PEAKDETMODE_AUTOCMD | CMU_HFXOCTRL_MODE_XTAL;
CMU->HFXOCTRL1 = CMU_HFXOCTRL1_PEAKDETTHR_DEFAULT;
CMU->HFXOSTEADYSTATECTRL |= CMU_HFXOSTEADYSTATECTRL_PEAKMONEN;
CMU->HFXOTIMEOUTCTRL = (7 << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT) | (8 << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT) | (12 << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT);
// Enable HFXO and wait for it to be ready
CMU->OSCENCMD = CMU_OSCENCMD_HFXOEN;
while(!(CMU->STATUS & CMU_STATUS_HFXORDY));
// Switch main clock to HFXO and wait for it to be selected
CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFXO;
while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFXO);
// Calibrate HFRCO for 72MHz and enable tuning by PLL
cmu_hfrco_calib((DEVINFO->HFRCOCAL16) | CMU_HFRCOCTRL_FINETUNINGEN);
// Setup the PLL
CMU->DPLLCTRL = CMU_DPLLCTRL_REFSEL_HFXO | CMU_DPLLCTRL_AUTORECOVER | CMU_DPLLCTRL_EDGESEL_RISE | CMU_DPLLCTRL_MODE_FREQLL;
// 72MHz = 50MHz (HFXO) * 1.44 (144/100)
CMU->DPLLCTRL1 = (143 << _CMU_DPLLCTRL1_N_SHIFT) | (99 << _CMU_DPLLCTRL1_M_SHIFT); // fHFRCO = fHFXO * (N + 1) / (M + 1)
// Enable the DPLL and wait for it to be ready
CMU->OSCENCMD = CMU_OSCENCMD_DPLLEN;
while(!(CMU->STATUS & CMU_STATUS_DPLLRDY));
// Config peripherals for the new frequency (freq > 32MHz)
CMU->CTRL |= CMU_CTRL_WSHFLE;
// Set prescalers
CMU->HFPRESC = CMU_HFPRESC_HFCLKLEPRESC_DIV2 | CMU_HFPRESC_PRESC_NODIVISION;
CMU->HFBUSPRESC = 1 << _CMU_HFBUSPRESC_PRESC_SHIFT;
CMU->HFCOREPRESC = 0 << _CMU_HFCOREPRESC_PRESC_SHIFT;
CMU->HFPERPRESC = 1 << _CMU_HFPERPRESC_PRESC_SHIFT;
CMU->HFEXPPRESC = 0 << _CMU_HFEXPPRESC_PRESC_SHIFT;
CMU->HFPERPRESCB = 0 << _CMU_HFPERPRESCB_PRESC_SHIFT;
CMU->HFPERPRESCC = 1 << _CMU_HFPERPRESCC_PRESC_SHIFT;
// Enable clock to peripherals
CMU->CTRL |= CMU_CTRL_HFPERCLKEN;
// Switch main clock to HFRCO and wait for it to be selected
CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCO;
while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFRCO);
// LFA Clock
CMU->LFACLKSEL = CMU_LFACLKSEL_LFA_LFRCO;
// LFB Clock
CMU->LFBCLKSEL = CMU_LFBCLKSEL_LFB_LFRCO;
// LFC Clock
CMU->LFCCLKSEL = CMU_LFCCLKSEL_LFC_LFRCO;
// LFE Clock
CMU->LFECLKSEL = CMU_LFECLKSEL_LFE_ULFRCO;
}
static void systick_init(void)
{
SysTick->LOAD = (72000000 / 1000) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
SCB->SHP[11] = 7 << (8 - __NVIC_PRIO_BITS); // Set priority 3,1 (min)
}
static void gpio_init(void)
{
CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO;
// NC - Not Connected (not available in mcu package)
// NR - Not routed (no routing to pin on pcb, floating)
// NU - Not used (not currently in use)
// Port A
GPIO->P[0].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
| GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
GPIO->P[0].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU
| GPIO_P_MODEL_MODE1_DISABLED // NU
| GPIO_P_MODEL_MODE2_DISABLED // NU
| GPIO_P_MODEL_MODE3_DISABLED // NU
| GPIO_P_MODEL_MODE4_DISABLED // NU
| GPIO_P_MODEL_MODE5_DISABLED // NU
| GPIO_P_MODEL_MODE6_DISABLED // NU
| GPIO_P_MODEL_MODE7_DISABLED; // NC
GPIO->P[0].MODEH = GPIO_P_MODEH_MODE8_DISABLED // GPIO - MIC_ENABLE
| GPIO_P_MODEH_MODE9_DISABLED // NC
| GPIO_P_MODEH_MODE10_DISABLED // NC
| GPIO_P_MODEH_MODE11_DISABLED // NC
| GPIO_P_MODEH_MODE12_WIREDAND // LED0R
| GPIO_P_MODEH_MODE13_WIREDAND // LED0B
| GPIO_P_MODEH_MODE14_WIREDAND // LED0G
| GPIO_P_MODEH_MODE15_DISABLED; // NU
GPIO->P[0].DOUT = 0x7000; // Leds off By default
GPIO->P[0].OVTDIS = 0;
// Port B
GPIO->P[1].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
| GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
GPIO->P[1].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC
| GPIO_P_MODEL_MODE1_DISABLED // NC
| GPIO_P_MODEL_MODE2_DISABLED // NC
| GPIO_P_MODEL_MODE3_DISABLED // NU
| GPIO_P_MODEL_MODE4_DISABLED // NU
| GPIO_P_MODEL_MODE5_DISABLED // NU
| GPIO_P_MODEL_MODE6_DISABLED // NU
| GPIO_P_MODEL_MODE7_DISABLED; // MAIN_LFXTAL_P
GPIO->P[1].MODEH = GPIO_P_MODEH_MODE8_DISABLED // MAIN_LFXTAL_N
| GPIO_P_MODEH_MODE9_DISABLED // NC
| GPIO_P_MODEH_MODE10_DISABLED // NC
| GPIO_P_MODEH_MODE11_DISABLED // PDM_DAT0 - MIC_DATA
| GPIO_P_MODEH_MODE12_DISABLED // PDM_CLK - MIC_CLOCK
| GPIO_P_MODEH_MODE13_DISABLED // MAIN_HFXTAL_P
| GPIO_P_MODEH_MODE14_DISABLED // MAIN_HFXTAL_N
| GPIO_P_MODEH_MODE15_DISABLED; // NC
GPIO->P[1].DOUT = 0;
GPIO->P[1].OVTDIS = 0;
// Port C
GPIO->P[2].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
| GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (7 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
GPIO->P[2].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC
| GPIO_P_MODEL_MODE1_DISABLED // NC
| GPIO_P_MODEL_MODE2_DISABLED // NC
| GPIO_P_MODEL_MODE3_DISABLED // NC
| GPIO_P_MODEL_MODE4_DISABLED // NU
| GPIO_P_MODEL_MODE5_DISABLED // NU
| GPIO_P_MODEL_MODE6_DISABLED // NC
| GPIO_P_MODEL_MODE7_DISABLED; // NC
GPIO->P[2].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC
| GPIO_P_MODEH_MODE9_DISABLED // NC
| GPIO_P_MODEH_MODE10_DISABLED // NC
| GPIO_P_MODEH_MODE11_DISABLED // NC
| GPIO_P_MODEH_MODE12_DISABLED // NC
| GPIO_P_MODEH_MODE13_DISABLED // NC
| GPIO_P_MODEH_MODE14_DISABLED // NC
| GPIO_P_MODEH_MODE15_DISABLED; // NC
GPIO->P[2].DOUT = 0;
GPIO->P[2].OVTDIS = 0;
// Port D
GPIO->P[3].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
| GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
GPIO->P[3].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU
| GPIO_P_MODEL_MODE1_DISABLED // NU
| GPIO_P_MODEL_MODE2_DISABLED // NU
| GPIO_P_MODEL_MODE3_DISABLED // NU
| GPIO_P_MODEL_MODE4_DISABLED // NU
| GPIO_P_MODEL_MODE5_INPUT // GPIO - BTN0
| GPIO_P_MODEL_MODE6_WIREDAND // LED1R
| GPIO_P_MODEL_MODE7_DISABLED; // NU
GPIO->P[3].MODEH = GPIO_P_MODEH_MODE8_INPUT // GPIO - BTN1
| GPIO_P_MODEH_MODE9_DISABLED // NC
| GPIO_P_MODEH_MODE10_DISABLED // NC
| GPIO_P_MODEH_MODE11_DISABLED // NC
| GPIO_P_MODEH_MODE12_DISABLED // NC
| GPIO_P_MODEH_MODE13_DISABLED // NC
| GPIO_P_MODEH_MODE14_DISABLED // NC
| GPIO_P_MODEH_MODE15_DISABLED; // NC
GPIO->P[3].DOUT = 0;
GPIO->P[3].OVTDIS = 0;
// Port E
GPIO->P[4].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
| GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
GPIO->P[4].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC
| GPIO_P_MODEL_MODE1_DISABLED // NC
| GPIO_P_MODEL_MODE2_DISABLED // NC
| GPIO_P_MODEL_MODE3_DISABLED // NC
| GPIO_P_MODEL_MODE4_DISABLED // NU
| GPIO_P_MODEL_MODE5_DISABLED // NU
| GPIO_P_MODEL_MODE6_DISABLED // NU
| GPIO_P_MODEL_MODE7_DISABLED; // NU
GPIO->P[4].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NU
| GPIO_P_MODEH_MODE9_DISABLED // NU
| GPIO_P_MODEH_MODE10_DISABLED // NU
| GPIO_P_MODEH_MODE11_DISABLED // NU
| GPIO_P_MODEH_MODE12_WIREDAND // LED1B
| GPIO_P_MODEH_MODE13_DISABLED // NU
| GPIO_P_MODEH_MODE14_DISABLED // NU
| GPIO_P_MODEH_MODE15_DISABLED; // NU
GPIO->P[4].DOUT = 0;
GPIO->P[4].OVTDIS = 0;
// Port F
GPIO->P[5].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
| GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
GPIO->P[5].MODEL = GPIO_P_MODEL_MODE0_PUSHPULL // SWCLK
| GPIO_P_MODEL_MODE1_PUSHPULL // SWDIO
| GPIO_P_MODEL_MODE2_PUSHPULL // SWO
| GPIO_P_MODEL_MODE3_DISABLED // NC
| GPIO_P_MODEL_MODE4_DISABLED // NC
| GPIO_P_MODEL_MODE5_DISABLED // NU
| GPIO_P_MODEL_MODE6_DISABLED // NC
| GPIO_P_MODEL_MODE7_DISABLED; // NC
GPIO->P[5].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC
| GPIO_P_MODEH_MODE9_DISABLED // NC
| GPIO_P_MODEH_MODE10_DISABLED // USB N
| GPIO_P_MODEH_MODE11_DISABLED // USB P
| GPIO_P_MODEH_MODE12_WIREDAND // LED1G
| GPIO_P_MODEH_MODE13_DISABLED // NC
| GPIO_P_MODEH_MODE14_DISABLED // NC
| GPIO_P_MODEH_MODE15_DISABLED; // NC
GPIO->P[5].DOUT = 0;
GPIO->P[5].OVTDIS = 0;
// Debugger Route
GPIO->ROUTEPEN &= ~(GPIO_ROUTEPEN_TDIPEN | GPIO_ROUTEPEN_TDOPEN); // Disable JTAG
GPIO->ROUTEPEN |= GPIO_ROUTEPEN_SWVPEN; // Enable SWO
GPIO->ROUTELOC0 = GPIO_ROUTELOC0_SWVLOC_LOC0; // SWO on PF2
// External interrupts
GPIO->EXTIPSELL = GPIO_EXTIPSELL_EXTIPSEL0_PORTE // NU
| GPIO_EXTIPSELL_EXTIPSEL1_PORTB // NU
| GPIO_EXTIPSELL_EXTIPSEL2_PORTB // NU
| GPIO_EXTIPSELL_EXTIPSEL3_PORTB // NU
| GPIO_EXTIPSELL_EXTIPSEL4_PORTA // NU
| GPIO_EXTIPSELL_EXTIPSEL5_PORTA // NU
| GPIO_EXTIPSELL_EXTIPSEL6_PORTC // NU
| GPIO_EXTIPSELL_EXTIPSEL7_PORTC; // NU
GPIO->EXTIPSELH = GPIO_EXTIPSELH_EXTIPSEL8_PORTA // NU
| GPIO_EXTIPSELH_EXTIPSEL9_PORTE // NU
| GPIO_EXTIPSELH_EXTIPSEL10_PORTF // NU
| GPIO_EXTIPSELH_EXTIPSEL11_PORTA // NU
| GPIO_EXTIPSELH_EXTIPSEL12_PORTA // NU
| GPIO_EXTIPSELH_EXTIPSEL13_PORTE // NU
| GPIO_EXTIPSELH_EXTIPSEL14_PORTF // NU
| GPIO_EXTIPSELH_EXTIPSEL15_PORTA; // NU
GPIO->EXTIPINSELL = GPIO_EXTIPINSELL_EXTIPINSEL0_PIN3 // NU
| GPIO_EXTIPINSELL_EXTIPINSEL1_PIN1 // NU
| GPIO_EXTIPINSELL_EXTIPINSEL2_PIN2 // NU
| GPIO_EXTIPINSELL_EXTIPINSEL3_PIN3 // NU
| GPIO_EXTIPINSELL_EXTIPINSEL4_PIN6 // NU
| GPIO_EXTIPINSELL_EXTIPINSEL5_PIN7 // NU
| GPIO_EXTIPINSELL_EXTIPINSEL6_PIN4 // NU
| GPIO_EXTIPINSELL_EXTIPINSEL7_PIN7; // NU
GPIO->EXTIPINSELH = GPIO_EXTIPINSELH_EXTIPINSEL8_PIN8 // NU
| GPIO_EXTIPINSELH_EXTIPINSEL9_PIN9 // NU
| GPIO_EXTIPINSELH_EXTIPINSEL10_PIN11 // NU
| GPIO_EXTIPINSELH_EXTIPINSEL11_PIN8 // NU
| GPIO_EXTIPINSELH_EXTIPINSEL12_PIN13 // NU
| GPIO_EXTIPINSELH_EXTIPINSEL13_PIN15 // NU
| GPIO_EXTIPINSELH_EXTIPINSEL14_PIN12 // NU
| GPIO_EXTIPINSELH_EXTIPINSEL15_PIN12; // NU
}
/*--------------------------------------------------------------------*/
/* Board Init */
/*--------------------------------------------------------------------*/
void board_init(void)
{
emu_dcdc_init(1800.f, 50.f, 100.f, 0.f); // Init DC-DC converter (1.8 V, 50 mA active, 100 uA sleep, 0 mA reverse limit)
emu_init(0);
emu_reg_init(3300.f); // set output regulator to 3.3V
cmu_hfxo_startup_calib(0x200, 0x145); // Config HFXO Startup for 1280 uA, 36 pF (18 pF + 2 pF CLOAD)
cmu_hfxo_steady_calib(0x009, 0x145); // Config HFXO Steady for 12 uA, 36 pF (18 pF + 2 pF CLOAD)
cmu_init(); // Init Clock Management Unit
cmu_ushfrco_calib(1, DEVINFO->USHFRCOCAL13); // Enable and calibrate USHFRCO for 48 MHz
cmu_auxhfrco_calib(1, DEVINFO->AUXHFRCOCAL11); // Enable and calibrate AUXHFRCO for 32 MHz
CMU->USBCRCTRL = CMU_USBCRCTRL_USBCREN; // enable USB clock recovery
CMU->USBCTRL = CMU_USBCTRL_USBCLKSEL_USHFRCO | CMU_USBCTRL_USBCLKEN; // select USHFRCO as USB Phy clock source and enable it
CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_USB; // enable USB peripheral clock
systick_init(); // Init system tick
gpio_init(); // Init IOs
}
/*--------------------------------------------------------------------*/
/* Board porting API */
/*--------------------------------------------------------------------*/
void board_led_write(bool state)
{
// Combine red and blue for pink Because it looks good :)
GPIO->P[LED_PORT].DOUT = (GPIO->P[LED_PORT].DOUT & ~((1 << LED_PIN_R) | (1 << LED_PIN_B))) | (state << LED_PIN_R) | (state << LED_PIN_B);
}
uint32_t board_button_read(void)
{
return !!(GPIO->P[BUTTON_PORT].DIN & (1 << BUTTON_PIN));
}
int board_uart_read(uint8_t* buf, int len)
{
(void) buf; (void) len;
return 0;
}
int board_uart_write(void const * buf, int len)
{
(void) buf; (void) len;
return 0;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void)
{
system_ticks++;
}
uint32_t tusb_time_millis_api(void)
{
return system_ticks;
}
#endif
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(char *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
================================================
FILE: hw/bsp/efm32/family.cmake
================================================
include_guard()
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# EFM32_FAMILY should be set by board.cmake (e.g. efm32gg12b)
string(TOUPPER ${EFM32_FAMILY} EFM32_FAMILY_UPPER)
set(SILABS_CMSIS ${TOP}/hw/mcu/silabs/cmsis-dfp-${EFM32_FAMILY}/Device/SiliconLabs/${EFM32_FAMILY_UPPER})
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
# toolchain set up
set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS EFM32GG CACHE INTERNAL "")
#------------------------------------
# Startup & Linker script
#------------------------------------
set(LD_FILE_GNU ${SILABS_CMSIS}/Source/GCC/${EFM32_FAMILY}.ld)
set(LD_FILE_Clang ${LD_FILE_GNU})
set(STARTUP_FILE_GNU ${SILABS_CMSIS}/Source/GCC/startup_${EFM32_FAMILY}.S)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
#------------------------------------
# Board Target
#------------------------------------
function(family_add_board BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SILABS_CMSIS}/Source/system_${EFM32_FAMILY}.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMSIS_5}/CMSIS/Core/Include
${SILABS_CMSIS}/Include
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
__STARTUP_CLEAR_BSS
__START=main
${EFM32_MCU}
)
update_board(${BOARD_TARGET})
endfunction()
#------------------------------------
# Functions
#------------------------------------
function(family_configure_example TARGET RTOS)
family_configure_common(${TARGET} ${RTOS})
family_add_tinyusb(${TARGET} OPT_MCU_EFM32GG)
target_sources(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${TARGET} PUBLIC
"LINKER:--script=${LD_FILE_Clang}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
SKIP_LINTING ON
COMPILE_OPTIONS -w)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
endfunction()
================================================
FILE: hw/bsp/efm32/family.mk
================================================
include $(TOP)/$(BOARD_PATH)/board.mk
CFLAGS += \
-flto \
-mthumb \
-mcpu=cortex-m4 \
-mfloat-abi=hard \
-mfpu=fpv4-sp-d16 \
-nostdlib -nostartfiles \
-D__STARTUP_CLEAR_BSS \
-D__START=main \
-DCFG_TUSB_MCU=OPT_MCU_EFM32GG
CPU_CORE ?= cortex-m4
# EFM32_FAMILY should be set by board.mk (e.g. efm32gg12b)
SILABS_CMSIS = hw/mcu/silabs/cmsis-dfp-$(EFM32_FAMILY)/Device/SiliconLabs/$(shell echo $(EFM32_FAMILY) | tr a-z A-Z)
LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
# All source paths should be relative to the top level.
LD_FILE = $(SILABS_CMSIS)/Source/GCC/$(EFM32_FAMILY).ld
SRC_C += \
$(SILABS_CMSIS)/Source/system_$(EFM32_FAMILY).c \
src/portable/synopsys/dwc2/dcd_dwc2.c \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
SRC_S += \
$(SILABS_CMSIS)/Source/GCC/startup_$(EFM32_FAMILY).S
INC += \
$(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
$(TOP)/$(SILABS_CMSIS)/Include \
$(TOP)/$(BOARD_PATH)
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F
================================================
FILE: hw/bsp/espressif/boards/CMakeLists.txt
================================================
set(hw_dir "${CMAKE_CURRENT_LIST_DIR}/../../../")
idf_component_register(SRCS family.c
INCLUDE_DIRS "." ${BOARD} ${hw_dir}
PRIV_REQUIRES driver usb
REQUIRES led_strip src tinyusb_src)
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32")
set(MAX3421_HOST 1)
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Adafruit Feather ESP32 v2
url: https://www.adafruit.com/product/5400
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 0
#define NEOPIXEL_POWER_PIN 2
#define NEOPIXEL_POWER_STATE 1
#define BUTTON_PIN 38
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI3_HOST
#define MAX3421_SCK_PIN 5
#define MAX3421_MOSI_PIN 19
#define MAX3421_MISO_PIN 21
#define MAX3421_CS_PIN 33
#define MAX3421_INTR_PIN 15
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32c6")
set(MAX3421_HOST 1)
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Adafruit Feather EPS32-C6
url: https://www.adafruit.com/product/5933
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 15
#define BUTTON_PIN 9
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 21
#define MAX3421_MOSI_PIN 22
#define MAX3421_MISO_PIN 23
#define MAX3421_CS_PIN 8
#define MAX3421_INTR_PIN 7
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s2")
set(MAX3421_HOST 1)
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32s2/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Adafruit Feather ESP32S2
url: https://www.adafruit.com/product/5000
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 33
#define NEOPIXEL_POWER_PIN 21
#define NEOPIXEL_POWER_STATE 1
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 10
#define MAX3421_INTR_PIN 9
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32s3/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s3")
set(MAX3421_HOST 1)
================================================
FILE: hw/bsp/espressif/boards/adafruit_feather_esp32s3/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Adafruit Feather ESP32S3
url: https://www.adafruit.com/product/5323
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 33
#define NEOPIXEL_POWER_PIN 21
#define NEOPIXEL_POWER_STATE 1
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 10
#define MAX3421_INTR_PIN 9
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/adafruit_magtag_29gray/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s2")
================================================
FILE: hw/bsp/espressif/boards/adafruit_magtag_29gray/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Adafruit MagTag 2.9" Grayscale
url: https://www.adafruit.com/product/4800
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 1
#define NEOPIXEL_POWER_PIN 21
#define NEOPIXEL_POWER_STATE 0
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s2")
set(MAX3421_HOST 1)
================================================
FILE: hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Adafruit Metro ESP32-S2
url: https://www.adafruit.com/product/4775
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 45
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_addax_1/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s3")
================================================
FILE: hw/bsp/espressif/boards/espressif_addax_1/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif Addax-1
url: n/a
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
// Note: On the production version (v1.1) WS2812 is connected to GPIO 47
#define NEOPIXEL_PIN 47
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_c3_devkitc/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32c3")
set(MAX3421_HOST 1)
================================================
FILE: hw/bsp/espressif/boards/espressif_c3_devkitc/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif C3 DevKitC
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c3/esp32-c3-devkitc-02/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 8
#define BUTTON_PIN 9
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 4
#define MAX3421_MOSI_PIN 6
#define MAX3421_MISO_PIN 5
#define MAX3421_CS_PIN 10
#define MAX3421_INTR_PIN 7
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_c6_devkitc/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32c6")
set(MAX3421_HOST 1)
================================================
FILE: hw/bsp/espressif/boards/espressif_c6_devkitc/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif C6 DevKitC
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 8
#define BUTTON_PIN 9
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 4
#define MAX3421_MOSI_PIN 6
#define MAX3421_MISO_PIN 5
#define MAX3421_CS_PIN 10
#define MAX3421_INTR_PIN 7
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_kaluga_1/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s2")
================================================
FILE: hw/bsp/espressif/boards/espressif_kaluga_1/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif Kaluga 1
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/esp32-s2-kaluga-1/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
// Note: need to insert jumper next to WS2812 pixel
#define NEOPIXEL_PIN 45
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_p4_function_ev/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32p4")
list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults")
================================================
FILE: hw/bsp/espressif/boards/espressif_p4_function_ev/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif P4 Function EV
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
// #define NEOPIXEL_PIN 48
#define BUTTON_PIN 35
#define BUTTON_STATE_ACTIVE 0
// For CI hardware test, to test both device and host on the same HS port with help of TS3USB30
// https://www.adafruit.com/product/5871
#define HIL_TS3USB30_MODE_PIN 47
#define HIL_TS3USB30_MODE_DEVICE 1
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_p4_function_ev/sdkconfig.defaults
================================================
CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y
CONFIG_ESP32P4_REV_MIN_1=y
================================================
FILE: hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s2")
================================================
FILE: hw/bsp/espressif/boards/espressif_s2_devkitc/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif S2 DevKitC
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/esp32-s2-devkitc-1/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 18
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_s3_devkitc/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s3")
================================================
FILE: hw/bsp/espressif/boards/espressif_s3_devkitc/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif S3 DevKitC
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-devkitc-1/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 38
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 39
#define MAX3421_MOSI_PIN 42
#define MAX3421_MISO_PIN 21
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_s3_devkitm/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s3")
================================================
FILE: hw/bsp/espressif/boards/espressif_s3_devkitm/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif S3 DevKitM
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-devkitm-1/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NEOPIXEL_PIN 48
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 39
#define MAX3421_MOSI_PIN 42
#define MAX3421_MISO_PIN 21
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
// For CI hardware test, to test both device and host on the same HS port with help of TS3USB30
// https://www.adafruit.com/product/5871
#define HIL_TS3USB30_MODE_PIN 47
#define HIL_TS3USB30_MODE_DEVICE 1
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/espressif_saola_1/board.cmake
================================================
# Apply board specific content here
set(IDF_TARGET "esp32s2")
================================================
FILE: hw/bsp/espressif/boards/espressif_saola_1/board.h
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
name: Espresif S2 Saola 1
url: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/esp32-s2-saola-1/index.html
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
// Note: On the production version (v1.2) WS2812 is connected to GPIO 18,
// however earlier revision v1.1 WS2812 is connected to GPIO 17
#define NEOPIXEL_PIN 18
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
================================================
FILE: hw/bsp/espressif/boards/family.c
================================================
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
/* metadata:
manufacturer: Espressif
*/
#include "bsp/board_api.h"
#include "board.h"
#include "esp_rom_gpio.h"
#include "esp_mac.h"
#include "hal/gpio_ll.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_private/periph_ctrl.h"
#ifdef NEOPIXEL_PIN
#include "led_strip.h"
static led_strip_handle_t led_strip;
#endif
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
#include "driver/spi_master.h"
static void max3421_init(void);
#endif
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4, OPT_MCU_ESP32P4)
static bool usb_init(uint8_t rhport, bool is_host);
#endif
//--------------------------------------------------------------------+
// Implementation
//--------------------------------------------------------------------+
// Initialize on-board peripherals : led, button, uart and USB
void board_init(void) {
#ifdef NEOPIXEL_PIN
#ifdef NEOPIXEL_POWER_PIN
gpio_reset_pin(NEOPIXEL_POWER_PIN);
gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE);
#endif
// WS2812 Neopixel driver with RMT peripheral
led_strip_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = 10 * 1000 * 1000, // RMT counter clock frequency, default = 10 Mhz
.flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3
};
led_strip_config_t strip_config = {
.strip_gpio_num = NEOPIXEL_PIN, // The GPIO that connected to the LED strip's data line
.max_leds = 1, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal
};
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
led_strip_clear(led_strip); // off
#endif
// Button
esp_rom_gpio_pad_select_gpio(BUTTON_PIN);
gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY);
#if CONFIG_USB_OTG_SUPPORTED
#if CFG_TUD_ENABLED
usb_init(BOARD_TUD_RHPORT, false);
#endif
#if CFG_TUH_ENABLED
usb_init(BOARD_TUH_RHPORT, true);
#endif
#endif
#ifdef HIL_TS3USB30_MODE_PIN
gpio_reset_pin(HIL_TS3USB30_MODE_PIN);
gpio_set_direction(HIL_TS3USB30_MODE_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(HIL_TS3USB30_MODE_PIN, CFG_TUD_ENABLED ? HIL_TS3USB30_MODE_DEVICE : (1-HIL_TS3USB30_MODE_DEVICE));
#endif
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
max3421_init();
#endif
}
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4)
#endif
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
// use factory default MAC as serial ID
esp_efuse_mac_get_default(id);
return 6;
}
void board_led_write(bool state) {
#ifdef NEOPIXEL_PIN
led_strip_set_pixel(led_strip, 0, state ? 0x08 : 0x00, 0x00, 0x00);
led_strip_refresh(led_strip);
#endif
}
// Get the current state of button
// a '1' means active (pressed), a '0' means inactive.
uint32_t board_button_read(void) {
return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE;
}
// Get characters from UART
int board_uart_read(uint8_t* buf, int len) {
for (int i=0; i= ESP_IDF_VERSION_VAL(5, 3, 0)
#include "esp_private/usb_phy.h"
static usb_phy_handle_t phy_hdl;
bool usb_init(uint8_t rhport, bool is_host) {
(void) rhport;
// Configure USB PHY
usb_phy_config_t phy_conf = {
.controller = USB_PHY_CTRL_OTG,
#if defined(CONFIG_SOC_USB_UTMI_PHY_NUM) && CONFIG_SOC_USB_UTMI_PHY_NUM > 0
.target = USB_PHY_TARGET_UTMI,
#else
.target = USB_PHY_TARGET_INT,
#endif
// maybe we can use USB_OTG_MODE_DEFAULT and switch using dwc2 driver
.otg_mode = is_host ? USB_OTG_MODE_HOST : USB_OTG_MODE_DEVICE,
// https://github.com/hathach/tinyusb/issues/2943#issuecomment-2601888322
// Set speed to undefined (auto-detect) to avoid timinng/racing issue with S3 with host such as macOS
.otg_speed = USB_PHY_SPEED_UNDEFINED,
};
esp_err_t const err = usb_new_phy(&phy_conf, &phy_hdl);
if (err != ESP_OK) {
printf("usb_new_phy failed: %s\r\n", esp_err_to_name(err));
phy_hdl = NULL;
return false;
}
return true;
}
#else
#include "esp_private/usb_phy.h"
#include "hal/usb_hal.h"
#include "soc/usb_periph.h"
static void configure_pins(usb_hal_context_t* usb) {
/* usb_periph_iopins currently configures USB_OTG as USB Device.
* Introduce additional parameters in usb_hal_context_t when adding support
* for USB Host. */
for (const usb_iopin_dsc_t* iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
esp_rom_gpio_pad_select_gpio(iopin->pin);
if (iopin->is_output) {
esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
} else {
esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT)) {
gpio_ll_input_enable(&GPIO, iopin->pin);
}
}
esp_rom_gpio_pad_unhold(iopin->pin);
}
}
if (!usb->use_external_phy) {
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
}
}
bool usb_init(void) {
// USB Controller Hal init
periph_module_reset(PERIPH_USB_MODULE);
periph_module_enable(PERIPH_USB_MODULE);
usb_hal_context_t hal = {
.use_external_phy = false // use built-in PHY
};
usb_hal_init(&hal);
configure_pins(&hal);
return true;
}
#endif
#endif
//--------------------------------------------------------------------+
// API: SPI transfer with MAX3421E, must be implemented by application
//--------------------------------------------------------------------+
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
static spi_device_handle_t max3421_spi;
SemaphoreHandle_t max3421_intr_sem;
static void IRAM_ATTR max3421_isr_handler(void* arg) {
(void) arg; // arg is gpio num
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(max3421_intr_sem, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR();
}
}
static void max3421_intr_task(void* param) {
(void) param;
while (1) {
xSemaphoreTake(max3421_intr_sem, portMAX_DELAY);
tuh_int_handler(BOARD_TUH_RHPORT, false);
}
}
static void max3421_init(void) {
// CS pin
gpio_set_direction(MAX3421_CS_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(MAX3421_CS_PIN, 1);
// SPI
spi_bus_config_t buscfg = {
.miso_io_num = MAX3421_MISO_PIN,
.mosi_io_num = MAX3421_MOSI_PIN,
.sclk_io_num = MAX3421_SCK_PIN,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.data4_io_num = -1,
.data5_io_num = -1,
.data6_io_num = -1,
.data7_io_num = -1,
.max_transfer_sz = 1024
};
ESP_ERROR_CHECK(spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
spi_device_interface_config_t max3421_cfg = {
.mode = 0,
.clock_speed_hz = 20000000, // S2/S3 can work with 26 Mhz, but esp32 seems only work up to 20 Mhz
.spics_io_num = -1, // manual control CS
.queue_size = 1
};
ESP_ERROR_CHECK(spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi));
// Interrupt pin
max3421_intr_sem = xSemaphoreCreateBinary();
xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES - 2, NULL);
gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT);
gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE);
gpio_install_isr_service(0);
gpio_isr_handler_add(MAX3421_INTR_PIN, max3421_isr_handler, NULL);
}
void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport;
if (enabled) {
gpio_intr_enable(MAX3421_INTR_PIN);
} else {
gpio_intr_disable(MAX3421_INTR_PIN);
}
}
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport;
gpio_set_level(MAX3421_CS_PIN, active ? 0 : 1);
}
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport;
if (tx_buf == NULL) {
// fifo read, transmit rx_buf as dummy
tx_buf = rx_buf;
}
// length in bits
size_t const len_bits = xfer_bytes << 3;
spi_transaction_t xact = {
.length = len_bits,
.rxlength = rx_buf ? len_bits : 0,
.tx_buffer = tx_buf,
.rx_buffer = rx_buf
};
ESP_ERROR_CHECK(spi_device_transmit(max3421_spi, &xact));
return true;
}
#endif
================================================
FILE: hw/bsp/espressif/components/led_strip/CHANGELOG.md
================================================
## 2.5.0
- Enabled support for IDF4.4 and above
- with RMT backend only
- Added API `led_strip_set_pixel_hsv`
## 2.4.0
- Support configurable SPI mode to control leds
- recommend enabling DMA when using SPI mode
## 2.3.0
- Support configurable RMT channel size by setting `mem_block_symbols`
## 2.2.0
- Support for 4 components RGBW leds (SK6812):
- in led_strip_config_t new fields
led_pixel_format, controlling byte format (LED_PIXEL_FORMAT_GRB, LED_PIXEL_FORMAT_GRBW)
led_model, used to configure bit timing (LED_MODEL_WS2812, LED_MODEL_SK6812)
- new API led_strip_set_pixel_rgbw
- new interface type set_pixel_rgbw
## 2.1.0
- Support DMA feature, which offloads the CPU by a lot when it comes to drive a bunch of LEDs
- Support various RMT clock sources
- Acquire and release the power management lock before and after each refresh
- New driver flag: `invert_out` which can invert the led control signal by hardware
## 2.0.0
- Reimplemented the driver using the new RMT driver (`driver/rmt_tx.h`)
## 1.0.0
- Initial driver version, based on the legacy RMT driver (`driver/rmt.h`)
================================================
FILE: hw/bsp/espressif/components/led_strip/CMakeLists.txt
================================================
include($ENV{IDF_PATH}/tools/cmake/version.cmake)
set(srcs "src/led_strip_api.c")
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
if(CONFIG_SOC_RMT_SUPPORTED)
list(APPEND srcs "src/led_strip_rmt_dev.c" "src/led_strip_rmt_encoder.c")
endif()
else()
list(APPEND srcs "src/led_strip_rmt_dev_idf4.c")
endif()
# the SPI backend driver relies on something that was added in IDF 5.1
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.1")
if(CONFIG_SOC_GPSPI_SUPPORTED)
list(APPEND srcs "src/led_strip_spi_dev.c")
endif()
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "include" "interface"
REQUIRES "driver")
================================================
FILE: hw/bsp/espressif/components/led_strip/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
================================================
FILE: hw/bsp/espressif/components/led_strip/README.md
================================================
# LED Strip Driver
[](https://components.espressif.com/components/espressif/led_strip)
This driver is designed for addressable LEDs like [WS2812](http://www.world-semi.com/Certifications/WS2812B.html), where each LED is controlled by a single data line.
## Backend Controllers
### The [RMT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html) Peripheral
This is the most economical way to drive the LEDs because it only consumes one RMT channel, leaving other channels free to use. However, the memory usage increases dramatically with the number of LEDs. If the RMT hardware can't be assist by DMA, the driver will going into interrupt very frequently, thus result in a high CPU usage. What's worse, if the RMT interrupt is delayed or not serviced in time (e.g. if Wi-Fi interrupt happens on the same CPU core), the RMT transaction will be corrupted and the LEDs will display incorrect colors. If you want to use RMT to drive a large number of LEDs, you'd better to enable the DMA feature if possible [^1].
#### Allocate LED Strip Object with RMT Backend
```c
#define BLINK_GPIO 0
led_strip_handle_t led_strip;
/* LED strip initialization with the GPIO and pixels number*/
led_strip_config_t strip_config = {
.strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = 1, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter)
};
led_strip_rmt_config_t rmt_config = {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
.rmt_channel = 0,
#else
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = 10 * 1000 * 1000, // 10MHz
.flags.with_dma = false, // whether to enable the DMA feature
#endif
};
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
```
You can create multiple LED strip objects with different GPIOs and pixel numbers. The backend driver will automatically allocate the RMT channel for you if there is more available.
### The [SPI](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html) Peripheral
SPI peripheral can also be used to generate the timing required by the LED strip. However this backend is not as economical as the RMT one, because it will take up the whole **bus**, unlike the RMT just takes one **channel**. You **CAN'T** connect other devices to the same SPI bus if it's been used by the led_strip, because the led_strip doesn't have the concept of "Chip Select".
Please note, the SPI backend has a dependency of **ESP-IDF >= 5.1**
#### Allocate LED Strip Object with SPI Backend
```c
#define BLINK_GPIO 0
led_strip_handle_t led_strip;
/* LED strip initialization with the GPIO and pixels number*/
led_strip_config_t strip_config = {
.strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = 1, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter)
};
led_strip_spi_config_t spi_config = {
.clk_src = SPI_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.flags.with_dma = true, // Using DMA can improve performance and help drive more LEDs
.spi_bus = SPI2_HOST, // SPI bus ID
};
ESP_ERROR_CHECK(led_strip_new_spi_device(&strip_config, &spi_config, &led_strip));
```
The number of LED strip objects can be created depends on how many free SPI buses are free to use in your project.
## FAQ
* Which led_strip backend should I choose?
* It depends on your application requirement and target chip's ability.
```mermaid
flowchart LR
A{Is RMT supported?}
A --> |No| B[SPI backend]
B --> C{Does the led strip has \n a larger number of LEDs?}
C --> |No| D[Don't have to enable the DMA of the backend]
C --> |Yes| E[Enable the DMA of the backend]
A --> |Yes| F{Does the led strip has \n a larger number of LEDs?}
F --> |Yes| G{Does RMT support DMA?}
G --> |Yes| E
G --> |No| B
F --> |No| H[RMT backend] --> D
```
* How to set the brightness of the LED strip?
* You can tune the brightness by scaling the value of each R-G-B element with a **same** factor. But pay attention to the overflow of the value.
[^1]: The RMT DMA feature is not available on all ESP chips. Please check the data sheet before using it.
================================================
FILE: hw/bsp/espressif/components/led_strip/api.md
================================================
# API Reference
## Header files
- [include/led_strip.h](#file-includeled_striph)
- [include/led_strip_rmt.h](#file-includeled_strip_rmth)
- [include/led_strip_spi.h](#file-includeled_strip_spih)
- [include/led_strip_types.h](#file-includeled_strip_typesh)
- [interface/led_strip_interface.h](#file-interfaceled_strip_interfaceh)
## File include/led_strip.h
## Functions
| Type | Name |
| ---: | :--- |
| esp\_err\_t | [**led\_strip\_clear**](#function-led_strip_clear) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip) _Clear LED strip (turn off all LEDs)_ |
| esp\_err\_t | [**led\_strip\_del**](#function-led_strip_del) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip) _Free LED strip resources._ |
| esp\_err\_t | [**led\_strip\_refresh**](#function-led_strip_refresh) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip) _Refresh memory colors to LEDs._ |
| esp\_err\_t | [**led\_strip\_set\_pixel**](#function-led_strip_set_pixel) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint32\_t red, uint32\_t green, uint32\_t blue) _Set RGB for a specific pixel._ |
| esp\_err\_t | [**led\_strip\_set\_pixel\_hsv**](#function-led_strip_set_pixel_hsv) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint16\_t hue, uint8\_t saturation, uint8\_t value) _Set HSV for a specific pixel._ |
| esp\_err\_t | [**led\_strip\_set\_pixel\_rgbw**](#function-led_strip_set_pixel_rgbw) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint32\_t red, uint32\_t green, uint32\_t blue, uint32\_t white) _Set RGBW for a specific pixel._ |
## Functions Documentation
### function `led_strip_clear`
_Clear LED strip (turn off all LEDs)_
```c
esp_err_t led_strip_clear (
led_strip_handle_t strip
)
```
**Parameters:**
- `strip` LED strip
**Returns:**
- ESP\_OK: Clear LEDs successfully
- ESP\_FAIL: Clear LEDs failed because some other error occurred
### function `led_strip_del`
_Free LED strip resources._
```c
esp_err_t led_strip_del (
led_strip_handle_t strip
)
```
**Parameters:**
- `strip` LED strip
**Returns:**
- ESP\_OK: Free resources successfully
- ESP\_FAIL: Free resources failed because error occurred
### function `led_strip_refresh`
_Refresh memory colors to LEDs._
```c
esp_err_t led_strip_refresh (
led_strip_handle_t strip
)
```
**Parameters:**
- `strip` LED strip
**Returns:**
- ESP\_OK: Refresh successfully
- ESP\_FAIL: Refresh failed because some other error occurred
**Note:**
: After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
### function `led_strip_set_pixel`
_Set RGB for a specific pixel._
```c
esp_err_t led_strip_set_pixel (
led_strip_handle_t strip,
uint32_t index,
uint32_t red,
uint32_t green,
uint32_t blue
)
```
**Parameters:**
- `strip` LED strip
- `index` index of pixel to set
- `red` red part of color
- `green` green part of color
- `blue` blue part of color
**Returns:**
- ESP\_OK: Set RGB for a specific pixel successfully
- ESP\_ERR\_INVALID\_ARG: Set RGB for a specific pixel failed because of invalid parameters
- ESP\_FAIL: Set RGB for a specific pixel failed because other error occurred
### function `led_strip_set_pixel_hsv`
_Set HSV for a specific pixel._
```c
esp_err_t led_strip_set_pixel_hsv (
led_strip_handle_t strip,
uint32_t index,
uint16_t hue,
uint8_t saturation,
uint8_t value
)
```
**Parameters:**
- `strip` LED strip
- `index` index of pixel to set
- `hue` hue part of color (0 - 360)
- `saturation` saturation part of color (0 - 255)
- `value` value part of color (0 - 255)
**Returns:**
- ESP\_OK: Set HSV color for a specific pixel successfully
- ESP\_ERR\_INVALID\_ARG: Set HSV color for a specific pixel failed because of an invalid argument
- ESP\_FAIL: Set HSV color for a specific pixel failed because other error occurred
### function `led_strip_set_pixel_rgbw`
_Set RGBW for a specific pixel._
```c
esp_err_t led_strip_set_pixel_rgbw (
led_strip_handle_t strip,
uint32_t index,
uint32_t red,
uint32_t green,
uint32_t blue,
uint32_t white
)
```
**Note:**
Only call this function if your led strip does have the white component (e.g. SK6812-RGBW)
**Note:**
Also see `led_strip_set_pixel` if you only want to specify the RGB part of the color and bypass the white component
**Parameters:**
- `strip` LED strip
- `index` index of pixel to set
- `red` red part of color
- `green` green part of color
- `blue` blue part of color
- `white` separate white component
**Returns:**
- ESP\_OK: Set RGBW color for a specific pixel successfully
- ESP\_ERR\_INVALID\_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
- ESP\_FAIL: Set RGBW color for a specific pixel failed because other error occurred
## File include/led_strip_rmt.h
## Structures and Types
| Type | Name |
| ---: | :--- |
| struct | [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) _LED Strip RMT specific configuration._ |
## Functions
| Type | Name |
| ---: | :--- |
| esp\_err\_t | [**led\_strip\_new\_rmt\_device**](#function-led_strip_new_rmt_device) (const [**led\_strip\_config\_t**](#struct-led_strip_config_t) \*led\_config, const [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) \*rmt\_config, [**led\_strip\_handle\_t**](#struct-led_strip_t) \*ret\_strip) _Create LED strip based on RMT TX channel._ |
## Structures and Types Documentation
### struct `led_strip_rmt_config_t`
_LED Strip RMT specific configuration._
Variables:
- rmt\_clock\_source\_t clk_src RMT clock source
- struct [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) flags Extra driver flags
- size\_t mem_block_symbols How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size.
- uint32\_t resolution_hz RMT tick resolution, if set to zero, a default resolution (10MHz) will be applied
- uint32\_t with_dma Use DMA to transmit data
## Functions Documentation
### function `led_strip_new_rmt_device`
_Create LED strip based on RMT TX channel._
```c
esp_err_t led_strip_new_rmt_device (
const led_strip_config_t *led_config,
const led_strip_rmt_config_t *rmt_config,
led_strip_handle_t *ret_strip
)
```
**Parameters:**
- `led_config` LED strip configuration
- `rmt_config` RMT specific configuration
- `ret_strip` Returned LED strip handle
**Returns:**
- ESP\_OK: create LED strip handle successfully
- ESP\_ERR\_INVALID\_ARG: create LED strip handle failed because of invalid argument
- ESP\_ERR\_NO\_MEM: create LED strip handle failed because of out of memory
- ESP\_FAIL: create LED strip handle failed because some other error
## File include/led_strip_spi.h
## Structures and Types
| Type | Name |
| ---: | :--- |
| struct | [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) _LED Strip SPI specific configuration._ |
## Functions
| Type | Name |
| ---: | :--- |
| esp\_err\_t | [**led\_strip\_new\_spi\_device**](#function-led_strip_new_spi_device) (const [**led\_strip\_config\_t**](#struct-led_strip_config_t) \*led\_config, const [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) \*spi\_config, [**led\_strip\_handle\_t**](#struct-led_strip_t) \*ret\_strip) _Create LED strip based on SPI MOSI channel._ |
## Structures and Types Documentation
### struct `led_strip_spi_config_t`
_LED Strip SPI specific configuration._
Variables:
- spi\_clock\_source\_t clk_src SPI clock source
- struct [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) flags Extra driver flags
- spi\_host\_device\_t spi_bus SPI bus ID. Which buses are available depends on the specific chip
- uint32\_t with_dma Use DMA to transmit data
## Functions Documentation
### function `led_strip_new_spi_device`
_Create LED strip based on SPI MOSI channel._
```c
esp_err_t led_strip_new_spi_device (
const led_strip_config_t *led_config,
const led_strip_spi_config_t *spi_config,
led_strip_handle_t *ret_strip
)
```
**Note:**
Although only the MOSI line is used for generating the signal, the whole SPI bus can't be used for other purposes.
**Parameters:**
- `led_config` LED strip configuration
- `spi_config` SPI specific configuration
- `ret_strip` Returned LED strip handle
**Returns:**
- ESP\_OK: create LED strip handle successfully
- ESP\_ERR\_INVALID\_ARG: create LED strip handle failed because of invalid argument
- ESP\_ERR\_NOT\_SUPPORTED: create LED strip handle failed because of unsupported configuration
- ESP\_ERR\_NO\_MEM: create LED strip handle failed because of out of memory
- ESP\_FAIL: create LED strip handle failed because some other error
## File include/led_strip_types.h
## Structures and Types
| Type | Name |
| ---: | :--- |
| enum | [**led\_model\_t**](#enum-led_model_t) _LED strip model._ |
| enum | [**led\_pixel\_format\_t**](#enum-led_pixel_format_t) _LED strip pixel format._ |
| struct | [**led\_strip\_config\_t**](#struct-led_strip_config_t) _LED Strip Configuration._ |
| typedef struct [**led\_strip\_t**](#struct-led_strip_t) \* | [**led\_strip\_handle\_t**](#typedef-led_strip_handle_t) _LED strip handle._ |
## Structures and Types Documentation
### enum `led_model_t`
_LED strip model._
```c
enum led_model_t {
LED_MODEL_WS2812,
LED_MODEL_SK6812,
LED_MODEL_INVALID
};
```
**Note:**
Different led model may have different timing parameters, so we need to distinguish them.
### enum `led_pixel_format_t`
_LED strip pixel format._
```c
enum led_pixel_format_t {
LED_PIXEL_FORMAT_GRB,
LED_PIXEL_FORMAT_GRBW,
LED_PIXEL_FORMAT_INVALID
};
```
### struct `led_strip_config_t`
_LED Strip Configuration._
Variables:
- struct [**led\_strip\_config\_t**](#struct-led_strip_config_t) flags Extra driver flags
- uint32\_t invert_out Invert output signal
- led\_model\_t led_model LED model
- led\_pixel\_format\_t led_pixel_format LED pixel format
- uint32\_t max_leds Maximum LEDs in a single strip
- int strip_gpio_num GPIO number that used by LED strip
### typedef `led_strip_handle_t`
_LED strip handle._
```c
typedef struct led_strip_t* led_strip_handle_t;
```
## File interface/led_strip_interface.h
## Structures and Types
| Type | Name |
| ---: | :--- |
| struct | [**led\_strip\_t**](#struct-led_strip_t) _LED strip interface definition._ |
| typedef struct [**led\_strip\_t**](#struct-led_strip_t) | [**led\_strip\_t**](#typedef-led_strip_t) |
## Structures and Types Documentation
### struct `led_strip_t`
_LED strip interface definition._
Variables:
- esp\_err\_t(\* clear _Clear LED strip (turn off all LEDs)_ **Parameters:**
- `strip` LED strip
- `timeout_ms` timeout value for clearing task
**Returns:**
- ESP\_OK: Clear LEDs successfully
- ESP\_FAIL: Clear LEDs failed because some other error occurred
- esp\_err\_t(\* del _Free LED strip resources._ **Parameters:**
- `strip` LED strip
**Returns:**
- ESP\_OK: Free resources successfully
- ESP\_FAIL: Free resources failed because error occurred
- esp\_err\_t(\* refresh _Refresh memory colors to LEDs._ **Parameters:**
- `strip` LED strip
- `timeout_ms` timeout value for refreshing task
**Returns:**
- ESP\_OK: Refresh successfully
- ESP\_FAIL: Refresh failed because some other error occurred
**Note:**
: After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
- esp\_err\_t(\* set_pixel _Set RGB for a specific pixel._ **Parameters:**
- `strip` LED strip
- `index` index of pixel to set
- `red` red part of color
- `green` green part of color
- `blue` blue part of color
**Returns:**
- ESP\_OK: Set RGB for a specific pixel successfully
- ESP\_ERR\_INVALID\_ARG: Set RGB for a specific pixel failed because of invalid parameters
- ESP\_FAIL: Set RGB for a specific pixel failed because other error occurred
- esp\_err\_t(\* set_pixel_rgbw _Set RGBW for a specific pixel. Similar to_ `set_pixel`_but also set the white component._ **Parameters:**
- `strip` LED strip
- `index` index of pixel to set
- `red` red part of color
- `green` green part of color
- `blue` blue part of color
- `white` separate white component
**Returns:**
- ESP\_OK: Set RGBW color for a specific pixel successfully
- ESP\_ERR\_INVALID\_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
- ESP\_FAIL: Set RGBW color for a specific pixel failed because other error occurred
### typedef `led_strip_t`
```c
typedef struct led_strip_t led_strip_t;
```
Type of LED strip
================================================
FILE: hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt
================================================
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
set(IDF_TARGET "esp32s3")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(led_strip_rmt_ws2812)
================================================
FILE: hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md
================================================
# LED Strip Example (RMT backend + WS2812)
This example demonstrates how to blink the WS2812 LED using the [led_strip](https://components.espressif.com/component/espressif/led_strip) component.
## How to Use Example
### Hardware Required
* A development board with Espressif SoC
* A USB cable for Power supply and programming
* WS2812 LED strip
### Configure the Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. Then assign the proper GPIO in the [source file](main/led_strip_rmt_ws2812_main.c). If your led strip has multiple LEDs, don't forget update the number.
### Build and Flash
Run `idf.py -p PORT build flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
```text
I (299) gpio: GPIO[8]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (309) example: Created LED strip object with RMT backend
I (309) example: Start blinking LED strip
```
================================================
FILE: hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt
================================================
idf_component_register(SRCS "led_strip_rmt_ws2812_main.c"
INCLUDE_DIRS ".")
================================================
FILE: hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml
================================================
## IDF Component Manager Manifest File
dependencies:
espressif/led_strip:
version: '^2'
override_path: '../../../'
================================================
FILE: hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c
================================================
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "led_strip.h"
#include "esp_log.h"
#include "esp_err.h"
// GPIO assignment
#define LED_STRIP_BLINK_GPIO 48
// Numbers of the LED in the strip
#define LED_STRIP_LED_NUMBERS 1
// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)
static const char *TAG = "example";
led_strip_handle_t configure_led(void)
{
// LED strip general initialization, according to your led board design
led_strip_config_t strip_config = {
.strip_gpio_num = LED_STRIP_BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = LED_STRIP_LED_NUMBERS, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal
};
// LED strip backend configuration: RMT
led_strip_rmt_config_t rmt_config = {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
.rmt_channel = 0,
#else
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency
.flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3
#endif
};
// LED Strip object handle
led_strip_handle_t led_strip;
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
ESP_LOGI(TAG, "Created LED strip object with RMT backend");
return led_strip;
}
void app_main(void)
{
led_strip_handle_t led_strip = configure_led();
bool led_on_off = false;
ESP_LOGI(TAG, "Start blinking LED strip");
while (1) {
if (led_on_off) {
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) {
ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, 5, 5, 5));
}
/* Refresh the strip to send data */
ESP_ERROR_CHECK(led_strip_refresh(led_strip));
ESP_LOGI(TAG, "LED ON!");
} else {
/* Set all LED off to clear all pixels */
ESP_ERROR_CHECK(led_strip_clear(led_strip));
ESP_LOGI(TAG, "LED OFF!");
}
led_on_off = !led_on_off;
vTaskDelay(pdMS_TO_TICKS(500));
}
}
================================================
FILE: hw/bsp/espressif/components/led_strip/idf_component.yml
================================================
version: "2.5.2"
description: Driver for Addressable LED Strip (WS2812, etc)
url: https://github.com/espressif/idf-extra-components/tree/master/led_strip
dependencies:
idf: ">=4.4"
================================================
FILE: hw/bsp/espressif/components/led_strip/include/led_strip.h
================================================
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include
#include "esp_err.h"
#include "led_strip_rmt.h"
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
#include "led_strip_spi.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set RGB for a specific pixel
*
* @param strip: LED strip
* @param index: index of pixel to set
* @param red: red part of color
* @param green: green part of color
* @param blue: blue part of color
*
* @return
* - ESP_OK: Set RGB for a specific pixel successfully
* - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters
* - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred
*/
esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
/**
* @brief Set RGBW for a specific pixel
*
* @note Only call this function if your led strip does have the white component (e.g. SK6812-RGBW)
* @note Also see `led_strip_set_pixel` if you only want to specify the RGB part of the color and bypass the white component
*
* @param strip: LED strip
* @param index: index of pixel to set
* @param red: red part of color
* @param green: green part of color
* @param blue: blue part of color
* @param white: separate white component
*
* @return
* - ESP_OK: Set RGBW color for a specific pixel successfully
* - ESP_ERR_INVALID_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
* - ESP_FAIL: Set RGBW color for a specific pixel failed because other error occurred
*/
esp_err_t led_strip_set_pixel_rgbw(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white);
/**
* @brief Set HSV for a specific pixel
*
* @param strip: LED strip
* @param index: index of pixel to set
* @param hue: hue part of color (0 - 360)
* @param saturation: saturation part of color (0 - 255)
* @param value: value part of color (0 - 255)
*
* @return
* - ESP_OK: Set HSV color for a specific pixel successfully
* - ESP_ERR_INVALID_ARG: Set HSV color for a specific pixel failed because of an invalid argument
* - ESP_FAIL: Set HSV color for a specific pixel failed because other error occurred
*/
esp_err_t led_strip_set_pixel_hsv(led_strip_handle_t strip, uint32_t index, uint16_t hue, uint8_t saturation, uint8_t value);
/**
* @brief Refresh memory colors to LEDs
*
* @param strip: LED strip
*
* @return
* - ESP_OK: Refresh successfully
* - ESP_FAIL: Refresh failed because some other error occurred
*
* @note:
* After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
*/
esp_err_t led_strip_refresh(led_strip_handle_t strip);
/**
* @brief Clear LED strip (turn off all LEDs)
*
* @param strip: LED strip
*
* @return
* - ESP_OK: Clear LEDs successfully
* - ESP_FAIL: Clear LEDs failed because some other error occurred
*/
esp_err_t led_strip_clear(led_strip_handle_t strip);
/**
* @brief Free LED strip resources
*
* @param strip: LED strip
*
* @return
* - ESP_OK: Free resources successfully
* - ESP_FAIL: Free resources failed because error occurred
*/
esp_err_t led_strip_del(led_strip_handle_t strip);
#ifdef __cplusplus
}
#endif
================================================
FILE: hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h
================================================
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include
#include "esp_err.h"
#include "led_strip_types.h"
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#include "driver/rmt_types.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief LED Strip RMT specific configuration
*/
typedef struct {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
uint8_t rmt_channel; /*!< Specify the channel number, the legacy RMT driver doesn't support channel allocator */
#else // new driver supports specify the clock source and clock resolution
rmt_clock_source_t clk_src; /*!< RMT clock source */
uint32_t resolution_hz; /*!< RMT tick resolution, if set to zero, a default resolution (10MHz) will be applied */
#endif
size_t mem_block_symbols; /*!< How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size. */
struct {
uint32_t with_dma: 1; /*!< Use DMA to transmit data */
} flags; /*!< Extra driver flags */
} led_strip_rmt_config_t;
/**
* @brief Create LED strip based on RMT TX channel
*
* @param led_config LED strip configuration
* @param rmt_config RMT specific configuration
* @param ret_strip Returned LED strip handle
* @return
* - ESP_OK: create LED strip handle successfully
* - ESP_ERR_INVALID_ARG: create LED strip handle failed because of invalid argument
* - ESP_ERR_NO_MEM: create LED strip handle failed because of out of memory
* - ESP_FAIL: create LED strip handle failed because some other error
*/
esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const led_strip_rmt_config_t *rmt_config, led_strip_handle_t *ret_strip);
#ifdef __cplusplus
}
#endif
================================================
FILE: hw/bsp/espressif/components/led_strip/include/led_strip_spi.h
================================================
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include
#include "esp_err.h"
#include "driver/spi_master.h"
#include "led_strip_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief LED Strip SPI specific configuration
*/
typedef struct {
spi_clock_source_t clk_src; /*!< SPI clock source */
spi_host_device_t spi_bus; /*!< SPI bus ID. Which buses are available depends on the specific chip */
struct {
uint32_t with_dma: 1; /*!< Use DMA to transmit data */
} flags; /*!< Extra driver flags */
} led_strip_spi_config_t;
/**
* @brief Create LED strip based on SPI MOSI channel
* @note Although only the MOSI line is used for generating the signal, the whole SPI bus can't be used for other purposes.
*
* @param led_config LED strip configuration
* @param spi_config SPI specific configuration
* @param ret_strip Returned LED strip handle
* @return
* - ESP_OK: create LED strip handle successfully
* - ESP_ERR_INVALID_ARG: create LED strip handle failed because of invalid argument
* - ESP_ERR_NOT_SUPPORTED: create LED strip handle failed because of unsupported configuration
* - ESP_ERR_NO_MEM: create LED strip handle failed because of out of memory
* - ESP_FAIL: create LED strip handle failed because some other error
*/
esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const led_strip_spi_config_t *spi_config, led_strip_handle_t *ret_strip);
#ifdef __cplusplus
}
#endif
================================================
FILE: hw/bsp/espressif/components/led_strip/include/led_strip_types.h
================================================
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief LED strip pixel format
*/
typedef enum {
LED_PIXEL_FORMAT_GRB, /*!< Pixel format: GRB */
LED_PIXEL_FORMAT_GRBW, /*!< Pixel format: GRBW */
LED_PIXEL_FORMAT_INVALID /*!< Invalid pixel format */
} led_pixel_format_t;
/**
* @brief LED strip model
* @note Different led model may have different timing parameters, so we need to distinguish them.
*/
typedef enum {
LED_MODEL_WS2812, /*!< LED strip model: WS2812 */
LED_MODEL_SK6812, /*!< LED strip model: SK6812 */
LED_MODEL_INVALID /*!< Invalid LED strip model */
} led_model_t;
/**
* @brief LED strip handle
*/
typedef struct led_strip_t *led_strip_handle_t;
/**
* @brief LED Strip Configuration
*/
typedef struct {
int strip_gpio_num; /*!< GPIO number that used by LED strip */
uint32_t max_leds; /*!< Maximum LEDs in a single strip */
led_pixel_format_t led_pixel_format; /*!< LED pixel format */
led_model_t led_model; /*!< LED model */
struct {
uint32_t invert_out: 1; /*!< Invert output signal */
} flags; /*!< Extra driver flags */
} led_strip_config_t;
#ifdef __cplusplus
}
#endif
================================================
FILE: hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h
================================================
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct led_strip_t led_strip_t; /*!< Type of LED strip */
/**
* @brief LED strip interface definition
*/
struct led_strip_t {
/**
* @brief Set RGB for a specific pixel
*
* @param strip: LED strip
* @param index: index of pixel to set
* @param red: red part of color
* @param green: green part of color
* @param blue: blue part of color
*
* @return
* - ESP_OK: Set RGB for a specific pixel successfully
* - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters
* - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred
*/
esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
/**
* @brief Set RGBW for a specific pixel. Similar to `set_pixel` but also set the white component
*
* @param strip: LED strip
* @param index: index of pixel to set
* @param red: red part of color
* @param green: green part of color
* @param blue: blue part of color
* @param white: separate white component
*
* @return
* - ESP_OK: Set RGBW color for a specific pixel successfully
* - ESP_ERR_INVALID_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
* - ESP_FAIL: Set RGBW color for a specific pixel failed because other error occurred
*/
esp_err_t (*set_pixel_rgbw)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white);
/**
* @brief Refresh memory colors to LEDs
*
* @param strip: LED strip
* @param timeout_ms: timeout value for refreshing task
*
* @return
* - ESP_OK: Refresh successfully
* - ESP_FAIL: Refresh failed because some other error occurred
*
* @note:
* After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
*/
esp_err_t (*refresh)(led_strip_t *strip);
/**
* @brief Clear LED strip (turn off all LEDs)
*
* @param strip: LED strip
* @param timeout_ms: timeout value for clearing task
*
* @return
* - ESP_OK: Clear LEDs successfully
* - ESP_FAIL: Clear LEDs failed because some other error occurred
*/
esp_err_t (*clear)(led_strip_t *strip);
/**
* @brief Free LED strip resources
*
* @param strip: LED strip
*
* @return
* - ESP_OK: Free resources successfully
* - ESP_FAIL: Free resources failed because error occurred
*/
esp_err_t (*del)(led_strip_t *strip);
};
#ifdef __cplusplus
}
#endif
================================================
FILE: hw/bsp/espressif/components/led_strip/src/led_strip_api.c
================================================
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_log.h"
#include "esp_check.h"
#include "led_strip.h"
#include "led_strip_interface.h"
static const char *TAG = "led_strip";
esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
{
ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return strip->set_pixel(strip, index, red, green, blue);
}
esp_err_t led_strip_set_pixel_hsv(led_strip_handle_t strip, uint32_t index, uint16_t hue, uint8_t saturation, uint8_t value)
{
ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
uint32_t red = 0;
uint32_t green = 0;
uint32_t blue = 0;
uint32_t rgb_max = value;
uint32_t rgb_min = rgb_max * (255 - saturation) / 255.0f;
uint32_t i = hue / 60;
uint32_t diff = hue % 60;
// RGB adjustment amount by hue
uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;
switch (i) {
case 0:
red = rgb_max;
green = rgb_min + rgb_adj;
blue = rgb_min;
break;
case 1:
red = rgb_max - rgb_adj;
green = rgb_max;
blue = rgb_min;
break;
case 2:
red = rgb_min;
green = rgb_max;
blue = rgb_min + rgb_adj;
break;
case 3:
red = rgb_min;
green = rgb_max - rgb_adj;
blue = rgb_max;
break;
case 4:
red = rgb_min + rgb_adj;
green = rgb_min;
blue = rgb_max;
break;
default:
red = rgb_max;
green = rgb_min;
blue = rgb_max - rgb_adj;
break;
}
return strip->set_pixel(strip, index, red, green, blue);
}
esp_err_t led_strip_set_pixel_rgbw(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white)
{
ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return strip->set_pixel_rgbw(strip, index, red, green, blue, white);
}
esp_err_t led_strip_refresh(led_strip_handle_t strip)
{
ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return strip->refresh(strip);
}
esp_err_t led_strip_clear(led_strip_handle_t strip)
{
ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return strip->clear(strip);
}
esp_err_t led_strip_del(led_strip_handle_t strip)
{
ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return strip->del(strip);
}
================================================
FILE: hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c
================================================
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include