mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
Merge pull request #2104 from hathach/g4-pd
Initial support for USB PD stack
This commit is contained in:
commit
bbc76e7777
10
.idea/runConfigurations/stm32g474_jlink.xml
generated
Normal file
10
.idea/runConfigurations/stm32g474_jlink.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="stm32g474 jlink" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "stm32g474re" -if swd -speed 100000 -port 25321 -swoport 25322 -TelnetPort 25323 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="cdc_msc" TARGET_NAME="cdc_msc" CONFIG_NAME="b_g474e_dpow1" version="1" RUN_TARGET_PROJECT_NAME="cdc_msc" RUN_TARGET_NAME="cdc_msc">
|
||||
<custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD">
|
||||
<debugger kind="GDB" isBundled="true" />
|
||||
</custom-gdb-server>
|
||||
<method v="2">
|
||||
<option name="CLION.COMPOUND.BUILD" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
11
README.rst
11
README.rst
@ -20,8 +20,8 @@ Please take a look at the online `documentation <https://docs.tinyusb.org/>`__.
|
||||
├── docs # Documentation
|
||||
├── examples # Sample with Makefile build support
|
||||
├── hw
|
||||
│ ├── bsp # Supported boards source files
|
||||
│ └── mcu # Low level mcu core & peripheral drivers
|
||||
│ ├── bsp # Supported boards source files
|
||||
│ └── mcu # Low level mcu core & peripheral drivers
|
||||
├── lib # Sources from 3rd party such as freeRTOS, fatfs ...
|
||||
├── src # All sources files for TinyUSB stack itself.
|
||||
├── test # Unit tests for the stack
|
||||
@ -89,6 +89,13 @@ Host Stack
|
||||
- Mass Storage Class (MSC)
|
||||
- Hub with multiple-level support
|
||||
|
||||
TypeC PD Stack
|
||||
==============
|
||||
|
||||
- Power Delivery 3.0 (PD3.0) with USB Type-C support (WIP)
|
||||
- Super early stage, only for testing purpose
|
||||
- Only support STM32 G4
|
||||
|
||||
OS Abstraction layer
|
||||
====================
|
||||
|
||||
|
@ -8,3 +8,4 @@ project(tinyusb_examples C CXX ASM)
|
||||
add_subdirectory(device)
|
||||
add_subdirectory(dual)
|
||||
add_subdirectory(host)
|
||||
add_subdirectory(typec)
|
||||
|
9
examples/typec/CMakeLists.txt
Normal file
9
examples/typec/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.17)
|
||||
|
||||
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)
|
32
examples/typec/power_delivery/CMakeLists.txt
Normal file
32
examples/typec/power_delivery/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 3.17)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT} C CXX ASM)
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Espressif has its own cmake build system
|
||||
if(FAMILY STREQUAL "espressif")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
)
|
||||
|
||||
# Example include
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example... see the corresponding function
|
||||
# in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_device_example(${PROJECT})
|
11
examples/typec/power_delivery/Makefile
Normal file
11
examples/typec/power_delivery/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
include ../../make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
$(TOP)/hw \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE += $(wildcard src/*.c)
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
include ../../rules.mk
|
1
examples/typec/power_delivery/only.txt
Normal file
1
examples/typec/power_delivery/only.txt
Normal file
@ -0,0 +1 @@
|
||||
mcu:STM32G4
|
195
examples/typec/power_delivery/src/main.c
Normal file
195
examples/typec/power_delivery/src/main.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.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);
|
||||
|
||||
uint32_t start_ms = 0;
|
||||
bool led_state = false;
|
||||
|
||||
while (1) {
|
||||
led_blinking_task();
|
||||
|
||||
// tinyusb typec task
|
||||
tuc_task();
|
||||
}
|
||||
}
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
|
||||
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; i<header->n_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] %lu mV %lu 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) {
|
||||
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 ( board_millis() - 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
|
||||
}
|
79
examples/typec/power_delivery/src/tusb_config.h
Normal file
79
examples/typec/power_delivery/src/tusb_config.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
// 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
|
||||
#define tud_int_handler(x)
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// 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
|
||||
|
||||
// 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_ */
|
@ -71,11 +71,12 @@ TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count)
|
||||
{
|
||||
(void) fhdl;
|
||||
uint8_t const* buf8 = (uint8_t const*) buf;
|
||||
for(size_t i=0; i<count; i++)
|
||||
{
|
||||
|
||||
for(size_t i=0; i<count; i++) {
|
||||
ITM_SendChar(buf8[i]);
|
||||
}
|
||||
return count;
|
||||
|
||||
return (int) count;
|
||||
}
|
||||
|
||||
TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count)
|
||||
|
@ -98,6 +98,18 @@ function(family_initialize_project PROJECT DIR)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Add segger rtt to example
|
||||
function(family_add_segger_rtt TARGET)
|
||||
if (NOT TARGET segger_rtt)
|
||||
add_library(segger_rtt STATIC
|
||||
${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c
|
||||
)
|
||||
target_include_directories(segger_rtt PUBLIC ${TOP}/lib/SEGGER_RTT/RTT)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${TARGET} PUBLIC segger_rtt)
|
||||
endfunction()
|
||||
|
||||
#------------------------------------
|
||||
# Main target configure
|
||||
#------------------------------------
|
||||
@ -116,6 +128,15 @@ function(family_configure_common TARGET)
|
||||
"LINKER:-Map=$<TARGET_FILE:${TARGET}>.map"
|
||||
)
|
||||
endif()
|
||||
|
||||
# LOGGER
|
||||
if (DEFINED LOGGER)
|
||||
target_compile_definitions(${TARGET} PUBLIC LOGGER_${LOGGER})
|
||||
if(LOGGER STREQUAL "RTT" OR LOGGER STREQUAL "rtt")
|
||||
family_add_segger_rtt(${TARGET})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
endfunction()
|
||||
|
||||
|
||||
@ -137,12 +158,11 @@ function(family_add_tinyusb TARGET OPT_MCU)
|
||||
set(TINYUSB_TARGET_PREFIX ${TARGET}-)
|
||||
add_library(${TARGET}-tinyusb_config INTERFACE)
|
||||
|
||||
target_include_directories(${TARGET}-tinyusb_config INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE
|
||||
CFG_TUSB_MCU=${OPT_MCU}
|
||||
)
|
||||
target_include_directories(${TARGET}-tinyusb_config INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_MCU=${OPT_MCU})
|
||||
if (DEFINED LOG)
|
||||
target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_DEBUG=${LOG})
|
||||
endif()
|
||||
|
||||
# tinyusb's CMakeList.txt
|
||||
add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb)
|
||||
|
@ -57,6 +57,8 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// RCC Clock
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// CPU Frequency (Core Clock) is 170 MHz
|
||||
static inline void board_clock_init(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
@ -67,8 +69,8 @@ static inline void board_clock_init(void)
|
||||
|
||||
/* Activate PLL with HSI as source */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
|
||||
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
|
||||
|
194
hw/bsp/stm32g4/boards/b_g474e_dpow1/cubemx/board.ioc
Normal file
194
hw/bsp/stm32g4/boards/b_g474e_dpow1/cubemx/board.ioc
Normal file
@ -0,0 +1,194 @@
|
||||
#MicroXplorer Configuration settings - do not modify
|
||||
CAD.formats=
|
||||
CAD.pinconfig=
|
||||
CAD.provider=
|
||||
Dma.Request0=UCPD1_RX
|
||||
Dma.Request1=UCPD1_TX
|
||||
Dma.RequestsNb=2
|
||||
Dma.UCPD1_RX.0.Direction=DMA_PERIPH_TO_MEMORY
|
||||
Dma.UCPD1_RX.0.EventEnable=DISABLE
|
||||
Dma.UCPD1_RX.0.Instance=DMA1_Channel1
|
||||
Dma.UCPD1_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
||||
Dma.UCPD1_RX.0.MemInc=DMA_MINC_ENABLE
|
||||
Dma.UCPD1_RX.0.Mode=DMA_NORMAL
|
||||
Dma.UCPD1_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
||||
Dma.UCPD1_RX.0.PeriphInc=DMA_PINC_DISABLE
|
||||
Dma.UCPD1_RX.0.Polarity=HAL_DMAMUX_REQ_GEN_RISING
|
||||
Dma.UCPD1_RX.0.Priority=DMA_PRIORITY_HIGH
|
||||
Dma.UCPD1_RX.0.RequestNumber=1
|
||||
Dma.UCPD1_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
|
||||
Dma.UCPD1_RX.0.SignalID=NONE
|
||||
Dma.UCPD1_RX.0.SyncEnable=DISABLE
|
||||
Dma.UCPD1_RX.0.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
|
||||
Dma.UCPD1_RX.0.SyncRequestNumber=1
|
||||
Dma.UCPD1_RX.0.SyncSignalID=NONE
|
||||
Dma.UCPD1_TX.1.Direction=DMA_MEMORY_TO_PERIPH
|
||||
Dma.UCPD1_TX.1.EventEnable=DISABLE
|
||||
Dma.UCPD1_TX.1.Instance=DMA1_Channel2
|
||||
Dma.UCPD1_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
||||
Dma.UCPD1_TX.1.MemInc=DMA_MINC_ENABLE
|
||||
Dma.UCPD1_TX.1.Mode=DMA_NORMAL
|
||||
Dma.UCPD1_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
||||
Dma.UCPD1_TX.1.PeriphInc=DMA_PINC_DISABLE
|
||||
Dma.UCPD1_TX.1.Polarity=HAL_DMAMUX_REQ_GEN_RISING
|
||||
Dma.UCPD1_TX.1.Priority=DMA_PRIORITY_HIGH
|
||||
Dma.UCPD1_TX.1.RequestNumber=1
|
||||
Dma.UCPD1_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
|
||||
Dma.UCPD1_TX.1.SignalID=NONE
|
||||
Dma.UCPD1_TX.1.SyncEnable=DISABLE
|
||||
Dma.UCPD1_TX.1.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
|
||||
Dma.UCPD1_TX.1.SyncRequestNumber=1
|
||||
Dma.UCPD1_TX.1.SyncSignalID=NONE
|
||||
File.Version=6
|
||||
GPIO.groupedBy=Group By Peripherals
|
||||
KeepUserPlacement=true
|
||||
Mcu.CPN=STM32G474RET3
|
||||
Mcu.Family=STM32G4
|
||||
Mcu.IP0=DMA
|
||||
Mcu.IP1=NVIC
|
||||
Mcu.IP2=RCC
|
||||
Mcu.IP3=SYS
|
||||
Mcu.IP4=UCPD1
|
||||
Mcu.IP5=USART3
|
||||
Mcu.IPNb=6
|
||||
Mcu.Name=STM32G474R(B-C-E)Tx
|
||||
Mcu.Package=LQFP64
|
||||
Mcu.Pin0=PC10
|
||||
Mcu.Pin1=PC11
|
||||
Mcu.Pin2=PB4
|
||||
Mcu.Pin3=PB6
|
||||
Mcu.Pin4=VP_SYS_VS_Systick
|
||||
Mcu.Pin5=VP_SYS_VS_DBSignals
|
||||
Mcu.PinsNb=6
|
||||
Mcu.ThirdPartyNb=0
|
||||
Mcu.UserConstants=
|
||||
Mcu.UserName=STM32G474RETx
|
||||
MxCube.Version=6.8.1
|
||||
MxDb.Version=DB.6.0.81
|
||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false
|
||||
NVIC.DMA1_Channel1_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
|
||||
NVIC.DMA1_Channel2_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
|
||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false
|
||||
NVIC.ForceEnableDMAVector=true
|
||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false
|
||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
|
||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
|
||||
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:false
|
||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false
|
||||
PB4.Mode=Sink_AllSignals
|
||||
PB4.Signal=UCPD1_CC2
|
||||
PB6.Mode=Sink_AllSignals
|
||||
PB6.Signal=UCPD1_CC1
|
||||
PC10.GPIOParameters=GPIO_PuPd
|
||||
PC10.GPIO_PuPd=GPIO_PULLUP
|
||||
PC10.Mode=Asynchronous
|
||||
PC10.Signal=USART3_TX
|
||||
PC11.GPIOParameters=GPIO_PuPd
|
||||
PC11.GPIO_PuPd=GPIO_PULLUP
|
||||
PC11.Mode=Asynchronous
|
||||
PC11.Signal=USART3_RX
|
||||
PinOutPanel.RotationAngle=0
|
||||
ProjectManager.AskForMigrate=true
|
||||
ProjectManager.BackupPrevious=false
|
||||
ProjectManager.CompilerOptimize=6
|
||||
ProjectManager.ComputerToolchain=false
|
||||
ProjectManager.CoupleFile=false
|
||||
ProjectManager.CustomerFirmwarePackage=
|
||||
ProjectManager.DefaultFWLocation=true
|
||||
ProjectManager.DeletePrevious=true
|
||||
ProjectManager.DeviceId=STM32G474RETx
|
||||
ProjectManager.FirmwarePackage=STM32Cube FW_G4 V1.5.1
|
||||
ProjectManager.FreePins=false
|
||||
ProjectManager.HalAssertFull=false
|
||||
ProjectManager.HeapSize=0x200
|
||||
ProjectManager.KeepUserCode=true
|
||||
ProjectManager.LastFirmware=true
|
||||
ProjectManager.LibraryCopy=2
|
||||
ProjectManager.MainLocation=Src
|
||||
ProjectManager.NoMain=false
|
||||
ProjectManager.PreviousToolchain=
|
||||
ProjectManager.ProjectBuild=false
|
||||
ProjectManager.ProjectFileName=board.ioc
|
||||
ProjectManager.ProjectName=board
|
||||
ProjectManager.ProjectStructure=
|
||||
ProjectManager.RegisterCallBack=
|
||||
ProjectManager.StackSize=0x400
|
||||
ProjectManager.TargetToolchain=Makefile
|
||||
ProjectManager.ToolChainLocation=
|
||||
ProjectManager.UnderRoot=false
|
||||
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART3_UART_Init-USART3-false-HAL-true,5-MX_UCPD1_Init-UCPD1-false-LL-true
|
||||
RCC.ADC12Freq_Value=150000000
|
||||
RCC.ADC345Freq_Value=150000000
|
||||
RCC.AHBFreq_Value=150000000
|
||||
RCC.APB1Freq_Value=150000000
|
||||
RCC.APB1TimFreq_Value=150000000
|
||||
RCC.APB2Freq_Value=150000000
|
||||
RCC.APB2TimFreq_Value=150000000
|
||||
RCC.CRSFreq_Value=48000000
|
||||
RCC.CortexFreq_Value=150000000
|
||||
RCC.EXTERNAL_CLOCK_VALUE=12288000
|
||||
RCC.FCLKCortexFreq_Value=150000000
|
||||
RCC.FDCANFreq_Value=150000000
|
||||
RCC.FamilyName=M
|
||||
RCC.HCLKFreq_Value=150000000
|
||||
RCC.HRTIM1Freq_Value=150000000
|
||||
RCC.HSE_VALUE=24000000
|
||||
RCC.HSI48_VALUE=48000000
|
||||
RCC.HSI_VALUE=16000000
|
||||
RCC.I2C1Freq_Value=150000000
|
||||
RCC.I2C2Freq_Value=150000000
|
||||
RCC.I2C3Freq_Value=150000000
|
||||
RCC.I2C4Freq_Value=150000000
|
||||
RCC.I2SFreq_Value=150000000
|
||||
RCC.IPParameters=ADC12Freq_Value,ADC345Freq_Value,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CRSFreq_Value,CortexFreq_Value,EXTERNAL_CLOCK_VALUE,FCLKCortexFreq_Value,FDCANFreq_Value,FamilyName,HCLKFreq_Value,HRTIM1Freq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,I2C4Freq_Value,I2SFreq_Value,LPTIM1Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSE_VALUE,LSI_VALUE,MCO1PinFreq_Value,PLLM,PLLN,PLLPoutputFreq_Value,PLLQ,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PWRFreq_Value,QSPIFreq_Value,RNGFreq_Value,SAI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value
|
||||
RCC.LPTIM1Freq_Value=150000000
|
||||
RCC.LPUART1Freq_Value=150000000
|
||||
RCC.LSCOPinFreq_Value=32000
|
||||
RCC.LSE_VALUE=32768
|
||||
RCC.LSI_VALUE=32000
|
||||
RCC.MCO1PinFreq_Value=16000000
|
||||
RCC.PLLM=RCC_PLLM_DIV4
|
||||
RCC.PLLN=75
|
||||
RCC.PLLPoutputFreq_Value=150000000
|
||||
RCC.PLLQ=RCC_PLLQ_DIV4
|
||||
RCC.PLLQoutputFreq_Value=75000000
|
||||
RCC.PLLRCLKFreq_Value=150000000
|
||||
RCC.PWRFreq_Value=150000000
|
||||
RCC.QSPIFreq_Value=150000000
|
||||
RCC.RNGFreq_Value=75000000
|
||||
RCC.SAI1Freq_Value=150000000
|
||||
RCC.SYSCLKFreq_VALUE=150000000
|
||||
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
||||
RCC.UART4Freq_Value=150000000
|
||||
RCC.UART5Freq_Value=150000000
|
||||
RCC.USART1Freq_Value=150000000
|
||||
RCC.USART2Freq_Value=150000000
|
||||
RCC.USART3Freq_Value=150000000
|
||||
RCC.USBFreq_Value=75000000
|
||||
RCC.VCOInputFreq_Value=4000000
|
||||
RCC.VCOOutputFreq_Value=300000000
|
||||
USART3.AutoBaudRateEnableParam=UART_ADVFEATURE_AUTOBAUDRATE_DISABLE
|
||||
USART3.BaudRate=115200
|
||||
USART3.DMADisableonRxErrorParam=ADVFEATURE_DMA_ENABLEONRXERROR
|
||||
USART3.DataInvertParam=ADVFEATURE_DATAINV_DISABLE
|
||||
USART3.IPParameters=BaudRate,WordLength,Parity,StopBits,Mode,OverSampling,OneBitSampling,AutoBaudRateEnableParam,TxPinLevelInvertParam,RxPinLevelInvertParam,DataInvertParam,SwapParam,OverrunDisableParam,DMADisableonRxErrorParam,MSBFirstParam,VirtualMode-Asynchronous
|
||||
USART3.MSBFirstParam=ADVFEATURE_MSBFIRST_DISABLE
|
||||
USART3.Mode=MODE_TX_RX
|
||||
USART3.OneBitSampling=UART_ONE_BIT_SAMPLE_DISABLE
|
||||
USART3.OverSampling=UART_OVERSAMPLING_16
|
||||
USART3.OverrunDisableParam=ADVFEATURE_OVERRUN_ENABLE
|
||||
USART3.Parity=PARITY_ODD
|
||||
USART3.RxPinLevelInvertParam=ADVFEATURE_RXINV_DISABLE
|
||||
USART3.StopBits=STOPBITS_1
|
||||
USART3.SwapParam=ADVFEATURE_SWAP_DISABLE
|
||||
USART3.TxPinLevelInvertParam=ADVFEATURE_TXINV_DISABLE
|
||||
USART3.VirtualMode-Asynchronous=VM_ASYNC
|
||||
USART3.WordLength=WORDLENGTH_8B
|
||||
VP_SYS_VS_DBSignals.Mode=DisableDeadBatterySignals
|
||||
VP_SYS_VS_DBSignals.Signal=SYS_VS_DBSignals
|
||||
VP_SYS_VS_Systick.Mode=SysTick
|
||||
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
|
||||
board=custom
|
@ -25,6 +25,8 @@
|
||||
*/
|
||||
|
||||
#include "stm32g4xx_hal.h"
|
||||
#include "stm32g4xx_ll_bus.h"
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "board.h"
|
||||
|
||||
@ -46,6 +48,11 @@ void USBWakeUp_IRQHandler(void)
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
// USB PD
|
||||
void UCPD1_IRQHandler(void) {
|
||||
tuc_int_handler(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM
|
||||
//--------------------------------------------------------------------+
|
||||
@ -82,6 +89,7 @@ void board_init(void)
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
// LED
|
||||
memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct));
|
||||
GPIO_InitStruct.Pin = LED_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
@ -91,6 +99,7 @@ void board_init(void)
|
||||
board_led_write(false);
|
||||
|
||||
// Button
|
||||
memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct));
|
||||
GPIO_InitStruct.Pin = BUTTON_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN : GPIO_PULLUP;
|
||||
@ -99,6 +108,7 @@ void board_init(void)
|
||||
|
||||
#ifdef UART_DEV
|
||||
// UART
|
||||
memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct));
|
||||
GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
@ -121,6 +131,7 @@ void board_init(void)
|
||||
|
||||
// USB Pins TODO double check USB clock and pin setup
|
||||
// Configure USB DM and DP pins. This is optional, and maintained only for user guidance.
|
||||
memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct));
|
||||
GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
@ -130,6 +141,21 @@ void board_init(void)
|
||||
__HAL_RCC_USB_CLK_ENABLE();
|
||||
|
||||
board_vbus_sense_init();
|
||||
|
||||
#if 1
|
||||
// USB PD
|
||||
// Default CC1/CC2 is PB4/PB6
|
||||
|
||||
// Enable pwr for disabling dead battery feature in Power's CR3
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_RCC_CRC_CLK_ENABLE();
|
||||
__HAL_RCC_UCPD1_CLK_ENABLE();
|
||||
|
||||
// Enable DMA for USB PD
|
||||
__HAL_RCC_DMAMUX1_CLK_ENABLE();
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -90,6 +90,7 @@ function(family_configure_example TARGET)
|
||||
target_sources(${TARGET} PUBLIC
|
||||
# TinyUSB Port
|
||||
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
|
||||
${TOP}/src/portable/st/typec/typec_stm32.c
|
||||
# BSP
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
|
||||
@ -109,7 +110,7 @@ function(family_configure_example TARGET)
|
||||
|
||||
# Flashing
|
||||
family_flash_stlink(${TARGET})
|
||||
#family_flash_jlink(${TARGET})
|
||||
family_flash_jlink(${TARGET})
|
||||
endfunction()
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
||||
* (c) 1995 - 2020 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
@ -46,7 +46,7 @@ File : SEGGER_RTT_Conf.h
|
||||
Purpose : Implementation of SEGGER real-time transfer (RTT) which
|
||||
allows real-time communication on targets which support
|
||||
debugger memory accesses while the CPU is running.
|
||||
Revision: $Rev: 18601 $
|
||||
Revision: $Rev: 24316 $
|
||||
|
||||
*/
|
||||
|
||||
@ -63,10 +63,25 @@ Revision: $Rev: 18601 $
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Take in and set to correct values for Cortex-A systems with CPU cache
|
||||
//
|
||||
//#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system
|
||||
//#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached
|
||||
//
|
||||
// Most common case:
|
||||
// Up-channel 0: RTT
|
||||
// Up-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Most common case:
|
||||
// Down-channel 0: RTT
|
||||
// Down-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3)
|
||||
#endif
|
||||
@ -135,18 +150,18 @@ Revision: $Rev: 18601 $
|
||||
#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32))
|
||||
#if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs %0, primask \n\t" \
|
||||
"movs r1, $1 \n\t" \
|
||||
"movs r1, #1 \n\t" \
|
||||
"msr primask, r1 \n\t" \
|
||||
: "=r" (LockState) \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1" \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
|
||||
: \
|
||||
: "r" (LockState) \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
@ -155,32 +170,32 @@ Revision: $Rev: 18601 $
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs %0, basepri \n\t" \
|
||||
"mov r1, %1 \n\t" \
|
||||
"msr basepri, r1 \n\t" \
|
||||
: "=r" (LockState) \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
|
||||
: "r1" \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
|
||||
: \
|
||||
: "r" (LockState) \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
|
||||
#elif defined(__ARM_ARCH_7A__)
|
||||
#elif (defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||
"mov %0, r1 \n\t" \
|
||||
"orr r1, r1, #0xC0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: "=r" (LockState) \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1" \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||
@ -190,17 +205,17 @@ Revision: $Rev: 18601 $
|
||||
"orr r1, r1, r0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: \
|
||||
: "r" (LockState) \
|
||||
: "r0", "r1" \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "r0", "r1", "cc" \
|
||||
); \
|
||||
}
|
||||
#elif defined(__riscv) || defined(__riscv_xlen)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("csrr %0, mstatus \n\t" \
|
||||
"csrci mstatus, 8 \n\t" \
|
||||
"andi %0, %0, 8 \n\t" \
|
||||
: "=r" (LockState) \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: \
|
||||
);
|
||||
@ -209,7 +224,7 @@ Revision: $Rev: 18601 $
|
||||
"or %0, %0, a1 \n\t" \
|
||||
"csrs mstatus, %0 \n\t" \
|
||||
: \
|
||||
: "r" (LockState) \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "a1" \
|
||||
); \
|
||||
}
|
||||
@ -227,11 +242,11 @@ Revision: $Rev: 18601 $
|
||||
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \
|
||||
(defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
LockState = __get_PRIMASK(); \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||
__set_PRIMASK(1);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \
|
||||
(defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \
|
||||
@ -241,11 +256,35 @@ Revision: $Rev: 18601 $
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
LockState = __get_BASEPRI(); \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_BASEPRI(); \
|
||||
__set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \
|
||||
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \
|
||||
(defined (__ARM7R__) && (__CORE__ == __ARM7R__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||
"mov %0, r1 \n\t" \
|
||||
"orr r1, r1, #0xC0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||
"mrs r1, CPSR \n\t" \
|
||||
"bic r1, r1, #0xC0 \n\t" \
|
||||
"and r0, r0, #0xC0 \n\t" \
|
||||
"orr r1, r1, r0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "r0", "r1", "cc" \
|
||||
); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -256,11 +295,11 @@ Revision: $Rev: 18601 $
|
||||
*/
|
||||
#ifdef __ICCRX__
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned long LockState; \
|
||||
LockState = __get_interrupt_state(); \
|
||||
unsigned long _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||
__disable_interrupt();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -270,11 +309,11 @@ Revision: $Rev: 18601 $
|
||||
*/
|
||||
#ifdef __ICCRL78__
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
__istate_t LockState; \
|
||||
LockState = __get_interrupt_state(); \
|
||||
__istate_t _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||
__disable_interrupt();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -285,13 +324,13 @@ Revision: $Rev: 18601 $
|
||||
#ifdef __CC_ARM
|
||||
#if (defined __TARGET_ARCH_6S_M)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
register unsigned char PRIMASK __asm( "primask"); \
|
||||
LockState = PRIMASK; \
|
||||
PRIMASK = 1u; \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \
|
||||
_SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \
|
||||
_SEGGER_RTT__PRIMASK = 1u; \
|
||||
__schedule_barrier();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \
|
||||
#define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \
|
||||
__schedule_barrier(); \
|
||||
}
|
||||
#elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
|
||||
@ -299,13 +338,13 @@ Revision: $Rev: 18601 $
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
register unsigned char BASEPRI __asm( "basepri"); \
|
||||
LockState = BASEPRI; \
|
||||
_SEGGER_RTT__LockState = BASEPRI; \
|
||||
BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
|
||||
__schedule_barrier();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \
|
||||
#define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \
|
||||
__schedule_barrier(); \
|
||||
}
|
||||
#endif
|
||||
@ -318,21 +357,21 @@ Revision: $Rev: 18601 $
|
||||
#ifdef __TI_ARM__
|
||||
#if defined (__TI_ARM_V6M0__)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
LockState = __get_PRIMASK(); \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||
__set_PRIMASK(1);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int LockState; \
|
||||
LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \
|
||||
#define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -342,12 +381,13 @@ Revision: $Rev: 18601 $
|
||||
* RTT lock configuration for CCRX
|
||||
*/
|
||||
#ifdef __RX
|
||||
#include <machine.h>
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned long LockState; \
|
||||
LockState = get_psw() & 0x010000; \
|
||||
unsigned long _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = get_psw() & 0x010000; \
|
||||
clrpsw_i();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \
|
||||
#define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
36
lib/SEGGER_RTT/LICENSE.md
Normal file
36
lib/SEGGER_RTT/LICENSE.md
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
SEGGER Microcontroller GmbH
|
||||
The Embedded Experts
|
||||
|
||||
(c) 1995 - 2021 SEGGER Microcontroller GmbH
|
||||
www.segger.com Support: support@segger.com
|
||||
|
||||
SEGGER RTT Real Time Transfer for embedded targets
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
SEGGER strongly recommends to not make any changes
|
||||
to or modify the source code of this software in order to stay
|
||||
compatible with the RTT protocol and J-Link.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, are permitted provided that the following
|
||||
condition is met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this condition and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
@ -1,34 +0,0 @@
|
||||
Important - Read carefully:
|
||||
|
||||
SEGGER RTT - Real Time Transfer for embedded targets
|
||||
|
||||
All rights reserved.
|
||||
|
||||
SEGGER strongly recommends to not make any changes
|
||||
to or modify the source code of this software in order to stay
|
||||
compatible with the RTT protocol and J-Link.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, are permitted provided that the following
|
||||
condition is met:
|
||||
|
||||
o Redistributions of source code must retain the above copyright
|
||||
notice, this condition and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
|
||||
(c) 2014 - 2016 SEGGER Microcontroller GmbH
|
||||
www.segger.com
|
24
lib/SEGGER_RTT/README.md
Normal file
24
lib/SEGGER_RTT/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
RTT
|
||||
===
|
||||
|
||||
SEGGER RTT Sources
|
||||
|
||||
https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer
|
||||
https://wiki.segger.com/RTT
|
||||
|
||||
## Included files
|
||||
|
||||
* `RTT/`
|
||||
* `SEGGER_RTT.c` - Main module for RTT.
|
||||
* `SEGGER_RTT.h` - Main header for RTT.
|
||||
* `SEGGER_RTT_ASM_ARMv7M.S` - Assembly-optimized implementation of RTT functions for ARMv7M processors.
|
||||
* `SEGGER_RTT_Printf.c` - Simple implementation of printf (`SEGGER_RTT_Printf()`) to write formatted strings via RTT.
|
||||
* `Syscalls/`
|
||||
* `SEGGER_RTT_Syscalls_*.c` - Low-level syscalls to retarget `printf()` to RTT with different toolchains.
|
||||
* `Config/`
|
||||
* `SEGGER_RTT_Conf.h` - RTT configuration file.
|
||||
* `Examples/`
|
||||
* `Main_RTT_InputEchoApp.c` - Example application which echoes input on Channel 0.
|
||||
* `Main_RTT_MenuApp.c` - Example application to demonstrate RTT bi-directional functionality.
|
||||
* `Main_RTT_PrintfTest.c` - Example application to test RTT's simple printf implementation.
|
||||
* `Main_RTT_SpeedTestApp.c` - Example application to measure RTT performance. (Requires embOS)
|
@ -1,20 +0,0 @@
|
||||
README.txt for the SEGGER RTT Implementation Pack.
|
||||
|
||||
Included files:
|
||||
===============
|
||||
Root Directory
|
||||
- Examples
|
||||
- Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0.
|
||||
- Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality.
|
||||
- Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation.
|
||||
- Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed.
|
||||
- RTT
|
||||
- SEGGER_RTT.c - The RTT implementation.
|
||||
- SEGGER_RTT.h - Header for RTT implementation.
|
||||
- SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation.
|
||||
- SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT.
|
||||
- Syscalls
|
||||
- RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib.
|
||||
- RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler.
|
||||
- RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler.
|
||||
- RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio.
|
File diff suppressed because it is too large
Load Diff
@ -46,16 +46,14 @@ File : SEGGER_RTT.h
|
||||
Purpose : Implementation of SEGGER real-time transfer which allows
|
||||
real-time communication on targets which support debugger
|
||||
memory accesses while the CPU is running.
|
||||
Revision: $Rev: 17697 $
|
||||
Revision: $Rev: 25842 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_H
|
||||
#define SEGGER_RTT_H
|
||||
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
|
||||
|
||||
#include "../Config/SEGGER_RTT_Conf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
@ -63,46 +61,168 @@ Revision: $Rev: 17697 $
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RTT_USE_ASM
|
||||
#if (defined __SES_ARM) // SEGGER Embedded Studio
|
||||
//
|
||||
// Some cores support out-of-order memory accesses (reordering of memory accesses in the core)
|
||||
// For such cores, we need to define a memory barrier to guarantee the order of certain accesses to the RTT ring buffers.
|
||||
// Needed for:
|
||||
// Cortex-M7 (ARMv7-M)
|
||||
// Cortex-M23 (ARM-v8M)
|
||||
// Cortex-M33 (ARM-v8M)
|
||||
// Cortex-A/R (ARM-v7A/R)
|
||||
//
|
||||
// We do not explicitly check for "Embedded Studio" as the compiler in use determines what we support.
|
||||
// You can use an external toolchain like IAR inside ES. So there is no point in checking for "Embedded Studio"
|
||||
//
|
||||
#if (defined __CROSSWORKS_ARM) // Rowley Crossworks
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __CROSSWORKS_ARM) // Rowley Crossworks
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __GNUC__) // GCC
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __clang__) // Clang compiler
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __IASMARM__) // IAR assembler
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ICCARM__) // IAR compiler
|
||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif (defined __ARMCC_VERSION)
|
||||
//
|
||||
// ARM compiler
|
||||
// ARM compiler V6.0 and later is clang based.
|
||||
// Our ASM part is compatible to clang.
|
||||
//
|
||||
#if (__ARMCC_VERSION >= 6000000)
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#else
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3/4
|
||||
#if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture
|
||||
#elif (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M7
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM7M__) // IAR Cortex-M3/4
|
||||
#if (__CORE__ == __ARM7M__)
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif (defined __ARM7EM__) // IAR Cortex-M7
|
||||
#if (__CORE__ == __ARM7EM__)
|
||||
#elif ((defined __GNUC__) || (defined __clang__))
|
||||
//
|
||||
// GCC / Clang
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
// ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__
|
||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here...
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif ((defined __IASMARM__) || (defined __ICCARM__))
|
||||
//
|
||||
// IAR assembler/compiler
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#if (__VER__ < 6300000)
|
||||
#define VOLATILE
|
||||
#else
|
||||
#define VOLATILE volatile
|
||||
#endif
|
||||
#if (defined __ARM7M__) // Needed for old versions that do not know the define yet
|
||||
#if (__CORE__ == __ARM7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7EM__)
|
||||
#if (__CORE__ == __ARM7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8M_BASELINE__)
|
||||
#if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8M_MAINLINE__)
|
||||
#if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8EM_MAINLINE__)
|
||||
#if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-???
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7A__)
|
||||
#if (__CORE__ == __ARM7A__) // Cortex-A 32-bit ARMv7-A
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7R__)
|
||||
#if (__CORE__ == __ARM7R__) // Cortex-R 32-bit ARMv7-R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
// TBD: __ARM8A__ => Cortex-A 64-bit ARMv8-A
|
||||
// TBD: __ARM8R__ => Cortex-R 64-bit ARMv8-R
|
||||
#else
|
||||
//
|
||||
// Other compilers
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
//
|
||||
// If IDE and core support the ASM version, enable ASM version by default
|
||||
//
|
||||
#ifndef _CORE_HAS_RTT_ASM_SUPPORT
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores
|
||||
#endif
|
||||
#if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT)
|
||||
#define RTT_USE_ASM (1)
|
||||
#else
|
||||
@ -110,6 +230,35 @@ Revision: $Rev: 17697 $
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _CORE_NEEDS_DMB
|
||||
#define _CORE_NEEDS_DMB 0
|
||||
#endif
|
||||
|
||||
#ifndef RTT__DMB
|
||||
#if _CORE_NEEDS_DMB
|
||||
#error "Don't know how to place inline assembly for DMB"
|
||||
#else
|
||||
#define RTT__DMB()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_UNCACHED_OFF
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||
#else
|
||||
#define SEGGER_RTT_UNCACHED_OFF (0)
|
||||
#endif
|
||||
#endif
|
||||
#if RTT_USE_ASM
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
@ -121,6 +270,21 @@ Revision: $Rev: 17697 $
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Determine how much we must pad the control block to make it a multiple of a cache line in size
|
||||
// Assuming: U8 = 1B
|
||||
// U16 = 2B
|
||||
// U32 = 4B
|
||||
// U8/U16/U32* = 4B
|
||||
//
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache
|
||||
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE)
|
||||
#else
|
||||
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes)
|
||||
#endif
|
||||
#define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24))
|
||||
#define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
@ -138,7 +302,7 @@ typedef struct {
|
||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||
unsigned WrOff; // Position of next item to be written by either target.
|
||||
volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host.
|
||||
unsigned Flags; // Contains configuration flags
|
||||
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||
} SEGGER_RTT_BUFFER_UP;
|
||||
|
||||
//
|
||||
@ -151,7 +315,7 @@ typedef struct {
|
||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||
volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host.
|
||||
unsigned RdOff; // Position of next item to be read by target (down-buffer).
|
||||
unsigned Flags; // Contains configuration flags
|
||||
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||
} SEGGER_RTT_BUFFER_DOWN;
|
||||
|
||||
//
|
||||
@ -165,6 +329,9 @@ typedef struct {
|
||||
int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
|
||||
SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host
|
||||
SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target
|
||||
#if SEGGER_RTT__CB_PADDING
|
||||
unsigned char aDummy[SEGGER_RTT__CB_PADDING];
|
||||
#endif
|
||||
} SEGGER_RTT_CB;
|
||||
|
||||
/*********************************************************************
|
||||
@ -214,7 +381,7 @@ unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex);
|
||||
//
|
||||
// Function macro for performance optimization
|
||||
//
|
||||
#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff)
|
||||
#define SEGGER_RTT_HASDATA(n) (((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff)
|
||||
|
||||
#if RTT_USE_ASM
|
||||
#define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock
|
||||
@ -231,7 +398,7 @@ unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pDa
|
||||
unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
|
||||
#define SEGGER_RTT_HASDATA_UP(n) (_SEGGER_RTT.aUp[n].WrOff - _SEGGER_RTT.aUp[n].RdOff)
|
||||
#define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
|
@ -23,6 +23,7 @@ Additional information:
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#define _CCIAR 0
|
||||
#define _CCCLANG 1
|
||||
|
||||
@ -182,6 +183,9 @@ _LoopCopyStraight: // memcpy(pRing->pBuffer + WrOf
|
||||
SUBS R2,R2,#+1
|
||||
BNE _LoopCopyStraight
|
||||
_CSDone:
|
||||
#if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here
|
||||
DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the <WrOff> in the struct
|
||||
#endif
|
||||
STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes;
|
||||
MOVS R0,#+1
|
||||
POP {R4-R7}
|
||||
@ -214,6 +218,9 @@ _LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData
|
||||
SUBS R2,R2,#+1
|
||||
BNE _LoopCopyAfterWrapAround
|
||||
_No2ChunkNeeded:
|
||||
#if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here
|
||||
DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the <WrOff> in the struct
|
||||
#endif
|
||||
STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer
|
||||
MOVS R0,#+1
|
||||
POP {R4-R7}
|
||||
|
@ -1,500 +0,0 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_printf.c
|
||||
Purpose : Replacement for printf to write formatted data via RTT
|
||||
Revision: $Rev: 17697 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
|
||||
#define FORMAT_FLAG_PAD_ZERO (1u << 1)
|
||||
#define FORMAT_FLAG_PRINT_SIGN (1u << 2)
|
||||
#define FORMAT_FLAG_ALTERNATE (1u << 3)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char* pBuffer;
|
||||
unsigned BufferSize;
|
||||
unsigned Cnt;
|
||||
|
||||
int ReturnValue;
|
||||
|
||||
unsigned RTTBufferIndex;
|
||||
} SEGGER_RTT_PRINTF_DESC;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Static code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* _StoreChar
|
||||
*/
|
||||
static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
|
||||
unsigned Cnt;
|
||||
|
||||
Cnt = p->Cnt;
|
||||
if ((Cnt + 1u) <= p->BufferSize) {
|
||||
*(p->pBuffer + Cnt) = c;
|
||||
p->Cnt = Cnt + 1u;
|
||||
p->ReturnValue++;
|
||||
}
|
||||
//
|
||||
// Write part of string, when the buffer is full
|
||||
//
|
||||
if (p->Cnt == p->BufferSize) {
|
||||
if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
|
||||
p->ReturnValue = -1;
|
||||
} else {
|
||||
p->Cnt = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _PrintUnsigned
|
||||
*/
|
||||
static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||
static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
unsigned Div;
|
||||
unsigned Digit;
|
||||
unsigned Number;
|
||||
unsigned Width;
|
||||
char c;
|
||||
|
||||
Number = v;
|
||||
Digit = 1u;
|
||||
//
|
||||
// Get actual field width
|
||||
//
|
||||
Width = 1u;
|
||||
while (Number >= Base) {
|
||||
Number = (Number / Base);
|
||||
Width++;
|
||||
}
|
||||
if (NumDigits > Width) {
|
||||
Width = NumDigits;
|
||||
}
|
||||
//
|
||||
// Print leading chars if necessary
|
||||
//
|
||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
|
||||
if (FieldWidth != 0u) {
|
||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, c);
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Compute Digit.
|
||||
// Loop until Digit has the value of the highest digit required.
|
||||
// Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
|
||||
//
|
||||
while (1) {
|
||||
if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
|
||||
NumDigits--;
|
||||
} else {
|
||||
Div = v / Digit;
|
||||
if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
|
||||
break;
|
||||
}
|
||||
}
|
||||
Digit *= Base;
|
||||
}
|
||||
//
|
||||
// Output digits
|
||||
//
|
||||
do {
|
||||
Div = v / Digit;
|
||||
v -= Div * Digit;
|
||||
_StoreChar(pBufferDesc, _aV2C[Div]);
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
Digit /= Base;
|
||||
} while (Digit);
|
||||
//
|
||||
// Print trailing spaces if necessary
|
||||
//
|
||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, ' ');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _PrintInt
|
||||
*/
|
||||
static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||
unsigned Width;
|
||||
int Number;
|
||||
|
||||
Number = (v < 0) ? -v : v;
|
||||
|
||||
//
|
||||
// Get actual field width
|
||||
//
|
||||
Width = 1u;
|
||||
while (Number >= (int)Base) {
|
||||
Number = (Number / (int)Base);
|
||||
Width++;
|
||||
}
|
||||
if (NumDigits > Width) {
|
||||
Width = NumDigits;
|
||||
}
|
||||
if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
|
||||
FieldWidth--;
|
||||
}
|
||||
|
||||
//
|
||||
// Print leading spaces if necessary
|
||||
//
|
||||
if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, ' ');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Print sign if necessary
|
||||
//
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
if (v < 0) {
|
||||
v = -v;
|
||||
_StoreChar(pBufferDesc, '-');
|
||||
} else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
|
||||
_StoreChar(pBufferDesc, '+');
|
||||
} else {
|
||||
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Print leading zeros if necessary
|
||||
//
|
||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, '0');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Print number without sign
|
||||
//
|
||||
_PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_vprintf
|
||||
*
|
||||
* Function description
|
||||
* Stores a formatted string in SEGGER RTT control block.
|
||||
* This data is read by the host.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||
* sFormat Pointer to format string
|
||||
* pParamList Pointer to the list of arguments for the format string
|
||||
*
|
||||
* Return values
|
||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||
* < 0: Error
|
||||
*/
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
|
||||
char c;
|
||||
SEGGER_RTT_PRINTF_DESC BufferDesc;
|
||||
int v;
|
||||
unsigned NumDigits;
|
||||
unsigned FormatFlags;
|
||||
unsigned FieldWidth;
|
||||
char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
|
||||
|
||||
BufferDesc.pBuffer = acBuffer;
|
||||
BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE;
|
||||
BufferDesc.Cnt = 0u;
|
||||
BufferDesc.RTTBufferIndex = BufferIndex;
|
||||
BufferDesc.ReturnValue = 0;
|
||||
|
||||
do {
|
||||
c = *sFormat;
|
||||
sFormat++;
|
||||
if (c == 0u) {
|
||||
break;
|
||||
}
|
||||
if (c == '%') {
|
||||
//
|
||||
// Filter out flags
|
||||
//
|
||||
FormatFlags = 0u;
|
||||
v = 1;
|
||||
do {
|
||||
c = *sFormat;
|
||||
switch (c) {
|
||||
case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
|
||||
case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
|
||||
case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
|
||||
case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
|
||||
default: v = 0; break;
|
||||
}
|
||||
} while (v);
|
||||
//
|
||||
// filter out field with
|
||||
//
|
||||
FieldWidth = 0u;
|
||||
do {
|
||||
c = *sFormat;
|
||||
if ((c < '0') || (c > '9')) {
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
|
||||
} while (1);
|
||||
|
||||
//
|
||||
// Filter out precision (number of digits to display)
|
||||
//
|
||||
NumDigits = 0u;
|
||||
c = *sFormat;
|
||||
if (c == '.') {
|
||||
sFormat++;
|
||||
do {
|
||||
c = *sFormat;
|
||||
if ((c < '0') || (c > '9')) {
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
NumDigits = NumDigits * 10u + ((unsigned)c - '0');
|
||||
} while (1);
|
||||
}
|
||||
//
|
||||
// Filter out length modifier
|
||||
//
|
||||
c = *sFormat;
|
||||
do {
|
||||
if ((c == 'l') || (c == 'h')) {
|
||||
sFormat++;
|
||||
c = *sFormat;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
//
|
||||
// Handle specifiers
|
||||
//
|
||||
switch (c) {
|
||||
case 'c': {
|
||||
char c0;
|
||||
v = va_arg(*pParamList, int);
|
||||
c0 = (char)v;
|
||||
_StoreChar(&BufferDesc, c0);
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'u':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
const char * s = va_arg(*pParamList, const char *);
|
||||
do {
|
||||
c = *s;
|
||||
s++;
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
_StoreChar(&BufferDesc, c);
|
||||
} while (BufferDesc.ReturnValue >= 0);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
|
||||
break;
|
||||
case '%':
|
||||
_StoreChar(&BufferDesc, '%');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
} else {
|
||||
_StoreChar(&BufferDesc, c);
|
||||
}
|
||||
} while (BufferDesc.ReturnValue >= 0);
|
||||
|
||||
if (BufferDesc.ReturnValue > 0) {
|
||||
//
|
||||
// Write remaining data, if any
|
||||
//
|
||||
if (BufferDesc.Cnt != 0u) {
|
||||
SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
|
||||
}
|
||||
BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
|
||||
}
|
||||
return BufferDesc.ReturnValue;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_printf
|
||||
*
|
||||
* Function description
|
||||
* Stores a formatted string in SEGGER RTT control block.
|
||||
* This data is read by the host.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||
* sFormat Pointer to format string, followed by the arguments for conversion
|
||||
*
|
||||
* Return values
|
||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||
* < 0: Error
|
||||
*
|
||||
* Notes
|
||||
* (1) Conversion specifications have following syntax:
|
||||
* %[flags][FieldWidth][.Precision]ConversionSpecifier
|
||||
* (2) Supported flags:
|
||||
* -: Left justify within the field width
|
||||
* +: Always print sign extension for signed conversions
|
||||
* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
|
||||
* Supported conversion specifiers:
|
||||
* c: Print the argument as one char
|
||||
* d: Print the argument as a signed integer
|
||||
* u: Print the argument as an unsigned integer
|
||||
* x: Print the argument as an hexadecimal integer
|
||||
* s: Print the string pointed to by the argument
|
||||
* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
|
||||
*/
|
||||
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
|
||||
int r;
|
||||
va_list ParamList;
|
||||
|
||||
va_start(ParamList, sFormat);
|
||||
r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
|
||||
va_end(ParamList);
|
||||
return r;
|
||||
}
|
||||
/*************************** End of file ****************************/
|
@ -1,120 +0,0 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_GCC.c
|
||||
Purpose : Low-level functions for using printf() via RTT in GCC.
|
||||
To use RTT for printf output, include this file in your
|
||||
application.
|
||||
Revision: $Rev: 17697 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM)
|
||||
|
||||
#include <reent.h> // required for _write_r
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// If necessary define the _reent struct
|
||||
// to match the one passed by the used standard library.
|
||||
//
|
||||
struct _reent;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int _write(int file, char *ptr, int len);
|
||||
int _write_r(struct _reent *r, int file, const void *ptr, int len);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _write()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* libc subroutines will use this system routine for output to all files,
|
||||
* including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
int _write(int file, char *ptr, int len) {
|
||||
(void) file; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _write_r()
|
||||
*
|
||||
* Function description
|
||||
* Low-level reentrant write function.
|
||||
* libc subroutines will use this system routine for output to all files,
|
||||
* including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
int _write_r(struct _reent *r, int file, const void *ptr, int len) {
|
||||
(void) file; /* Not used, avoid warning */
|
||||
(void) r; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
@ -1,115 +0,0 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_IAR.c
|
||||
Purpose : Low-level functions for using printf() via RTT in IAR.
|
||||
To use RTT for printf output, include this file in your
|
||||
application and set the Library Configuration to Normal.
|
||||
Revision: $Rev: 17697 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
|
||||
//
|
||||
// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h
|
||||
// shall be used instead. To not break any compatibility with older compiler versions, we have a
|
||||
// version check in here.
|
||||
//
|
||||
#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400))
|
||||
#include <LowLevelIOInterface.h>
|
||||
#else
|
||||
#include <yfuns.h>
|
||||
#endif
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#pragma module_name = "?__write"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* __write()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* Standard library subroutines will use this system routine
|
||||
* for output to all files, including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size) {
|
||||
(void) handle; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __write_buffered()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* Standard library subroutines will use this system routine
|
||||
* for output to all files, including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) {
|
||||
(void) handle; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
@ -1,386 +0,0 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : RTT_Syscalls_KEIL.c
|
||||
Purpose : Retargeting module for KEIL MDK-CM3.
|
||||
Low-level functions for using printf() via RTT
|
||||
Revision: $Rev: 17697 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifdef __CC_ARM
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rt_sys.h>
|
||||
#include <rt_misc.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
/*********************************************************************
|
||||
*
|
||||
* #pragmas
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#pragma import(__use_no_semihosting)
|
||||
|
||||
#ifdef _MICROLIB
|
||||
#pragma import(__use_full_stdio)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines non-configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/* Standard IO device handles - arbitrary, but any real file system handles must be
|
||||
less than 0x8000. */
|
||||
#define STDIN 0x8001 // Standard Input Stream
|
||||
#define STDOUT 0x8002 // Standard Output Stream
|
||||
#define STDERR 0x8003 // Standard Error Stream
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public const
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#if __ARMCC_VERSION < 5000000
|
||||
//const char __stdin_name[] = "STDIN";
|
||||
const char __stdout_name[] = "STDOUT";
|
||||
const char __stderr_name[] = "STDERR";
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _ttywrch
|
||||
*
|
||||
* Function description:
|
||||
* Outputs a character to the console
|
||||
*
|
||||
* Parameters:
|
||||
* c - character to output
|
||||
*
|
||||
*/
|
||||
void _ttywrch(int c) {
|
||||
fputc(c, stdout); // stdout
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_open
|
||||
*
|
||||
* Function description:
|
||||
* Opens the device/file in order to do read/write operations
|
||||
*
|
||||
* Parameters:
|
||||
* sName - sName of the device/file to open
|
||||
* OpenMode - This parameter is currently ignored
|
||||
*
|
||||
* Return value:
|
||||
* != 0 - Handle to the object to open, otherwise
|
||||
* == 0 -"device" is not handled by this module
|
||||
*
|
||||
*/
|
||||
FILEHANDLE _sys_open(const char * sName, int OpenMode) {
|
||||
(void)OpenMode;
|
||||
// Register standard Input Output devices.
|
||||
if (strcmp(sName, __stdout_name) == 0) {
|
||||
return (STDOUT);
|
||||
} else if (strcmp(sName, __stderr_name) == 0) {
|
||||
return (STDERR);
|
||||
} else
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_close
|
||||
*
|
||||
* Function description:
|
||||
* Closes the handle to the open device/file
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* 0 - device/file closed
|
||||
*
|
||||
*/
|
||||
int _sys_close(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return 0; // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_write
|
||||
*
|
||||
* Function description:
|
||||
* Writes the data to an open handle.
|
||||
* Currently this function only outputs data to the console
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* pBuffer - Pointer to the data that shall be written
|
||||
* NumBytes - Number of bytes to write
|
||||
* Mode - The Mode that shall be used
|
||||
*
|
||||
* Return value:
|
||||
* Number of bytes *not* written to the file/device
|
||||
*
|
||||
*/
|
||||
int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
||||
int r = 0;
|
||||
|
||||
(void)Mode;
|
||||
if (hFile == STDOUT) {
|
||||
SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes);
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_read
|
||||
*
|
||||
* Function description:
|
||||
* Reads data from an open handle.
|
||||
* Currently this modules does nothing.
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* pBuffer - Pointer to buffer to store the read data
|
||||
* NumBytes - Number of bytes to read
|
||||
* Mode - The Mode that shall be used
|
||||
*
|
||||
* Return value:
|
||||
* Number of bytes read from the file/device
|
||||
*
|
||||
*/
|
||||
int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
||||
(void)hFile;
|
||||
(void)pBuffer;
|
||||
(void)NumBytes;
|
||||
(void)Mode;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_istty
|
||||
*
|
||||
* Function description:
|
||||
* This function shall return whether the opened file
|
||||
* is a console device or not.
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* 1 - Device is a console
|
||||
* 0 - Device is not a console
|
||||
*
|
||||
*/
|
||||
int _sys_istty(FILEHANDLE hFile) {
|
||||
if (hFile > 0x8000) {
|
||||
return (1);
|
||||
}
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_seek
|
||||
*
|
||||
* Function description:
|
||||
* Seeks via the file to a specific position
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* Pos -
|
||||
*
|
||||
* Return value:
|
||||
* int -
|
||||
*
|
||||
*/
|
||||
int _sys_seek(FILEHANDLE hFile, long Pos) {
|
||||
(void)hFile;
|
||||
(void)Pos;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_ensure
|
||||
*
|
||||
* Function description:
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* int -
|
||||
*
|
||||
*/
|
||||
int _sys_ensure(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return (-1); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_flen
|
||||
*
|
||||
* Function description:
|
||||
* Returns the length of the opened file handle
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* Length of the file
|
||||
*
|
||||
*/
|
||||
long _sys_flen(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_tmpnam
|
||||
*
|
||||
* Function description:
|
||||
* This function converts the file number fileno for a temporary
|
||||
* file to a unique filename, for example, tmp0001.
|
||||
*
|
||||
* Parameters:
|
||||
* pBuffer - Pointer to a buffer to store the name
|
||||
* FileNum - file number to convert
|
||||
* MaxLen - Size of the buffer
|
||||
*
|
||||
* Return value:
|
||||
* 1 - Error
|
||||
* 0 - Success
|
||||
*
|
||||
*/
|
||||
int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) {
|
||||
(void)pBuffer;
|
||||
(void)FileNum;
|
||||
(void)MaxLen;
|
||||
return (1); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_command_string
|
||||
*
|
||||
* Function description:
|
||||
* This function shall execute a system command.
|
||||
*
|
||||
* Parameters:
|
||||
* cmd - Pointer to the command string
|
||||
* len - Length of the string
|
||||
*
|
||||
* Return value:
|
||||
* == NULL - Command was not successfully executed
|
||||
* == sCmd - Command was passed successfully
|
||||
*
|
||||
*/
|
||||
char * _sys_command_string(char * cmd, int len) {
|
||||
(void)len;
|
||||
return cmd; // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_exit
|
||||
*
|
||||
* Function description:
|
||||
* This function is called when the application returns from main
|
||||
*
|
||||
* Parameters:
|
||||
* ReturnCode - Return code from the main function
|
||||
*
|
||||
*
|
||||
*/
|
||||
void _sys_exit(int ReturnCode) {
|
||||
(void)ReturnCode;
|
||||
while (1); // Not implemented
|
||||
}
|
||||
|
||||
#if __ARMCC_VERSION >= 5000000
|
||||
/*********************************************************************
|
||||
*
|
||||
* stdout_putchar
|
||||
*
|
||||
* Function description:
|
||||
* Put a character to the stdout
|
||||
*
|
||||
* Parameters:
|
||||
* ch - Character to output
|
||||
*
|
||||
*
|
||||
*/
|
||||
int stdout_putchar(int ch) {
|
||||
(void)ch;
|
||||
return ch; // Not implemented
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*************************** End of file ****************************/
|
@ -1,247 +0,0 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_SES.c
|
||||
Purpose : Reimplementation of printf, puts and __getchar using RTT
|
||||
in SEGGER Embedded Studio.
|
||||
To use RTT for printf output, include this file in your
|
||||
application.
|
||||
Revision: $Rev: 18539 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM)
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "limits.h"
|
||||
#include "__libc.h"
|
||||
#include "__vfprintf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// Select string formatting implementation.
|
||||
//
|
||||
// RTT printf formatting
|
||||
// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h)
|
||||
// - No maximum string length.
|
||||
// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c)
|
||||
// Standard library printf formatting
|
||||
// - Configurable formatting capabilities.
|
||||
// - Full conversion specifier and flag support.
|
||||
// - Maximum string length has to be known or (slightly) slower character-wise output.
|
||||
//
|
||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting
|
||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting
|
||||
//
|
||||
#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING
|
||||
#define PRINTF_USE_SEGGER_RTT_FORMATTING 0
|
||||
#endif
|
||||
//
|
||||
// If using standard library formatting,
|
||||
// select maximum output string buffer size or character-wise output.
|
||||
//
|
||||
// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output
|
||||
// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length
|
||||
//
|
||||
#ifndef PRINTF_BUFFER_SIZE
|
||||
#define PRINTF_BUFFER_SIZE 128
|
||||
#endif
|
||||
|
||||
#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string using RTT and SEGGER RTT formatting.
|
||||
*/
|
||||
int printf(const char *fmt,...) {
|
||||
int n;
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
n = SEGGER_RTT_vprintf(0, fmt, &args);
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Static functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
static int _putchar(int x, __printf_tag_ptr ctx) {
|
||||
(void)ctx;
|
||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string character-wise, using RTT and standard
|
||||
* library formatting.
|
||||
*/
|
||||
int printf(const char *fmt, ...) {
|
||||
int n;
|
||||
va_list args;
|
||||
__printf_t iod;
|
||||
|
||||
va_start(args, fmt);
|
||||
iod.string = 0;
|
||||
iod.maxchars = INT_MAX;
|
||||
iod.output_fn = _putchar;
|
||||
SEGGER_RTT_LOCK();
|
||||
n = __vfprintf(&iod, fmt, args);
|
||||
SEGGER_RTT_UNLOCK();
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
#else // Use standard library formatting with static buffer
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string using RTT and standard library formatting.
|
||||
*/
|
||||
int printf(const char *fmt,...) {
|
||||
int n;
|
||||
char aBuffer[PRINTF_BUFFER_SIZE];
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args);
|
||||
if (n > (int)sizeof(aBuffer)) {
|
||||
SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer));
|
||||
} else if (n > 0) {
|
||||
SEGGER_RTT_Write(0, aBuffer, n);
|
||||
}
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* puts()
|
||||
*
|
||||
* Function description
|
||||
* print a string using RTT.
|
||||
*/
|
||||
int puts(const char *s) {
|
||||
return SEGGER_RTT_WriteString(0, s);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __putchar()
|
||||
*
|
||||
* Function description
|
||||
* Write one character via RTT.
|
||||
*/
|
||||
int __putchar(int x, __printf_tag_ptr ctx) {
|
||||
(void)ctx;
|
||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __getchar()
|
||||
*
|
||||
* Function description
|
||||
* Wait for and get a character via RTT.
|
||||
*/
|
||||
int __getchar() {
|
||||
return SEGGER_RTT_WaitKey();
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
@ -32,6 +32,8 @@ function(add_tinyusb TARGET)
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_host.c
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_host.c
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_host.c
|
||||
# typec
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/typec/utcd.c
|
||||
)
|
||||
target_include_directories(${TARGET} PUBLIC
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
|
||||
@ -98,7 +100,3 @@ endif()
|
||||
target_link_libraries(${TINYUSB_TARGET} PUBLIC
|
||||
${TINYUSB_CONFIG_TARGET}
|
||||
)
|
||||
|
||||
# export target name
|
||||
# set(TINYUSB_TARGET ${TINYUSB_TARGET} PARENT_SCOPE)
|
||||
# set(TINYUSB_CONFIG_TARGET ${TINYUSB_CONFIG_TARGET} PARENT_SCOPE)
|
||||
|
@ -197,10 +197,17 @@
|
||||
#define TUP_DCD_ENDPOINT_MAX 9
|
||||
|
||||
#elif TU_CHECK_MCU(OPT_MCU_STM32G4)
|
||||
// Device controller
|
||||
#define TUP_USBIP_FSDEV
|
||||
#define TUP_USBIP_FSDEV_STM32
|
||||
|
||||
// TypeC controller
|
||||
#define TUP_USBIP_TYPEC_STM32
|
||||
|
||||
#define TUP_DCD_ENDPOINT_MAX 8
|
||||
|
||||
#define TUP_TYPEC_RHPORTS_NUM 1
|
||||
|
||||
#elif TU_CHECK_MCU(OPT_MCU_STM32G0)
|
||||
#define TUP_USBIP_FSDEV
|
||||
#define TUP_USBIP_FSDEV_STM32
|
||||
|
@ -232,6 +232,9 @@ enum {
|
||||
|
||||
#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
typedef enum
|
||||
{
|
||||
XFER_RESULT_SUCCESS = 0,
|
||||
@ -474,9 +477,10 @@ typedef struct TU_ATTR_PACKED
|
||||
uint16_t bcdDFUVersion;
|
||||
} tusb_desc_dfu_functional_t;
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Types
|
||||
*------------------------------------------------------------------*/
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
typedef struct TU_ATTR_PACKED{
|
||||
union {
|
||||
struct TU_ATTR_PACKED {
|
||||
|
@ -189,6 +189,7 @@ TU_ATTR_WEAK bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t l
|
||||
|
||||
// Configure and enable an ISO endpoint according to descriptor
|
||||
TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Event API (implemented by stack)
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -252,9 +252,19 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid)
|
||||
drvid -= _app_driver_count;
|
||||
}
|
||||
|
||||
// when there is no built-in drivers BUILTIN_DRIVER_COUNT = 0 will cause -Wtype-limits warning
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
#endif
|
||||
|
||||
// Built-in drivers
|
||||
if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid];
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -724,7 +724,7 @@ uint8_t* usbh_get_enum_buf(void)
|
||||
|
||||
void usbh_int_set(bool enabled)
|
||||
{
|
||||
// TODO all host controller if multiple is used
|
||||
// TODO all host controller if multiple are used since they shared the same event queue
|
||||
if (enabled)
|
||||
{
|
||||
hcd_int_enable(_usbh_controller);
|
||||
|
369
src/portable/st/typec/typec_stm32.c
Normal file
369
src/portable/st/typec/typec_stm32.c
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 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 "tusb_option.h"
|
||||
#include "typec/tcd.h"
|
||||
|
||||
#if CFG_TUC_ENABLED && defined(TUP_USBIP_TYPEC_STM32)
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_STM32G4
|
||||
#include "stm32g4xx.h"
|
||||
#include "stm32g4xx_ll_dma.h" // for UCPD REQID
|
||||
#else
|
||||
#error "Unsupported STM32 family"
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
enum {
|
||||
IMR_ATTACHED = UCPD_IMR_TXMSGDISCIE | UCPD_IMR_TXMSGSENTIE | UCPD_IMR_TXMSGABTIE | UCPD_IMR_TXUNDIE |
|
||||
UCPD_IMR_RXHRSTDETIE | UCPD_IMR_RXOVRIE | UCPD_IMR_RXMSGENDIE | UCPD_IMR_RXORDDETIE |
|
||||
UCPD_IMR_HRSTDISCIE | UCPD_IMR_HRSTSENTIE | UCPD_IMR_FRSEVTIE
|
||||
};
|
||||
|
||||
#define PHY_SYNC1 0x18u
|
||||
#define PHY_SYNC2 0x11u
|
||||
#define PHY_SYNC3 0x06u
|
||||
#define PHY_RST1 0x07u
|
||||
#define PHY_RST2 0x19u
|
||||
#define PHY_EOP 0x0Du
|
||||
|
||||
#define PHY_ORDERED_SET_SOP (PHY_SYNC1 | (PHY_SYNC1<<5u) | (PHY_SYNC1<<10u) | (PHY_SYNC2<<15u)) // SOP Ordered set coding
|
||||
#define PHY_ORDERED_SET_SOP_P (PHY_SYNC1 | (PHY_SYNC1<<5u) | (PHY_SYNC3<<10u) | (PHY_SYNC3<<15u)) // SOP' Ordered set coding
|
||||
#define PHY_ORDERED_SET_SOP_PP (PHY_SYNC1 | (PHY_SYNC3<<5u) | (PHY_SYNC1<<10u) | (PHY_SYNC3<<15u)) // SOP'' Ordered set coding
|
||||
#define PHY_ORDERED_SET_HARD_RESET (PHY_RST1 | (PHY_RST1<<5u) | (PHY_RST1<<10u) | (PHY_RST2<<15u )) // Hard Reset Ordered set coding
|
||||
#define PHY_ORDERED_SET_CABLE_RESET (PHY_RST1 | (PHY_SYNC1<<5u) | (PHY_RST1<<10u) | (PHY_SYNC3<<15u)) // Cable Reset Ordered set coding
|
||||
#define PHY_ORDERED_SET_SOP_P_DEBUG (PHY_SYNC1 | (PHY_RST2<<5u) | (PHY_RST2<<10u) | (PHY_SYNC3<<15u)) // SOP' Debug Ordered set coding
|
||||
#define PHY_ORDERED_SET_SOP_PP_DEBUG (PHY_SYNC1 | (PHY_RST2<<5u) | (PHY_SYNC3<<10u) | (PHY_SYNC2<<15u)) // SOP'' Debug Ordered set coding
|
||||
|
||||
|
||||
static uint8_t const* _rx_buf;
|
||||
static uint8_t const* _tx_pending_buf;
|
||||
static uint16_t _tx_pending_bytes;
|
||||
static uint16_t _tx_xferring_bytes;
|
||||
|
||||
static pd_header_t _good_crc = {
|
||||
.msg_type = PD_CTRL_GOOD_CRC,
|
||||
.data_role = 0, // UFP
|
||||
.specs_rev = PD_REV_20,
|
||||
.power_role = 0, // Sink
|
||||
.msg_id = 0,
|
||||
.n_data_obj = 0,
|
||||
.extended = 0
|
||||
};
|
||||
|
||||
// address of DMA channel rx, tx for each port
|
||||
#define CFG_TUC_STM32_DMA { { DMA1_Channel1_BASE, DMA1_Channel2_BASE } }
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// DMA
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static const uint32_t _dma_addr_arr[TUP_TYPEC_RHPORTS_NUM][2] = CFG_TUC_STM32_DMA;
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint32_t dma_get_addr(uint8_t rhport, bool is_rx) {
|
||||
return _dma_addr_arr[rhport][is_rx ? 0 : 1];
|
||||
}
|
||||
|
||||
static void dma_init(uint8_t rhport, bool is_rx) {
|
||||
uint32_t dma_addr = dma_get_addr(rhport, is_rx);
|
||||
DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_addr;
|
||||
uint32_t req_id;
|
||||
|
||||
if (is_rx) {
|
||||
// Peripheral -> Memory, Memory inc, 8-bit, High priority
|
||||
dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1;
|
||||
dma_ch->CPAR = (uint32_t) &UCPD1->RXDR;
|
||||
|
||||
req_id = LL_DMAMUX_REQ_UCPD1_RX;
|
||||
} else {
|
||||
// Memory -> Peripheral, Memory inc, 8-bit, High priority
|
||||
dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1 | DMA_CCR_DIR;
|
||||
dma_ch->CPAR = (uint32_t) &UCPD1->TXDR;
|
||||
|
||||
req_id = LL_DMAMUX_REQ_UCPD1_TX;
|
||||
}
|
||||
|
||||
// find and set up mux channel TODO support mcu with multiple DMAMUXs
|
||||
enum {
|
||||
CH_DIFF = DMA1_Channel2_BASE - DMA1_Channel1_BASE
|
||||
};
|
||||
uint32_t mux_ch_num;
|
||||
|
||||
#ifdef DMA2_BASE
|
||||
if (dma_addr > DMA2_BASE) {
|
||||
mux_ch_num = 8 * ((dma_addr - DMA2_Channel1_BASE) / CH_DIFF);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mux_ch_num = (dma_addr - DMA1_Channel1_BASE) / CH_DIFF;
|
||||
}
|
||||
|
||||
DMAMUX_Channel_TypeDef* mux_ch = DMAMUX1_Channel0 + mux_ch_num;
|
||||
|
||||
uint32_t mux_ccr = mux_ch->CCR & ~(DMAMUX_CxCR_DMAREQ_ID);
|
||||
mux_ccr |= req_id;
|
||||
mux_ch->CCR = mux_ccr;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void dma_start(uint8_t rhport, bool is_rx, void const* buf, uint16_t len) {
|
||||
DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
|
||||
|
||||
dma_ch->CMAR = (uint32_t) buf;
|
||||
dma_ch->CNDTR = len;
|
||||
dma_ch->CCR |= DMA_CCR_EN;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void dma_stop(uint8_t rhport, bool is_rx) {
|
||||
DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
|
||||
dma_ch->CCR &= ~DMA_CCR_EN;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool dma_enabled(uint8_t rhport, bool is_rx) {
|
||||
DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
|
||||
return dma_ch->CCR & DMA_CCR_EN;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void dma_tx_start(uint8_t rhport, void const* buf, uint16_t len) {
|
||||
UCPD1->TX_ORDSET = PHY_ORDERED_SET_SOP;
|
||||
UCPD1->TX_PAYSZ = len;
|
||||
dma_start(rhport, false, buf, len);
|
||||
UCPD1->CR |= UCPD_CR_TXSEND;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void dma_tx_stop(uint8_t rhport) {
|
||||
dma_stop(rhport, false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tcd_init(uint8_t rhport, uint32_t port_type) {
|
||||
(void) rhport;
|
||||
|
||||
// Init DMA for RX, TX
|
||||
dma_init(rhport, true);
|
||||
dma_init(rhport, false);
|
||||
|
||||
// Initialization phase: CFG1, detect all SOPs
|
||||
UCPD1->CFG1 = (0x0d << UCPD_CFG1_HBITCLKDIV_Pos) | (0x10 << UCPD_CFG1_IFRGAP_Pos) | (0x07 << UCPD_CFG1_TRANSWIN_Pos) |
|
||||
(0x01 << UCPD_CFG1_PSC_UCPDCLK_Pos) | (0x1f << UCPD_CFG1_RXORDSETEN_Pos);
|
||||
UCPD1->CFG1 |= UCPD_CFG1_UCPDEN;
|
||||
|
||||
// General programming sequence (with UCPD configured then enabled)
|
||||
if (port_type == TUSB_TYPEC_PORT_SNK) {
|
||||
// Set analog mode enable both CC Phy
|
||||
UCPD1->CR = (0x01 << UCPD_CR_ANAMODE_Pos) | (UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1);
|
||||
|
||||
// Read Voltage State on CC1 & CC2 fore initial state
|
||||
uint32_t v_cc[2];
|
||||
v_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
|
||||
v_cc[1] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos) & 0x03;
|
||||
|
||||
TU_LOG1("Initial VState CC1 = %u, CC2 = %u\r\n", v_cc[0], v_cc[1]);
|
||||
|
||||
// Enable CC1 & CC2 Interrupt
|
||||
UCPD1->IMR = UCPD_IMR_TYPECEVT1IE | UCPD_IMR_TYPECEVT2IE;
|
||||
}
|
||||
|
||||
// Disable dead battery in PWR's CR3
|
||||
PWR->CR3 |= PWR_CR3_UCPD_DBDIS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Enable interrupt
|
||||
void tcd_int_enable (uint8_t rhport) {
|
||||
(void) rhport;
|
||||
NVIC_EnableIRQ(UCPD1_IRQn);
|
||||
}
|
||||
|
||||
// Disable interrupt
|
||||
void tcd_int_disable(uint8_t rhport) {
|
||||
(void) rhport;
|
||||
NVIC_DisableIRQ(UCPD1_IRQn);
|
||||
}
|
||||
|
||||
bool tcd_msg_receive(uint8_t rhport, uint8_t* buffer, uint16_t total_bytes) {
|
||||
_rx_buf = buffer;
|
||||
dma_start(rhport, true, buffer, total_bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tcd_msg_send(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes) {
|
||||
(void) rhport;
|
||||
|
||||
if (dma_enabled(rhport, false)) {
|
||||
// DMA is busy, probably sending GoodCRC, save as pending TX
|
||||
_tx_pending_buf = buffer;
|
||||
_tx_pending_bytes = total_bytes;
|
||||
}else {
|
||||
// DMA is free, start sending
|
||||
_tx_pending_buf = NULL;
|
||||
_tx_pending_bytes = 0;
|
||||
|
||||
_tx_xferring_bytes = total_bytes;
|
||||
dma_tx_start(rhport, buffer, total_bytes);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void tcd_int_handler(uint8_t rhport) {
|
||||
(void) rhport;
|
||||
|
||||
uint32_t sr = UCPD1->SR;
|
||||
sr &= UCPD1->IMR;
|
||||
|
||||
if (sr & (UCPD_SR_TYPECEVT1 | UCPD_SR_TYPECEVT2)) {
|
||||
uint32_t v_cc[2];
|
||||
v_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
|
||||
v_cc[1] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos) & 0x03;
|
||||
|
||||
TU_LOG3("VState CC1 = %u, CC2 = %u\n", v_cc[0], v_cc[1]);
|
||||
|
||||
uint32_t cr = UCPD1->CR;
|
||||
|
||||
// TODO only support SNK for now, required highest voltage for now
|
||||
// Enable PHY on active CC and disable Rd on other CC
|
||||
// FIXME somehow CC2 is vstate is not correct, always 1 even not attached.
|
||||
// on DPOW1 board, it is connected to PA10 (USBPD_DBCC2), we probably miss something.
|
||||
if ((sr & UCPD_SR_TYPECEVT1) && (v_cc[0] == 3)) {
|
||||
TU_LOG3("Attach CC1\n");
|
||||
cr &= ~(UCPD_CR_PHYCCSEL | UCPD_CR_CCENABLE);
|
||||
cr |= UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_0;
|
||||
} else if ((sr & UCPD_SR_TYPECEVT2) && (v_cc[1] == 3)) {
|
||||
TU_LOG3("Attach CC2\n");
|
||||
cr &= ~UCPD_CR_CCENABLE;
|
||||
cr |= (UCPD_CR_PHYCCSEL | UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_1);
|
||||
} else {
|
||||
TU_LOG3("Detach\n");
|
||||
cr &= ~UCPD_CR_PHYRXEN;
|
||||
cr |= UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1;
|
||||
}
|
||||
|
||||
if (cr & UCPD_CR_PHYRXEN) {
|
||||
// Attached
|
||||
UCPD1->IMR |= IMR_ATTACHED;
|
||||
UCPD1->CFG1 |= UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN;
|
||||
}else {
|
||||
// Detached
|
||||
UCPD1->CFG1 &= ~(UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN);
|
||||
UCPD1->IMR &= ~IMR_ATTACHED;
|
||||
}
|
||||
|
||||
// notify stack
|
||||
tcd_event_cc_changed(rhport, v_cc[0], v_cc[1], true);
|
||||
|
||||
UCPD1->CR = cr;
|
||||
|
||||
// ack
|
||||
UCPD1->ICR = UCPD_ICR_TYPECEVT1CF | UCPD_ICR_TYPECEVT2CF;
|
||||
}
|
||||
|
||||
//------------- RX -------------//
|
||||
if (sr & UCPD_SR_RXORDDET) {
|
||||
// SOP: Start of Packet.
|
||||
TU_LOG3("SOP\n");
|
||||
// UCPD1->RX_ORDSET & UCPD_RX_ORDSET_RXORDSET_Msk;
|
||||
|
||||
// ack
|
||||
UCPD1->ICR = UCPD_ICR_RXORDDETCF;
|
||||
}
|
||||
|
||||
// Received full message
|
||||
if (sr & UCPD_SR_RXMSGEND) {
|
||||
TU_LOG3("RX MSG END\n");
|
||||
|
||||
// stop TX
|
||||
dma_stop(rhport, true);
|
||||
|
||||
uint8_t result;
|
||||
|
||||
if (!(sr & UCPD_SR_RXERR)) {
|
||||
// response with good crc
|
||||
_good_crc.msg_id = ((pd_header_t const*) _rx_buf)->msg_id;
|
||||
dma_tx_start(rhport, &_good_crc, 2);
|
||||
|
||||
result = XFER_RESULT_SUCCESS;
|
||||
}else {
|
||||
// CRC failed
|
||||
result = XFER_RESULT_FAILED;
|
||||
}
|
||||
|
||||
// notify stack
|
||||
tcd_event_rx_complete(rhport, UCPD1->RX_PAYSZ, result, true);
|
||||
|
||||
// ack
|
||||
UCPD1->ICR = UCPD_ICR_RXMSGENDCF;
|
||||
}
|
||||
|
||||
if (sr & UCPD_SR_RXOVR) {
|
||||
TU_LOG3("RXOVR\n");
|
||||
// ack
|
||||
UCPD1->ICR = UCPD_ICR_RXOVRCF;
|
||||
}
|
||||
|
||||
//------------- TX -------------//
|
||||
// All tx events: complete and error
|
||||
if (sr & (UCPD_SR_TXMSGSENT | (UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND))) {
|
||||
// force TX stop
|
||||
dma_tx_stop(rhport);
|
||||
|
||||
uint16_t const xferred_bytes = _tx_xferring_bytes - UCPD1->TX_PAYSZ;
|
||||
uint8_t result;
|
||||
|
||||
if ( sr & UCPD_SR_TXMSGSENT ) {
|
||||
TU_LOG3("TX MSG SENT\n");
|
||||
result = XFER_RESULT_SUCCESS;
|
||||
// ack
|
||||
UCPD1->ICR = UCPD_ICR_TXMSGSENTCF;
|
||||
}else {
|
||||
TU_LOG3("TX Error\n");
|
||||
result = XFER_RESULT_FAILED;
|
||||
// ack
|
||||
UCPD1->ICR = UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND;
|
||||
}
|
||||
|
||||
// start pending TX if any
|
||||
if (_tx_pending_buf && _tx_pending_bytes ) {
|
||||
// Start the pending TX
|
||||
dma_tx_start(rhport, _tx_pending_buf, _tx_pending_bytes);
|
||||
|
||||
// clear pending
|
||||
_tx_pending_buf = NULL;
|
||||
_tx_pending_bytes = 0;
|
||||
}
|
||||
|
||||
// notify stack
|
||||
tcd_event_tx_complete(rhport, xferred_bytes, result, true);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -40,6 +40,11 @@
|
||||
|
||||
#include "class/hid/hid.h"
|
||||
|
||||
//------------- TypeC -------------//
|
||||
#if CFG_TUC_ENABLED
|
||||
#include "typec/utcd.h"
|
||||
#endif
|
||||
|
||||
//------------- HOST -------------//
|
||||
#if CFG_TUH_ENABLED
|
||||
#include "host/usbh.h"
|
||||
|
@ -483,6 +483,16 @@
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TypeC Options (Default)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifndef CFG_TUC_ENABLED
|
||||
#define CFG_TUC_ENABLED 0
|
||||
|
||||
#define tuc_int_handler(_p)
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Configuration Validation
|
||||
//------------------------------------------------------------------
|
||||
|
237
src/typec/pd_types.h
Normal file
237
src/typec/pd_types.h
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 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_PD_TYPES_H_
|
||||
#define _TUSB_PD_TYPES_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "common/tusb_compiler.h"
|
||||
|
||||
// Start of all packed definitions for compiler without per-type packed
|
||||
TU_ATTR_PACKED_BEGIN
|
||||
TU_ATTR_BIT_FIELD_ORDER_BEGIN
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TYPE-C
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
typedef enum {
|
||||
TUSB_TYPEC_PORT_SRC,
|
||||
TUSB_TYPEC_PORT_SNK,
|
||||
TUSB_TYPEC_PORT_DRP
|
||||
} tusb_typec_port_type_t;
|
||||
|
||||
enum {
|
||||
PD_CTRL_RESERVED = 0, // 0b00000: 0
|
||||
PD_CTRL_GOOD_CRC, // 0b00001: 1
|
||||
PD_CTRL_GO_TO_MIN, // 0b00010: 2
|
||||
PD_CTRL_ACCEPT, // 0b00011: 3
|
||||
PD_CTRL_REJECT, // 0b00100: 4
|
||||
PD_CTRL_PING, // 0b00101: 5
|
||||
PD_CTRL_PS_READY, // 0b00110: 6
|
||||
PD_CTRL_GET_SOURCE_CAP, // 0b00111: 7
|
||||
PD_CTRL_GET_SINK_CAP, // 0b01000: 8
|
||||
PD_CTRL_DR_SWAP, // 0b01001: 9
|
||||
PD_CTRL_PR_SWAP, // 0b01010: 10
|
||||
PD_CTRL_VCONN_SWAP, // 0b01011: 11
|
||||
PD_CTRL_WAIT, // 0b01100: 12
|
||||
PD_CTRL_SOFT_RESET, // 0b01101: 13
|
||||
PD_CTRL_DATA_RESET, // 0b01110: 14
|
||||
PD_CTRL_DATA_RESET_COMPLETE, // 0b01111: 15
|
||||
PD_CTRL_NOT_SUPPORTED, // 0b10000: 16
|
||||
PD_CTRL_GET_SOURCE_CAP_EXTENDED, // 0b10001: 17
|
||||
PD_CTRL_GET_STATUS, // 0b10010: 18
|
||||
PD_CTRL_FR_SWAP, // 0b10011: 19
|
||||
PD_CTRL_GET_PPS_STATUS, // 0b10100: 20
|
||||
PD_CTRL_GET_COUNTRY_CODES, // 0b10101: 21
|
||||
PD_CTRL_GET_SINK_CAP_EXTENDED, // 0b10110: 22
|
||||
PD_CTRL_GET_SOURCE_INFO, // 0b10111: 23
|
||||
PD_CTRL_REVISION, // 0b11000: 24
|
||||
};
|
||||
|
||||
enum {
|
||||
PD_DATA_RESERVED = 0, // 0b00000: 0
|
||||
PD_DATA_SOURCE_CAP, // 0b00001: 1
|
||||
PD_DATA_REQUEST, // 0b00010: 2
|
||||
PD_DATA_BIST, // 0b00011: 3
|
||||
PD_DATA_SINK_CAP, // 0b00100: 4
|
||||
PD_DATA_BATTERY_STATUS, // 0b00101: 5
|
||||
PD_DATA_ALERT, // 0b00110: 6
|
||||
PD_DATA_GET_COUNTRY_INFO, // 0b00111: 7
|
||||
PD_DATA_ENTER_USB, // 0b01000: 8
|
||||
PD_DATA_EPR_REQUEST, // 0b01001: 9
|
||||
PD_DATA_EPR_MODE, // 0b01010: 10
|
||||
PD_DATA_SRC_INFO, // 0b01011: 11
|
||||
PD_DATA_REVISION, // 0b01100: 12
|
||||
PD_DATA_RESERVED_13, // 0b01101: 13
|
||||
PD_DATA_RESERVED_14, // 0b01110: 14
|
||||
PD_DATA_VENDOR_DEFINED, // 0b01111: 15
|
||||
};
|
||||
|
||||
enum {
|
||||
PD_REV_10 = 0x0,
|
||||
PD_REV_20 = 0x1,
|
||||
PD_REV_30 = 0x2,
|
||||
};
|
||||
|
||||
enum {
|
||||
PD_DATA_ROLE_UFP = 0x0,
|
||||
PD_DATA_ROLE_DFP = 0x1,
|
||||
};
|
||||
|
||||
enum {
|
||||
PD_POWER_ROLE_SINK = 0x0,
|
||||
PD_POWER_ROLE_SOURCE = 0x1,
|
||||
};
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t msg_type : 5; // [0:4]
|
||||
uint16_t data_role : 1; // [5] SOP only: 0 UFP, 1 DFP
|
||||
uint16_t specs_rev : 2; // [6:7]
|
||||
uint16_t power_role : 1; // [8] SOP only: 0 Sink, 1 Source
|
||||
uint16_t msg_id : 3; // [9:11]
|
||||
uint16_t n_data_obj : 3; // [12:14]
|
||||
uint16_t extended : 1; // [15]
|
||||
} pd_header_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_header_t) == 2, "size is not correct");
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t data_size : 9; // [0:8]
|
||||
uint16_t reserved : 1; // [9]
|
||||
uint16_t request_chunk : 1; // [10]
|
||||
uint16_t chunk_number : 4; // [11:14]
|
||||
uint16_t chunked : 1; // [15]
|
||||
} pd_header_extended_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_header_extended_t) == 2, "size is not correct");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Source Capability
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// All table references are from USBPD Specification rev3.1 version 1.8
|
||||
enum {
|
||||
PD_PDO_TYPE_FIXED = 0, // Vmin = Vmax
|
||||
PD_PDO_TYPE_BATTERY,
|
||||
PD_PDO_TYPE_VARIABLE, // non-battery
|
||||
PD_PDO_TYPE_APDO, // Augmented Power Data Object
|
||||
};
|
||||
|
||||
// Fixed Power Data Object (PDO) table 6-9
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t current_max_10ma : 10; // [9..0] Max current in 10mA unit
|
||||
uint32_t voltage_50mv : 10; // [19..10] Voltage in 50mV unit
|
||||
uint32_t current_peak : 2; // [21..20] Peak current
|
||||
uint32_t reserved : 1; // [22] Reserved
|
||||
uint32_t epr_mode_capable : 1; // [23] epr_mode_capable
|
||||
uint32_t unchunked_ext_msg_support : 1; // [24] UnChunked Extended Message Supported
|
||||
uint32_t dual_role_data : 1; // [25] Dual Role Data
|
||||
uint32_t usb_comm_capable : 1; // [26] USB Communications Capable
|
||||
uint32_t unconstrained_power : 1; // [27] Unconstrained Power
|
||||
uint32_t usb_suspend_supported : 1; // [28] USB Suspend Supported
|
||||
uint32_t dual_role_power : 1; // [29] Dual Role Power
|
||||
uint32_t type : 2; // [30] Fixed Supply type = PD_PDO_TYPE_FIXED
|
||||
} pd_pdo_fixed_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_pdo_fixed_t) == 4, "Invalid size");
|
||||
|
||||
// Battery Power Data Object (PDO) table 6-12
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t power_max_250mw : 10; // [9..0] Max allowable power in 250mW unit
|
||||
uint32_t voltage_min_50mv : 10; // [19..10] Minimum voltage in 50mV unit
|
||||
uint32_t voltage_max_50mv : 10; // [29..20] Maximum voltage in 50mV unit
|
||||
uint32_t type : 2; // [31..30] Battery type = PD_PDO_TYPE_BATTERY
|
||||
} pd_pdo_battery_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_pdo_battery_t) == 4, "Invalid size");
|
||||
|
||||
// Variable Power Data Object (PDO) table 6-11
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t current_max_10ma : 10; // [9..0] Max current in 10mA unit
|
||||
uint32_t voltage_min_50mv : 10; // [19..10] Minimum voltage in 50mV unit
|
||||
uint32_t voltage_max_50mv : 10; // [29..20] Maximum voltage in 50mV unit
|
||||
uint32_t type : 2; // [31..30] Variable Supply type = PD_PDO_TYPE_VARIABLE
|
||||
} pd_pdo_variable_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_pdo_variable_t) == 4, "Invalid size");
|
||||
|
||||
// Augmented Power Data Object (PDO) table 6-13
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t current_max_50ma : 7; // [6..0] Max current in 50mA unit
|
||||
uint32_t reserved1 : 1; // [7] Reserved
|
||||
uint32_t voltage_min_100mv : 8; // [15..8] Minimum Voltage in 100mV unit
|
||||
uint32_t reserved2 : 1; // [16] Reserved
|
||||
uint32_t voltage_max_100mv : 8; // [24..17] Maximum Voltage in 100mV unit
|
||||
uint32_t reserved3 : 2; // [26..25] Reserved
|
||||
uint32_t pps_power_limited : 1; // [27] PPS Power Limited
|
||||
uint32_t spr_programmable : 2; // [29..28] SPR Programmable Power Supply
|
||||
uint32_t type : 2; // [31..30] Augmented Power Data Object = PD_PDO_TYPE_APDO
|
||||
} pd_pdo_apdo_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_pdo_apdo_t) == 4, "Invalid size");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Request
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t current_extremum_10ma : 10; // [9..0] Max (give back = 0) or Min (give back = 1) current in 10mA unit
|
||||
uint32_t current_operate_10ma : 10; // [19..10] Operating current in 10mA unit
|
||||
uint32_t reserved : 2; // [21..20] Reserved
|
||||
uint32_t epr_mode_capable : 1; // [22] EPR mode capable
|
||||
uint32_t unchunked_ext_msg_support : 1; // [23] UnChunked Extended Message Supported
|
||||
uint32_t no_usb_suspend : 1; // [24] No USB Suspend
|
||||
uint32_t usb_comm_capable : 1; // [25] USB Communications Capable
|
||||
uint32_t capability_mismatch : 1; // [26] Capability Mismatch
|
||||
uint32_t give_back_flag : 1; // [27] GiveBack Flag: 0 = Max, 1 = Min
|
||||
uint32_t object_position : 4; // [31..28] Object Position
|
||||
} pd_rdo_fixed_variable_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_rdo_fixed_variable_t) == 4, "Invalid size");
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t power_extremum_250mw : 10; // [9..0] Max (give back = 0) or Min (give back = 1) operating power in 250mW unit
|
||||
uint32_t power_operate_250mw : 10; // [19..10] Operating power in 250mW unit
|
||||
uint32_t reserved : 2; // [21..20] Reserved
|
||||
uint32_t epr_mode_capable : 1; // [22] EPR mode capable
|
||||
uint32_t unchunked_ext_msg_support : 1; // [23] UnChunked Extended Message Supported
|
||||
uint32_t no_usb_suspend : 1; // [24] No USB Suspend
|
||||
uint32_t usb_comm_capable : 1; // [25] USB Communications Capable
|
||||
uint32_t capability_mismatch : 1; // [26] Capability Mismatch
|
||||
uint32_t give_back_flag : 1; // [27] GiveBack Flag: 0 = Max, 1 = Min
|
||||
uint32_t object_position : 4; // [31..28] Object Position
|
||||
} pd_rdo_battery_t;
|
||||
TU_VERIFY_STATIC(sizeof(pd_rdo_battery_t) == 4, "Invalid size");
|
||||
|
||||
|
||||
TU_ATTR_PACKED_END // End of all packed definitions
|
||||
TU_ATTR_BIT_FIELD_ORDER_END
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
143
src/typec/tcd.h
Normal file
143
src/typec/tcd.h
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Ha Thach (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.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_TCD_H_
|
||||
#define _TUSB_TCD_H_
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "pd_types.h"
|
||||
|
||||
#include "osal/osal.h"
|
||||
#include "common/tusb_fifo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
enum {
|
||||
TCD_EVENT_INVALID = 0,
|
||||
TCD_EVENT_CC_CHANGED,
|
||||
TCD_EVENT_RX_COMPLETE,
|
||||
TCD_EVENT_TX_COMPLETE,
|
||||
};
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t rhport;
|
||||
uint8_t event_id;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t cc_state[2];
|
||||
} cc_changed;
|
||||
|
||||
struct TU_ATTR_PACKED {
|
||||
uint16_t result : 2;
|
||||
uint16_t xferred_bytes : 14;
|
||||
} xfer_complete;
|
||||
};
|
||||
|
||||
} tcd_event_t;;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Initialize controller
|
||||
bool tcd_init(uint8_t rhport, uint32_t port_type);
|
||||
|
||||
// Enable interrupt
|
||||
void tcd_int_enable (uint8_t rhport);
|
||||
|
||||
// Disable interrupt
|
||||
void tcd_int_disable(uint8_t rhport);
|
||||
|
||||
// Interrupt Handler
|
||||
void tcd_int_handler(uint8_t rhport);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tcd_msg_receive(uint8_t rhport, uint8_t* buffer, uint16_t total_bytes);
|
||||
bool tcd_msg_send(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Event API (implemented by stack)
|
||||
// Called by TCD to notify stack
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
extern void tcd_event_handler(tcd_event_t const * event, bool in_isr);
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tcd_event_cc_changed(uint8_t rhport, uint8_t cc1, uint8_t cc2, bool in_isr) {
|
||||
tcd_event_t event = {
|
||||
.rhport = rhport,
|
||||
.event_id = TCD_EVENT_CC_CHANGED,
|
||||
.cc_changed = {
|
||||
.cc_state = {cc1, cc2 }
|
||||
}
|
||||
};
|
||||
|
||||
tcd_event_handler(&event, in_isr);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tcd_event_rx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t result, bool in_isr) {
|
||||
tcd_event_t event = {
|
||||
.rhport = rhport,
|
||||
.event_id = TCD_EVENT_RX_COMPLETE,
|
||||
.xfer_complete = {
|
||||
.xferred_bytes = xferred_bytes,
|
||||
.result = result
|
||||
}
|
||||
};
|
||||
|
||||
tcd_event_handler(&event, in_isr);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tcd_event_tx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t result, bool in_isr) {
|
||||
tcd_event_t event = {
|
||||
.rhport = rhport,
|
||||
.event_id = TCD_EVENT_TX_COMPLETE,
|
||||
.xfer_complete = {
|
||||
.xferred_bytes = xferred_bytes,
|
||||
.result = result
|
||||
}
|
||||
};
|
||||
|
||||
tcd_event_handler(&event, in_isr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
219
src/typec/utcd.c
Normal file
219
src/typec/utcd.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Ha Thach (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_option.h"
|
||||
|
||||
#if CFG_TUC_ENABLED
|
||||
|
||||
#include "tcd.h"
|
||||
#include "utcd.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Debug level of USBD
|
||||
#define UTCD_DEBUG 2
|
||||
#define TU_LOG_UTCD(...) TU_LOG(UTCD_DEBUG, __VA_ARGS__)
|
||||
|
||||
// Event queue
|
||||
// utcd_int_set() is used as mutex in OS NONE config
|
||||
void utcd_int_set(bool enabled);
|
||||
OSAL_QUEUE_DEF(utcd_int_set, _utcd_qdef, CFG_TUC_TASK_QUEUE_SZ, tcd_event_t);
|
||||
tu_static osal_queue_t _utcd_q;
|
||||
|
||||
// if stack is initialized
|
||||
static bool _utcd_inited = false;
|
||||
|
||||
// if port is initialized
|
||||
static bool _port_inited[TUP_TYPEC_RHPORTS_NUM];
|
||||
|
||||
// Max possible PD size is 262 bytes
|
||||
static uint8_t _rx_buf[64] TU_ATTR_ALIGNED(4);
|
||||
static uint8_t _tx_buf[64] TU_ATTR_ALIGNED(4);
|
||||
|
||||
bool utcd_msg_send(uint8_t rhport, pd_header_t const* header, void const* data);
|
||||
bool parse_msg_data(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end);
|
||||
bool parse_msg_control(uint8_t rhport, pd_header_t const* header);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
bool tuc_inited(uint8_t rhport) {
|
||||
return _utcd_inited && _port_inited[rhport];
|
||||
}
|
||||
|
||||
bool tuc_init(uint8_t rhport, uint32_t port_type) {
|
||||
// Initialize stack
|
||||
if (!_utcd_inited) {
|
||||
tu_memclr(_port_inited, sizeof(_port_inited));
|
||||
|
||||
_utcd_q = osal_queue_create(&_utcd_qdef);
|
||||
TU_ASSERT(_utcd_q != NULL);
|
||||
|
||||
_utcd_inited = true;
|
||||
}
|
||||
|
||||
// skip if port already initialized
|
||||
if ( _port_inited[rhport] ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TU_LOG_UTCD("UTCD init on port %u\r\n", rhport);
|
||||
TU_LOG_INT(UTCD_DEBUG, sizeof(tcd_event_t));
|
||||
|
||||
TU_ASSERT(tcd_init(rhport, port_type));
|
||||
tcd_int_enable(rhport);
|
||||
|
||||
_port_inited[rhport] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void tuc_task_ext(uint32_t timeout_ms, bool in_isr) {
|
||||
(void) in_isr; // not implemented yet
|
||||
|
||||
// Skip if stack is not initialized
|
||||
if (!_utcd_inited) return;
|
||||
|
||||
// Loop until there is no more events in the queue
|
||||
while (1) {
|
||||
tcd_event_t event;
|
||||
if (!osal_queue_receive(_utcd_q, &event, timeout_ms)) return;
|
||||
|
||||
switch (event.event_id) {
|
||||
case TCD_EVENT_CC_CHANGED:
|
||||
break;
|
||||
|
||||
case TCD_EVENT_RX_COMPLETE:
|
||||
// TODO process message here in ISR, move to thread later
|
||||
if (event.xfer_complete.result == XFER_RESULT_SUCCESS) {
|
||||
pd_header_t const* header = (pd_header_t const*) _rx_buf;
|
||||
|
||||
if (header->n_data_obj == 0) {
|
||||
parse_msg_control(event.rhport, header);
|
||||
|
||||
}else {
|
||||
uint8_t const* p_end = _rx_buf + event.xfer_complete.xferred_bytes;
|
||||
uint8_t const * dobj = _rx_buf + sizeof(pd_header_t);
|
||||
|
||||
parse_msg_data(event.rhport, header, dobj, p_end);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare for next message
|
||||
tcd_msg_receive(event.rhport, _rx_buf, sizeof(_rx_buf));
|
||||
break;
|
||||
|
||||
case TCD_EVENT_TX_COMPLETE:
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool parse_msg_data(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end) {
|
||||
if (tuc_pd_data_received_cb) {
|
||||
tuc_pd_data_received_cb(rhport, header, dobj, p_end);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_msg_control(uint8_t rhport, pd_header_t const* header) {
|
||||
if (tuc_pd_control_received_cb) {
|
||||
tuc_pd_control_received_cb(rhport, header);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool utcd_msg_send(uint8_t rhport, pd_header_t const* header, void const* data) {
|
||||
// copy header
|
||||
memcpy(_tx_buf, header, sizeof(pd_header_t));
|
||||
|
||||
// copy data objcet if available
|
||||
uint16_t const n_data_obj = header->n_data_obj;
|
||||
if (n_data_obj > 0) {
|
||||
memcpy(_tx_buf + sizeof(pd_header_t), data, n_data_obj * 4);
|
||||
}
|
||||
|
||||
return tcd_msg_send(rhport, _tx_buf, sizeof(pd_header_t) + n_data_obj * 4);
|
||||
}
|
||||
|
||||
bool tuc_msg_request(uint8_t rhport, void const* rdo) {
|
||||
pd_header_t const header = {
|
||||
.msg_type = PD_DATA_REQUEST,
|
||||
.data_role = PD_DATA_ROLE_UFP,
|
||||
.specs_rev = PD_REV_30,
|
||||
.power_role = PD_POWER_ROLE_SINK,
|
||||
.msg_id = 0,
|
||||
.n_data_obj = 1,
|
||||
.extended = 0,
|
||||
};
|
||||
|
||||
return utcd_msg_send(rhport, &header, rdo);
|
||||
}
|
||||
|
||||
void tcd_event_handler(tcd_event_t const * event, bool in_isr) {
|
||||
(void) in_isr;
|
||||
switch(event->event_id) {
|
||||
case TCD_EVENT_CC_CHANGED:
|
||||
if (event->cc_changed.cc_state[0] || event->cc_changed.cc_state[1]) {
|
||||
// Attach, start receiving
|
||||
tcd_msg_receive(event->rhport, _rx_buf, sizeof(_rx_buf));
|
||||
}else {
|
||||
// Detach
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
osal_queue_send(_utcd_q, event, in_isr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
void utcd_int_set(bool enabled) {
|
||||
// Disable all controllers since they shared the same event queue
|
||||
for (uint8_t p = 0; p < TUP_TYPEC_RHPORTS_NUM; p++) {
|
||||
if ( _port_inited[p] ) {
|
||||
if (enabled) {
|
||||
tcd_int_enable(p);
|
||||
}else {
|
||||
tcd_int_disable(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
91
src/typec/utcd.h
Normal file
91
src/typec/utcd.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 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_UTCD_H_
|
||||
#define _TUSB_UTCD_H_
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "pd_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TypeC Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifndef CFG_TUC_TASK_QUEUE_SZ
|
||||
#define CFG_TUC_TASK_QUEUE_SZ 8
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Init typec stack on a port
|
||||
bool tuc_init(uint8_t rhport, uint32_t port_type);
|
||||
|
||||
// Check if typec port is initialized
|
||||
bool tuc_inited(uint8_t rhport);
|
||||
|
||||
// Task function should be called in main/rtos loop, extended version of tud_task()
|
||||
// - timeout_ms: millisecond to wait, zero = no wait, 0xFFFFFFFF = wait forever
|
||||
// - in_isr: if function is called in ISR
|
||||
void tuc_task_ext(uint32_t timeout_ms, bool in_isr);
|
||||
|
||||
// Task function should be called in main/rtos loop
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tuc_task (void) {
|
||||
tuc_task_ext(UINT32_MAX, false);
|
||||
}
|
||||
|
||||
#ifndef _TUSB_TCD_H_
|
||||
extern void tcd_int_handler(uint8_t rhport);
|
||||
#endif
|
||||
|
||||
// Interrupt handler, name alias to TCD
|
||||
#define tuc_int_handler tcd_int_handler
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
TU_ATTR_WEAK bool tuc_pd_data_received_cb(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end);
|
||||
TU_ATTR_WEAK bool tuc_pd_control_received_cb(uint8_t rhport, pd_header_t const* header);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tuc_msg_request(uint8_t rhport, void const* rdo);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user