clang formatting stuff

This commit is contained in:
Triss 2021-06-29 01:03:02 +02:00
parent 4ec3f35ccd
commit 2905ff2116
33 changed files with 1863 additions and 1793 deletions

29
.clang-format Normal file
View File

@ -0,0 +1,29 @@
---
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 100
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
AlignConsecutiveAssignments: AcrossComments
AlignConsecutiveBitFields: AcrossComments
AlignConsecutiveDeclarations: AcrossComments
AlignConsecutiveMacros: AcrossComments
AlignOperands: AlignAfterOperator
AlignAfterOpenBracket: DontAlign
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: true
#AllowShortIfStatementsOnASingleLine: OnlyFirstIf
AllowShortLoopsOnASingleLine: true
BinPackArguments: true
BinPackParameters: true
BreakBeforeTernaryOperators: true
ContinuationIndentWidth: 8
SpaceInEmptyBlock: true
...

View File

@ -1,3 +1,4 @@
// vim: set et:
/*
* The MIT License (MIT)
*
@ -45,100 +46,99 @@ This information includes:
*/
#include "cmsis_compiler.h"
#include "util.h"
/// Processor Clock of the Cortex-M MCU used in the Debug Unit.
/// This value is used to calculate the SWD/JTAG clock speed.
#define CPU_CLOCK 48000000U ///< Specifies the CPU Clock in Hz.
#define CPU_CLOCK 48000000U ///< Specifies the CPU Clock in Hz.
/// Number of processor cycles for I/O Port write operations.
/// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O
/// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors
/// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses
/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be
/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be
/// required.
#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0.
#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0.
/// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available.
#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available.
/// Indicate that JTAG communication mode is available at the Debug Port.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available.
#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available.
/// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port.
/// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255.
#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain.
#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain.
/// Default communication mode on the Debug Access Port.
/// Used for the command \ref DAP_Connect when Port Default mode is selected.
#define DAP_DEFAULT_PORT 2U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG.
#define DAP_DEFAULT_PORT 2U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG.
/// Default communication speed on the Debug Access Port for SWD and JTAG mode.
/// Used to initialize the default SWD/JTAG clock frequency.
/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting.
#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz.
#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz.
/// Maximum Package Size for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the
/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB,
/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB.
#define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes.
/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or
/// WinUSB, 1024 for High-speed USB HID and 512 for High-speed USB WinUSB.
#define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes.
/// Maximum Package Buffers for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the
/// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the
/// setting can be reduced (valid range is 1 .. 255).
#define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered.
#define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered.
/// Indicate that UART Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available.
#define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available.
/// Maximum SWO UART Baudrate.
#define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz.
#define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz.
/// Indicate that Manchester Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available.
#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available.
/// SWO Trace Buffer Size.
#define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n).
#define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n).
/// SWO Streaming Trace.
#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available.
#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available.
/// Indicate that UART Communication Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_UART 0 ///< DAP UART: 1 = available, 0 = not available.
#define DAP_UART 0 ///< DAP UART: 1 = available, 0 = not available.
/// USART Driver instance number for the UART Communication Port.
#define DAP_UART_DRIVER 1 ///< USART Driver instance number (Driver_USART#).
#define DAP_UART_DRIVER 1 ///< USART Driver instance number (Driver_USART#).
/// UART Receive Buffer Size.
#define DAP_UART_RX_BUFFER_SIZE 64U ///< Uart Receive Buffer Size in bytes (must be 2^n).
#define DAP_UART_RX_BUFFER_SIZE 64U ///< Uart Receive Buffer Size in bytes (must be 2^n).
/// UART Transmit Buffer Size.
#define DAP_UART_TX_BUFFER_SIZE 64U ///< Uart Transmit Buffer Size in bytes (must be 2^n).
#define DAP_UART_TX_BUFFER_SIZE 64U ///< Uart Transmit Buffer Size in bytes (must be 2^n).
/// Indicate that UART Communication via USB COM Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#ifdef USE_USBCDC_FOR_STDIO
#define DAP_UART_USB_COM_PORT 1 ///< USB COM Port: 1 = available, 0 = not available.
#define DAP_UART_USB_COM_PORT 1 ///< USB COM Port: 1 = available, 0 = not available.
#else
#define DAP_UART_USB_COM_PORT 0
#define DAP_UART_USB_COM_PORT 0
#endif
/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET.
#define TIMESTAMP_CLOCK 0U ///< Timestamp clock in Hz (0 = timestamps not supported).
#define TIMESTAMP_CLOCK 0U ///< Timestamp clock in Hz (0 = timestamps not supported).
/// Debug Unit is connected to fixed Target Device.
/// The Debug Unit may be part of an evaluation board and always connected to a fixed
/// known device. In this case a Device Vendor and Device Name string is stored which
/// may be used by the debugger or IDE to configure device parameters.
#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown;
#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown;
#include "DAP.h"
@ -146,72 +146,84 @@ This information includes:
\param str Pointer to buffer to store the string.
\return String length.
*/
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
static const char vnd[] = INFO_MANUFACTURER;
for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i];
return sizeof(vnd)-1;
__STATIC_INLINE uint8_t DAP_GetVendorString(char* str) {
static const char vnd[] = INFO_MANUFACTURER;
for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i];
return sizeof(vnd) - 1;
}
/** Get Product ID string.
\param str Pointer to buffer to store the string.
\return String length.
*/
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i];
return sizeof(prd)-1;
__STATIC_INLINE uint8_t DAP_GetProductString(char* str) {
static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i];
return sizeof(prd) - 1;
}
/** Get Serial Number string.
\param str Pointer to buffer to store the string.
\return String length.
*/
__STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) {
return get_unique_id_u8((uint8_t*)str);
}
__STATIC_INLINE uint8_t DAP_GetSerNumString(char* str) { return get_unique_id_u8((uint8_t*)str); }
/** Get Target Device Vendor string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetDeviceVendorString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetDeviceVendorString(char* str) {
(void)str;
return 0;
}
/** Get Target Device Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetDeviceNameString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetDeviceNameString(char* str) {
(void)str;
return 0;
}
/** Get Target Board Vendor string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetBoardVendorString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetBoardVendorString(char* str) {
(void)str;
return 0;
}
/** Get Target Board Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetBoardNameString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetBoardNameString(char* str) {
(void)str;
return 0;
}
/* TODO! */
/** Get Product Firmware Version string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetProductFirmwareVersionString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetProductFirmwareVersionString(char* str) {
(void)str;
return 0;
}
///@}
//**************************************************************************************************
/**
/**
\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access
\ingroup DAP_ConfigIO_gr
\ingroup DAP_ConfigIO_gr
@{
Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode
and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug
and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug
interface of a device. The following I/O Pins are provided:
JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode
@ -219,19 +231,19 @@ JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mod
TCK: Test Clock | SWCLK: Clock | Output Push/Pull
TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data)
TDI: Test Data Input | | Output Push/Pull
TDO: Test Data Output | | Input
TDO: Test Data Output | | Input
nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor
nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor
DAP Hardware I/O Pin Access Functions
-------------------------------------
The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins.
The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins.
For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only.
This functions are provided to achieve faster I/O that is possible with some advanced GPIO
peripherals that can independently write/read a single I/O pin without affecting any other pins
This functions are provided to achieve faster I/O that is possible with some advanced GPIO
peripherals that can independently write/read a single I/O pin without affecting any other pins
of the same I/O port. The following SWDIO I/O Pin functions are provided:
- \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware.
- \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware.
@ -239,7 +251,6 @@ of the same I/O port. The following SWDIO I/O Pin functions are provided:
- \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed.
*/
// Configure DAP I/O pins ------------------------------
/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET.
@ -247,167 +258,130 @@ Configures the DAP Hardware I/O pins for JTAG mode:
- TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level.
- TDO to input mode.
*/
__STATIC_INLINE void PORT_JTAG_SETUP (void) {
}
__STATIC_INLINE void PORT_JTAG_SETUP(void) { }
/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET.
Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
- SWCLK, SWDIO, nRESET to output mode and set to default high level.
- TDI, nTRST to HighZ mode (pins are unused in SWD mode).
*/
__STATIC_INLINE void PORT_SWD_SETUP (void) {
}
__STATIC_INLINE void PORT_SWD_SETUP(void) { }
/** Disable JTAG/SWD I/O Pins.
Disables the DAP Hardware I/O pins which configures:
- TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode.
*/
__STATIC_INLINE void PORT_OFF (void) {
}
__STATIC_INLINE void PORT_OFF(void) { }
// SWCLK/TCK I/O pin -------------------------------------
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return 0;
}
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) { return 0; }
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {
}
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET(void) { }
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
}
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) { }
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return 0;
}
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) { return 0; }
/* PIN_SWDIO_TMS_SET and PIN_SWDIO_TMS_CLR are used by SWJ_Sequence */
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
}
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void) { }
/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {
}
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) { }
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return 0;
}
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) { return 0; }
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
(void)bit;
}
__STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) { (void)bit; }
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
}
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) { }
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
}
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) { }
// TDI Pin I/O ---------------------------------------------
/** TDI I/O pin: Get Input.
\return Current status of the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) {
return 0;
}
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) { return 0; }
/** TDI I/O pin: Set Output.
\param bit Output value for the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) {
(void)bit;
}
__STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) { (void)bit; }
// TDO Pin I/O ---------------------------------------------
/** TDO I/O pin: Get Input.
\return Current status of the TDO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) {
return 0;
}
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) { return 0; }
// nTRST Pin I/O -------------------------------------------
/** nTRST I/O pin: Get Input.
\return Current status of the nTRST DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) {
return 0;
}
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) { return 0; }
/** nTRST I/O pin: Set Output.
\param bit JTAG TRST Test Reset pin status:
- 0: issue a JTAG TRST Test Reset.
- 1: release JTAG TRST Test Reset.
*/
__STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
(void)bit;
}
__STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) { (void)bit; }
// nRESET Pin I/O------------------------------------------
/** nRESET I/O pin: Get Input.
\return Current status of the nRESET DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
return 0;
}
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) { return 0; }
/** nRESET I/O pin: Set Output.
\param bit target device hardware reset pin status:
- 0: issue a device hardware reset.
- 1: release device hardware reset.
*/
__STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) {
(void)bit;
}
__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) { (void)bit; }
///@}
//**************************************************************************************************
/**
/**
\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs
\ingroup DAP_ConfigIO_gr
@{
@ -424,22 +398,17 @@ It is recommended to provide the following LEDs for status indication:
- 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit.
- 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit.
*/
__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
(void)bit;
}
__STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit) { (void)bit; }
/** Debug Unit: Set status Target Running LED.
\param bit status of the Target Running LED.
- 1: Target Running LED ON: program execution in target started.
- 0: Target Running LED OFF: program execution in target stopped.
*/
__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {
(void)bit;
}
__STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit) { (void)bit; }
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp
@ -447,25 +416,25 @@ __STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {
@{
Access function for Test Domain Timer.
The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By
default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK.
The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET.
By default, the DWT timer is used. The frequency of this timer is configured with \ref
TIMESTAMP_CLOCK.
*/
/** Get timestamp of Test Domain Timer.
\return Current timestamp value.
*/
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {
__STATIC_INLINE uint32_t TIMESTAMP_GET(void) {
#if TIMESTAMP_CLOCK > 0
return (DWT->CYCCNT);
return (DWT->CYCCNT);
#else
return 0;
return 0;
#endif
}
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization
@ -476,25 +445,24 @@ CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_S
*/
/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized).
This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the
This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the
Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set:
- I/O clock system enabled.
- all I/O pins: input buffer enabled, output pins are set to HighZ mode.
- for nTRST, nRESET a weak pull-up (if available) is enabled.
- LED output pins are enabled and LEDs are turned off.
*/
__STATIC_INLINE void DAP_SETUP (void) {
}
__STATIC_INLINE void DAP_SETUP(void) { }
/** Reset Target Device with custom specific I/O pin or command sequence.
This function allows the optional implementation of a device specific reset sequence.
It is called when the command \ref DAP_ResetTarget and is for example required
It is called when the command \ref DAP_ResetTarget and is for example required
when a device needs a time-critical unlock sequence that enables the debug port.
\return 0 = no device specific reset sequence is implemented.\n
1 = a device specific reset sequence is implemented.
*/
__STATIC_INLINE uint8_t RESET_TARGET (void) {
return (0U); // change to '1' when a device reset sequence is implemented
__STATIC_INLINE uint8_t RESET_TARGET(void) {
return (0U); // change to '1' when a device reset sequence is implemented
}
///@}

View File

@ -1,11 +1,10 @@
// vim: set et:
#include "protos.h"
void cdc_uart_init(void) {
}
void cdc_uart_init(void) { }
void cdc_uart_task(void) {
}
void cdc_uart_task(void) { }
void cdc_uart_set_hwflow(bool enable) { (void)enable; }
void cdc_uart_set_baud_rate(uint32_t brate) { (void)brate; }

View File

@ -1,36 +1,36 @@
// vim: set et:
#include "i2ctinyusb.h"
__attribute__((__const__))
enum ki2c_funcs i2ctu_get_func(void) { return 0; }
__attribute__((__const__)) enum ki2c_funcs i2ctu_get_func(void) { return 0; }
void i2ctu_init(void) { }
uint32_t i2ctu_set_freq(uint32_t freq, uint32_t us) {
(void)freq;
(void)us;
(void)freq;
(void)us;
return 0;
return 0;
}
enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, const uint8_t* buf, size_t len) {
(void)flags;
(void)startstopflags;
(void)addr;
(void)buf;
(void)len;
enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr,
const uint8_t* buf, size_t len) {
(void)flags;
(void)startstopflags;
(void)addr;
(void)buf;
(void)len;
return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_NAK;
}
enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, uint8_t* buf, size_t len) {
(void)flags;
(void)startstopflags;
(void)addr;
(void)buf;
(void)len;
enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr,
uint8_t* buf, size_t len) {
(void)flags;
(void)startstopflags;
(void)addr;
(void)buf;
(void)len;
return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_NAK;
}

View File

@ -1,3 +1,4 @@
// vim: set et:
#ifndef PROTOCFG_H_
#define PROTOCFG_H_
@ -9,22 +10,20 @@
#define DBOARD_HAS_TEMPSENSOR*/
enum {
/*HID_N_CMSISDAP = 0,*/
/*HID_N_CMSISDAP = 0,*/
HID_N__NITF
HID_N__NITF
};
enum {
/*CDC_N_UART = 0,
CDC_N_SERPROG,*/
/*CDC_N_UART = 0,
CDC_N_SERPROG,*/
#ifdef USE_USBCDC_FOR_STDIO
CDC_N_STDIO,
CDC_N_STDIO,
#endif
CDC_N__NITF
};
enum {
VND_N__NITF = 0
CDC_N__NITF
};
enum { VND_N__NITF = 0 };
#define CFG_TUD_HID 0
#ifdef USE_USBCDC_FOR_STDIO
@ -35,7 +34,7 @@ enum {
#define CFG_TUD_VENDOR 0
/*#define USB_VID 0x2e8a*/ /* Raspberry Pi */
#define USB_VID 0xcafe /* TinyUSB */
#define USB_VID 0xcafe /* TinyUSB */
/*#define USB_VID 0x1209*/ /* Generic */
/*#define USB_VID 0x1d50*/ /* OpenMoko */
#define USB_PID 0x1312

View File

@ -1,3 +1,4 @@
// vim: set et:
#include "protos.h"
#include "serprog.h"
@ -5,8 +6,8 @@
void sp_spi_init(void) { }
uint32_t __not_in_flash_func(sp_spi_set_freq)(uint32_t freq_wanted) {
(void)freq_wanted;
return 0;
(void)freq_wanted;
return 0;
}
void __not_in_flash_func(sp_spi_cs_deselect)(void) { }
@ -15,11 +16,11 @@ void __not_in_flash_func(sp_spi_op_begin)(void) { }
void __not_in_flash_func(sp_spi_op_end)(void) { }
void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const uint8_t* write_data) {
(void)write_len;
(void)write_data;
(void)write_len;
(void)write_data;
}
void __not_in_flash_func(sp_spi_op_read)(uint32_t read_len, uint8_t* read_data) {
(void)read_len;
(void)read_data;
(void)read_len;
(void)read_data;
}

View File

@ -1,11 +1,14 @@
// vim: set et:
#include "tempsensor.h"
void tempsense_dev_init(void) { }
// clang-format off
// 8.4
int16_t tempsense_dev_get_temp (void) { return 0 << 4; }
int16_t tempsense_dev_get_lower(void) { return trunc_8fix4(float2fix( 0)); }
int16_t tempsense_dev_get_upper(void) { return trunc_8fix4(float2fix( 0)); }
int16_t tempsense_dev_get_crit (void) { return trunc_8fix4(float2fix( 0)); }
// clang-format on

View File

@ -1,3 +1,5 @@
// vim: set et:
#include <stdint.h>
#include "util.h"

View File

@ -1,3 +1,4 @@
// vim: set et:
/*
* The MIT License (MIT)
*
@ -44,21 +45,21 @@ This information includes:
- Optional information about a connected Target Device (for Evaluation Boards).
*/
#include "cmsis_compiler.h"
#include "bsp/board.h"
#include <stdint.h>
#include <hardware/regs/resets.h>
#include <hardware/structs/resets.h>
#include <hardware/regs/sio.h>
#include <hardware/structs/sio.h>
#include <hardware/regs/pads_bank0.h>
#include <hardware/structs/padsbank0.h>
#include <hardware/regs/io_bank0.h>
#include <hardware/structs/iobank0.h>
#include <hardware/gpio.h>
#include <hardware/regs/io_bank0.h>
#include <hardware/regs/pads_bank0.h>
#include <hardware/regs/resets.h>
#include <hardware/regs/sio.h>
#include <hardware/structs/iobank0.h>
#include <hardware/structs/padsbank0.h>
#include <hardware/structs/resets.h>
#include <hardware/structs/sio.h>
#include <pico/binary_info.h>
#include "bsp/board.h"
#include "cmsis_compiler.h"
#include "pinout.h"
#include "protos.h"
#include "util.h"
@ -69,110 +70,110 @@ This information includes:
#define PINOUT_SWCLK_MASK (1UL << PINOUT_SWCLK)
#define PINOUT_SWDIO_MASK (1UL << PINOUT_SWDIO)
#define PINOUT_TCK_MASK (1UL << PINOUT_JTAG_TCK)
#define PINOUT_TMS_MASK (1UL << PINOUT_JTAG_TMS)
#define PINOUT_TDI_MASK (1UL << PINOUT_JTAG_TDI)
#define PINOUT_TDO_MASK (1UL << PINOUT_JTAG_TDO)
#define PINOUT_nTRST_MASK (1UL << PINOUT_JTAG_nTRST)
#define PINOUT_TCK_MASK (1UL << PINOUT_JTAG_TCK)
#define PINOUT_TMS_MASK (1UL << PINOUT_JTAG_TMS)
#define PINOUT_TDI_MASK (1UL << PINOUT_JTAG_TDI)
#define PINOUT_TDO_MASK (1UL << PINOUT_JTAG_TDO)
#define PINOUT_nTRST_MASK (1UL << PINOUT_JTAG_nTRST)
#define PINOUT_nRESET_MASK (1UL << PINOUT_JTAG_nRESET)
#define PINOUT_LED_MASK (1UL << PINOUT_LED)
/// Processor Clock of the Cortex-M MCU used in the Debug Unit.
/// This value is used to calculate the SWD/JTAG clock speed.
#define CPU_CLOCK 48000000U ///< Specifies the CPU Clock in Hz.
#define CPU_CLOCK 48000000U ///< Specifies the CPU Clock in Hz.
/// Number of processor cycles for I/O Port write operations.
/// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O
/// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors
/// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses
/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be
/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be
/// required.
#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0.
#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0.
/// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available.
#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available.
/// Indicate that JTAG communication mode is available at the Debug Port.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available.
#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available.
/// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port.
/// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255.
#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain.
#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain.
/// Default communication mode on the Debug Access Port.
/// Used for the command \ref DAP_Connect when Port Default mode is selected.
#define DAP_DEFAULT_PORT 2U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG.
#define DAP_DEFAULT_PORT 2U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG.
/// Default communication speed on the Debug Access Port for SWD and JTAG mode.
/// Used to initialize the default SWD/JTAG clock frequency.
/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting.
#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz.
#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz.
/// Maximum Package Size for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the
/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB,
/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB.
#define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes.
/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or
/// WinUSB, 1024 for High-speed USB HID and 512 for High-speed USB WinUSB.
#define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes.
/// Maximum Package Buffers for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the
/// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the
/// setting can be reduced (valid range is 1 .. 255).
#define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered.
#define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered.
/// Indicate that UART Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available.
#define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available.
/// Maximum SWO UART Baudrate.
#define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz.
#define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz.
/// Indicate that Manchester Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available.
#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available.
/// SWO Trace Buffer Size.
#define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n).
#define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n).
/// SWO Streaming Trace.
#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available.
#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available.
/// Indicate that UART Communication Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_UART 0 ///< DAP UART: 1 = available, 0 = not available.
#define DAP_UART 0 ///< DAP UART: 1 = available, 0 = not available.
/// USART Driver instance number for the UART Communication Port.
#define DAP_UART_DRIVER 1 ///< USART Driver instance number (Driver_USART#).
#define DAP_UART_DRIVER 1 ///< USART Driver instance number (Driver_USART#).
/// UART Receive Buffer Size.
#define DAP_UART_RX_BUFFER_SIZE 64U ///< Uart Receive Buffer Size in bytes (must be 2^n).
#define DAP_UART_RX_BUFFER_SIZE 64U ///< Uart Receive Buffer Size in bytes (must be 2^n).
/// UART Transmit Buffer Size.
#define DAP_UART_TX_BUFFER_SIZE 64U ///< Uart Transmit Buffer Size in bytes (must be 2^n).
#define DAP_UART_TX_BUFFER_SIZE 64U ///< Uart Transmit Buffer Size in bytes (must be 2^n).
/// Indicate that UART Communication via USB COM Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#ifdef USE_USBCDC_FOR_STDIO
#define DAP_UART_USB_COM_PORT 1 ///< USB COM Port: 1 = available, 0 = not available.
#define DAP_UART_USB_COM_PORT 1 ///< USB COM Port: 1 = available, 0 = not available.
#else
#define DAP_UART_USB_COM_PORT 0
#define DAP_UART_USB_COM_PORT 0
#endif
/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET.
#define TIMESTAMP_CLOCK 0U ///< Timestamp clock in Hz (0 = timestamps not supported).
#define TIMESTAMP_CLOCK 0U ///< Timestamp clock in Hz (0 = timestamps not supported).
/// Debug Unit is connected to fixed Target Device.
/// The Debug Unit may be part of an evaluation board and always connected to a fixed
/// known device. In this case a Device Vendor and Device Name string is stored which
/// may be used by the debugger or IDE to configure device parameters.
#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown;
#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown;
#if TARGET_DEVICE_FIXED
#define TARGET_DEVICE_VENDOR "Raspberry Pi" ///< String indicating the Silicon Vendor
#define TARGET_DEVICE_NAME "Pico" ///< String indicating the Target Device
#define TARGET_DEVICE_VENDOR "Raspberry Pi" ///< String indicating the Silicon Vendor
#define TARGET_DEVICE_NAME "Pico" ///< String indicating the Target Device
#endif
#include "DAP.h"
@ -181,72 +182,84 @@ This information includes:
\param str Pointer to buffer to store the string.
\return String length.
*/
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
static const char vnd[] = INFO_MANUFACTURER;
for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i];
return sizeof(vnd)-1;
__STATIC_INLINE uint8_t DAP_GetVendorString(char* str) {
static const char vnd[] = INFO_MANUFACTURER;
for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i];
return sizeof(vnd) - 1;
}
/** Get Product ID string.
\param str Pointer to buffer to store the string.
\return String length.
*/
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i];
return sizeof(prd)-1;
__STATIC_INLINE uint8_t DAP_GetProductString(char* str) {
static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i];
return sizeof(prd) - 1;
}
/** Get Serial Number string.
\param str Pointer to buffer to store the string.
\return String length.
*/
__STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) {
return get_unique_id_u8((uint8_t*)str);
}
__STATIC_INLINE uint8_t DAP_GetSerNumString(char* str) { return get_unique_id_u8((uint8_t*)str); }
/** Get Target Device Vendor string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetDeviceVendorString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetDeviceVendorString(char* str) {
(void)str;
return 0;
}
/** Get Target Device Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetDeviceNameString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetDeviceNameString(char* str) {
(void)str;
return 0;
}
/** Get Target Board Vendor string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetBoardVendorString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetBoardVendorString(char* str) {
(void)str;
return 0;
}
/** Get Target Board Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetBoardNameString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetTargetBoardNameString(char* str) {
(void)str;
return 0;
}
/* TODO! */
/** Get Product Firmware Version string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetProductFirmwareVersionString (char *str) { (void)str; return 0; }
__STATIC_INLINE uint8_t DAP_GetProductFirmwareVersionString(char* str) {
(void)str;
return 0;
}
///@}
//**************************************************************************************************
/**
/**
\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access
\ingroup DAP_ConfigIO_gr
\ingroup DAP_ConfigIO_gr
@{
Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode
and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug
and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug
interface of a device. The following I/O Pins are provided:
JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode
@ -254,19 +267,19 @@ JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mod
TCK: Test Clock | SWCLK: Clock | Output Push/Pull
TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data)
TDI: Test Data Input | | Output Push/Pull
TDO: Test Data Output | | Input
TDO: Test Data Output | | Input
nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor
nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor
DAP Hardware I/O Pin Access Functions
-------------------------------------
The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins.
The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins.
For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only.
This functions are provided to achieve faster I/O that is possible with some advanced GPIO
peripherals that can independently write/read a single I/O pin without affecting any other pins
This functions are provided to achieve faster I/O that is possible with some advanced GPIO
peripherals that can independently write/read a single I/O pin without affecting any other pins
of the same I/O port. The following SWDIO I/O Pin functions are provided:
- \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware.
- \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware.
@ -274,7 +287,6 @@ of the same I/O port. The following SWDIO I/O Pin functions are provided:
- \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed.
*/
// Configure DAP I/O pins ------------------------------
/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET.
@ -282,45 +294,45 @@ Configures the DAP Hardware I/O pins for JTAG mode:
- TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level.
- TDO to input mode.
*/
__STATIC_INLINE void PORT_JTAG_SETUP (void) {
resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS);
__STATIC_INLINE void PORT_JTAG_SETUP(void) {
resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS);
/* set to default high level */
sio_hw->gpio_oe_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
sio_hw->gpio_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
/* TDO needs to be an input */
sio_hw->gpio_oe_clr = PINOUT_TDO_MASK;
/* set to default high level */
sio_hw->gpio_oe_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK |
PINOUT_nRESET_MASK;
sio_hw->gpio_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK |
PINOUT_nRESET_MASK;
/* TDO needs to be an input */
sio_hw->gpio_oe_clr = PINOUT_TDO_MASK;
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TCK],
PADS_BANK0_GPIO0_IE_BITS, // bits to set: input enable
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); // bits to mask out: input enable, output disable
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TMS],
PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDI],
PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDO],
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS, // TDO needs to have its output disabled
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nTRST],
PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nRESET],
PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TCK],
PADS_BANK0_GPIO0_IE_BITS, // bits to set: input enable
PADS_BANK0_GPIO0_IE_BITS |
PADS_BANK0_GPIO0_OD_BITS); // bits to mask out: input enable, output disable
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TMS], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDI], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDO],
PADS_BANK0_GPIO0_IE_BITS |
PADS_BANK0_GPIO0_OD_BITS, // TDO needs to have its output disabled
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nTRST], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nRESET], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
// NOTE: hiZ: ctrl = (ctrl & ~(CTRL_OEOVER_BITS)) | (GPIO_OVERRIDE_LOW << CTRL_OEOVER_LSB);
// normal == 0, low == 2
// NOTE: hiZ: ctrl = (ctrl & ~(CTRL_OEOVER_BITS)) | (GPIO_OVERRIDE_LOW << CTRL_OEOVER_LSB);
// normal == 0, low == 2
// set pin modes to general IO (SIO)
iobank0_hw->io[PINOUT_JTAG_TCK].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_TMS].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_TDI].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_TDO].ctrl = (GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB)
/*| (GPIO_OVERRIDE_LOW << IO_BANK0_GPIO0_CTRL_OEOVER_LSB)*/;
iobank0_hw->io[PINOUT_JTAG_nTRST].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_nRESET].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
// set pin modes to general IO (SIO)
iobank0_hw->io[PINOUT_JTAG_TCK].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_TMS].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_TDI].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_TDO].ctrl = (GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB)
/*| (GPIO_OVERRIDE_LOW << IO_BANK0_GPIO0_CTRL_OEOVER_LSB)*/;
iobank0_hw->io[PINOUT_JTAG_nTRST].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_JTAG_nRESET].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
}
/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET.
@ -328,61 +340,57 @@ Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
- SWCLK, SWDIO, nRESET to output mode and set to default high level.
- TDI, nTRST to HighZ mode (pins are unused in SWD mode).
*/
__STATIC_INLINE void PORT_SWD_SETUP (void) {
resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS);
__STATIC_INLINE void PORT_SWD_SETUP(void) {
resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS);
/* set to default high level */
sio_hw->gpio_oe_set = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK;
sio_hw->gpio_set = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK;
/* set to default high level */
sio_hw->gpio_oe_set = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK;
sio_hw->gpio_set = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK;
hw_write_masked(&padsbank0_hw->io[PINOUT_SWCLK], PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_SWDIO], PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
iobank0_hw->io[PINOUT_SWCLK].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_SWDIO].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
hw_write_masked(&padsbank0_hw->io[PINOUT_SWCLK], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_SWDIO], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
iobank0_hw->io[PINOUT_SWCLK].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
iobank0_hw->io[PINOUT_SWDIO].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
}
/** Disable JTAG/SWD I/O Pins.
Disables the DAP Hardware I/O pins which configures:
- TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode.
*/
__STATIC_INLINE void PORT_OFF (void) {
sio_hw->gpio_oe_clr = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK
| PINOUT_TDI_MASK //| PINOUT_TDO_MASK
| PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
__STATIC_INLINE void PORT_OFF(void) {
sio_hw->gpio_oe_clr = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK |
PINOUT_TDI_MASK //| PINOUT_TDO_MASK
| PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
}
// SWCLK/TCK I/O pin -------------------------------------
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (sio_hw->gpio_in & PINOUT_SWCLK_MASK) >> PINOUT_SWCLK;
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) {
return (sio_hw->gpio_in & PINOUT_SWCLK_MASK) >> PINOUT_SWCLK;
}
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {
sio_hw->gpio_set = PINOUT_SWCLK_MASK;
}
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET(void) { sio_hw->gpio_set = PINOUT_SWCLK_MASK; }
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
sio_hw->gpio_clr = PINOUT_SWCLK_MASK;
}
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) { sio_hw->gpio_clr = PINOUT_SWCLK_MASK; }
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) >> PINOUT_SWDIO;
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) {
return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) >> PINOUT_SWDIO;
}
/* PIN_SWDIO_TMS_SET and PIN_SWDIO_TMS_CLR are used by SWJ_Sequence */
@ -390,88 +398,77 @@ __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
sio_hw->gpio_set = PINOUT_SWDIO_MASK;
}
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void) { sio_hw->gpio_set = PINOUT_SWDIO_MASK; }
/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {
sio_hw->gpio_clr = PINOUT_SWDIO_MASK;
}
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) { sio_hw->gpio_clr = PINOUT_SWDIO_MASK; }
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) ? 1U : 0U;
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) {
return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) ? 1U : 0U;
}
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_SWDIO_MASK;
else
sio_hw->gpio_clr = PINOUT_SWDIO_MASK;
__STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_SWDIO_MASK;
else
sio_hw->gpio_clr = PINOUT_SWDIO_MASK;
}
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
sio_hw->gpio_oe_set = PINOUT_SWDIO_MASK;
}
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) { sio_hw->gpio_oe_set = PINOUT_SWDIO_MASK; }
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
sio_hw->gpio_oe_clr = PINOUT_SWDIO_MASK;
}
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) { sio_hw->gpio_oe_clr = PINOUT_SWDIO_MASK; }
// TDI Pin I/O ---------------------------------------------
/** TDI I/O pin: Get Input.
\return Current status of the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) {
return (sio_hw->gpio_in & PINOUT_TDI_MASK) >> PINOUT_JTAG_TDI;
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) {
return (sio_hw->gpio_in & PINOUT_TDI_MASK) >> PINOUT_JTAG_TDI;
}
/** TDI I/O pin: Set Output.
\param bit Output value for the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_TDI_MASK;
else
sio_hw->gpio_clr = PINOUT_TDI_MASK;
__STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_TDI_MASK;
else
sio_hw->gpio_clr = PINOUT_TDI_MASK;
}
// TDO Pin I/O ---------------------------------------------
/** TDO I/O pin: Get Input.
\return Current status of the TDO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) {
return (sio_hw->gpio_in & PINOUT_TDO_MASK) >> PINOUT_JTAG_TDO;
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) {
return (sio_hw->gpio_in & PINOUT_TDO_MASK) >> PINOUT_JTAG_TDO;
}
// nTRST Pin I/O -------------------------------------------
/** nTRST I/O pin: Get Input.
\return Current status of the nTRST DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) {
return (sio_hw->gpio_in & PINOUT_nTRST_MASK) >> PINOUT_JTAG_nTRST;
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) {
return (sio_hw->gpio_in & PINOUT_nTRST_MASK) >> PINOUT_JTAG_nTRST;
}
/** nTRST I/O pin: Set Output.
@ -479,11 +476,11 @@ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) {
- 0: issue a JTAG TRST Test Reset.
- 1: release JTAG TRST Test Reset.
*/
__STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_nTRST_MASK;
else
sio_hw->gpio_clr = PINOUT_nTRST_MASK;
__STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_nTRST_MASK;
else
sio_hw->gpio_clr = PINOUT_nTRST_MASK;
}
// nRESET Pin I/O------------------------------------------
@ -491,8 +488,8 @@ __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
/** nRESET I/O pin: Get Input.
\return Current status of the nRESET DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
return (sio_hw->gpio_in & PINOUT_nRESET_MASK) >> PINOUT_JTAG_nRESET;
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) {
return (sio_hw->gpio_in & PINOUT_nRESET_MASK) >> PINOUT_JTAG_nRESET;
}
/** nRESET I/O pin: Set Output.
@ -500,18 +497,17 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
- 0: issue a device hardware reset.
- 1: release device hardware reset.
*/
__STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_nRESET_MASK;
else
sio_hw->gpio_clr = PINOUT_nRESET_MASK;
__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) {
if (bit & 1)
sio_hw->gpio_set = PINOUT_nRESET_MASK;
else
sio_hw->gpio_clr = PINOUT_nRESET_MASK;
}
///@}
//**************************************************************************************************
/**
/**
\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs
\ingroup DAP_ConfigIO_gr
@{
@ -528,14 +524,14 @@ It is recommended to provide the following LEDs for status indication:
- 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit.
- 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit.
*/
__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
__STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit) {
#if PINOUT_LED_CONNECTED
if (bit & 1)
sio_hw->gpio_set = PINOUT_LED_MASK;
else
sio_hw->gpio_clr = PINOUT_LED_MASK;
if (bit & 1)
sio_hw->gpio_set = PINOUT_LED_MASK;
else
sio_hw->gpio_clr = PINOUT_LED_MASK;
#else
(void)bit;
(void)bit;
#endif
}
@ -544,20 +540,19 @@ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
- 1: Target Running LED ON: program execution in target started.
- 0: Target Running LED OFF: program execution in target stopped.
*/
__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {
__STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit) {
#if PINOUT_LED_RUNNING
if (bit & 1)
sio_hw->gpio_set = PINOUT_LED_MASK;
else
sio_hw->gpio_clr = PINOUT_LED_MASK;
if (bit & 1)
sio_hw->gpio_set = PINOUT_LED_MASK;
else
sio_hw->gpio_clr = PINOUT_LED_MASK;
#else
(void)bit;
(void)bit;
#endif
}
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp
@ -565,25 +560,25 @@ __STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {
@{
Access function for Test Domain Timer.
The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By
default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK.
The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET.
By default, the DWT timer is used. The frequency of this timer is configured with \ref
TIMESTAMP_CLOCK.
*/
/** Get timestamp of Test Domain Timer.
\return Current timestamp value.
*/
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {
__STATIC_INLINE uint32_t TIMESTAMP_GET(void) {
#if TIMESTAMP_CLOCK > 0
return (DWT->CYCCNT);
return (DWT->CYCCNT);
#else
return 0;
return 0;
#endif
}
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization
@ -594,41 +589,35 @@ CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_S
*/
/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized).
This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the
This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the
Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set:
- I/O clock system enabled.
- all I/O pins: input buffer enabled, output pins are set to HighZ mode.
- for nTRST, nRESET a weak pull-up (if available) is enabled.
- LED output pins are enabled and LEDs are turned off.
*/
__STATIC_INLINE void DAP_SETUP (void) {
sio_hw->gpio_oe_set = PINOUT_LED_MASK;
sio_hw->gpio_clr = PINOUT_LED_MASK;
__STATIC_INLINE void DAP_SETUP(void) {
sio_hw->gpio_oe_set = PINOUT_LED_MASK;
sio_hw->gpio_clr = PINOUT_LED_MASK;
hw_write_masked(&padsbank0_hw->io[PINOUT_LED], 0, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
iobank0_hw->io[PINOUT_LED].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
hw_write_masked(
&padsbank0_hw->io[PINOUT_LED], 0, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
iobank0_hw->io[PINOUT_LED].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
bi_decl(bi_2pins_with_names(
PINOUT_JTAG_TCK, "TCK / SWCLK",
PINOUT_JTAG_TMS, "TMS / SWDIO"
));
bi_decl(bi_4pins_with_names(
PINOUT_JTAG_TDI , "TDI",
PINOUT_JTAG_TDO , "TDO",
PINOUT_JTAG_nTRST , "nTRST",
PINOUT_JTAG_nRESET, "nRESET"
));
bi_decl(bi_2pins_with_names(PINOUT_JTAG_TCK, "TCK / SWCLK", PINOUT_JTAG_TMS, "TMS / SWDIO"));
bi_decl(bi_4pins_with_names(PINOUT_JTAG_TDI, "TDI", PINOUT_JTAG_TDO, "TDO", PINOUT_JTAG_nTRST,
"nTRST", PINOUT_JTAG_nRESET, "nRESET"));
}
/** Reset Target Device with custom specific I/O pin or command sequence.
This function allows the optional implementation of a device specific reset sequence.
It is called when the command \ref DAP_ResetTarget and is for example required
It is called when the command \ref DAP_ResetTarget and is for example required
when a device needs a time-critical unlock sequence that enables the debug port.
\return 0 = no device specific reset sequence is implemented.\n
1 = a device specific reset sequence is implemented.
*/
__STATIC_INLINE uint8_t RESET_TARGET (void) {
return (0U); // change to '1' when a device reset sequence is implemented
__STATIC_INLINE uint8_t RESET_TARGET(void) {
return (0U); // change to '1' when a device reset sequence is implemented
}
///@}

View File

@ -1,4 +1,5 @@
/*
// vim: set et:
/*
* The MIT License (MIT)
*
* Copyright (c) 2021, Ha Thach (tinyusb.org)
@ -32,18 +33,19 @@ extern "C" {
#endif
#ifdef PICO_DEFAULT_LED_PIN
#define LED_PIN PICO_DEFAULT_LED_PIN
#define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED))
#define LED_PIN PICO_DEFAULT_LED_PIN
#define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED))
#endif
// Button pin is BOOTSEL which is flash CS pin
#define BUTTON_BOOTSEL
#define BUTTON_STATE_ACTIVE 0
#define BUTTON_STATE_ACTIVE 0
#if !defined(USE_USBCDC_FOR_STDIO) && defined(PICO_DEFAULT_UART_TX_PIN) && defined(PICO_DEFAULT_UART_RX_PIN) && defined(PICO_DEFAULT_UART)
#define UART_DEV PICO_DEFAULT_UART
#define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN
#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN
#if !defined(USE_USBCDC_FOR_STDIO) && defined(PICO_DEFAULT_UART_TX_PIN) && \
defined(PICO_DEFAULT_UART_RX_PIN) && defined(PICO_DEFAULT_UART)
#define UART_DEV PICO_DEFAULT_UART
#define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN
#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN
#endif
#ifdef __cplusplus

View File

@ -1,15 +1,15 @@
// vim: set et:
#include <pico/time.h>
#include <pico/stdio.h>
#include <pico/stdio/driver.h>
#include <hardware/irq.h>
#include <pico/binary_info.h>
#include <pico/mutex.h>
#include <hardware/irq.h>
#include "tusb.h"
#include <pico/stdio.h>
#include <pico/stdio/driver.h>
#include <pico/time.h>
#include "pinout.h"
#include "protocfg.h"
#include "tusb.h"
#ifndef PICO_STDIO_USB_STDOUT_TIMEOUT_US
#define PICO_STDIO_USB_STDOUT_TIMEOUT_US 500000
@ -22,85 +22,88 @@
static mutex_t stdio_usb_mutex;
static void stdio_usb_out_chars(const char* buf, int length) {
static uint64_t last_avail_time;
uint32_t owner;
static uint64_t last_avail_time;
uint32_t owner;
if (!mutex_try_enter(&stdio_usb_mutex, &owner)) {
if (owner == get_core_num()) return; // would deadlock otherwise
mutex_enter_blocking(&stdio_usb_mutex);
}
if (!mutex_try_enter(&stdio_usb_mutex, &owner)) {
if (owner == get_core_num()) return; // would deadlock otherwise
mutex_enter_blocking(&stdio_usb_mutex);
}
if (tud_cdc_n_connected(CDC_N_STDIO)) {
for (int i = 0; i < length; ) {
int n = length - i;
int avail = tud_cdc_n_write_available(CDC_N_STDIO);
if (tud_cdc_n_connected(CDC_N_STDIO)) {
for (int i = 0; i < length;) {
int n = length - i;
int avail = tud_cdc_n_write_available(CDC_N_STDIO);
if (n > avail) n = avail;
if (n) {
int n2 = tud_cdc_n_write(CDC_N_STDIO, buf+i, n);
tud_task();
tud_cdc_n_write_flush(CDC_N_STDIO);
i += n2;
last_avail_time = time_us_64();
} else {
tud_task();
tud_cdc_n_write_flush(CDC_N_STDIO);
if (n > avail) n = avail;
if (n) {
int n2 = tud_cdc_n_write(CDC_N_STDIO, buf + i, n);
tud_task();
tud_cdc_n_write_flush(CDC_N_STDIO);
i += n2;
last_avail_time = time_us_64();
} else {
tud_task();
tud_cdc_n_write_flush(CDC_N_STDIO);
if (!tud_cdc_n_connected(CDC_N_STDIO) ||
(!tud_cdc_n_write_available(CDC_N_STDIO)
&& time_us_64() > last_avail_time + PICO_STDIO_USB_STDOUT_TIMEOUT_US)) {
break;
}
}
}
} else {
// reset our timeout
last_avail_time = 0;
}
if (!tud_cdc_n_connected(CDC_N_STDIO) ||
(!tud_cdc_n_write_available(CDC_N_STDIO) &&
time_us_64() > last_avail_time + PICO_STDIO_USB_STDOUT_TIMEOUT_US)) {
break;
}
}
}
} else {
// reset our timeout
last_avail_time = 0;
}
mutex_exit(&stdio_usb_mutex);
mutex_exit(&stdio_usb_mutex);
}
static int stdio_usb_in_chars(char* buf, int length) {
uint32_t owner;
uint32_t owner;
if (!mutex_try_enter(&stdio_usb_mutex, &owner)) {
if (owner == get_core_num()) return PICO_ERROR_NO_DATA; // would deadlock otherwise
mutex_enter_blocking(&stdio_usb_mutex);
}
if (!mutex_try_enter(&stdio_usb_mutex, &owner)) {
if (owner == get_core_num()) return PICO_ERROR_NO_DATA; // would deadlock otherwise
mutex_enter_blocking(&stdio_usb_mutex);
}
int rc = PICO_ERROR_NO_DATA;
int rc = PICO_ERROR_NO_DATA;
if (tud_cdc_n_connected(CDC_N_STDIO) && tud_cdc_n_available(CDC_N_STDIO)) {
int count = tud_cdc_n_read(CDC_N_STDIO, buf, length);
rc = count ? count : PICO_ERROR_NO_DATA;
}
if (tud_cdc_n_connected(CDC_N_STDIO) && tud_cdc_n_available(CDC_N_STDIO)) {
int count = tud_cdc_n_read(CDC_N_STDIO, buf, length);
mutex_exit(&stdio_usb_mutex);
rc = count ? count : PICO_ERROR_NO_DATA;
}
return rc;
mutex_exit(&stdio_usb_mutex);
return rc;
}
extern stdio_driver_t stdio_usb;
stdio_driver_t stdio_usb = {
.out_chars = stdio_usb_out_chars,
. in_chars = stdio_usb_in_chars ,
// clang-format off
stdio_driver_t stdio_usb = {
.out_chars = stdio_usb_out_chars,
.in_chars = stdio_usb_in_chars,
#if PICO_STDIO_ENABLE_CRLF_SUPPORT
.crlf_enabled = PICO_STDIO_DEFAULT_CRLF
.crlf_enabled = PICO_STDIO_DEFAULT_CRLF
#endif
};
// clang-format on
bool stdio_usb_init(void) {
//#if !PICO_NO_BI_STDIO_USB
bi_decl_if_func_used(bi_program_feature("USB stdin / stdout"));
//#endif
//#if !PICO_NO_BI_STDIO_USB
bi_decl_if_func_used(bi_program_feature("USB stdin / stdout"));
//#endif
mutex_init(&stdio_usb_mutex);
mutex_init(&stdio_usb_mutex);
// unlike with the SDK code, we don't need to add IRQ stuff for the USB
// task, as our main function handles this automatically
// unlike with the SDK code, we don't need to add IRQ stuff for the USB
// task, as our main function handles this automatically
stdio_set_driver_enabled(&stdio_usb, true);
return true;
stdio_set_driver_enabled(&stdio_usb, true);
return true;
}

View File

@ -1,3 +1,4 @@
// vim: set et:
/*
* The MIT License (MIT)
*
@ -23,54 +24,49 @@
*
*/
#include <pico/stdlib.h>
#include <pico/binary_info.h>
#include "tusb.h"
#include <pico/stdlib.h>
#include "pinout.h"
#include "protos.h"
#include "tusb.h"
static uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
static uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
void cdc_uart_init(void) {
gpio_set_function(PINOUT_UART_TX, GPIO_FUNC_UART);
gpio_set_function(PINOUT_UART_RX, GPIO_FUNC_UART);
uart_init(PINOUT_UART_INTERFACE, PINOUT_UART_BAUDRATE);
gpio_set_function(PINOUT_UART_TX, GPIO_FUNC_UART);
gpio_set_function(PINOUT_UART_RX, GPIO_FUNC_UART);
uart_init(PINOUT_UART_INTERFACE, PINOUT_UART_BAUDRATE);
bi_decl(bi_2pins_with_func(PINOUT_UART_TX, PINOUT_UART_RX, GPIO_FUNC_UART));
bi_decl(bi_2pins_with_func(PINOUT_UART_TX, PINOUT_UART_RX, GPIO_FUNC_UART));
}
void cdc_uart_task(void) {
// Consume uart fifo regardless even if not connected
uint rx_len = 0;
while (uart_is_readable(PINOUT_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) {
rx_buf[rx_len++] = uart_getc(PINOUT_UART_INTERFACE);
}
// Consume uart fifo regardless even if not connected
uint rx_len = 0;
while (uart_is_readable(PINOUT_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) {
rx_buf[rx_len++] = uart_getc(PINOUT_UART_INTERFACE);
}
if (tud_cdc_n_connected(CDC_N_UART)) {
// Do we have anything to display on the host's terminal?
if (rx_len) {
for (uint i = 0; i < rx_len; i++) {
tud_cdc_n_write_char(CDC_N_UART, rx_buf[i]);
}
tud_cdc_n_write_flush(CDC_N_UART);
}
if (tud_cdc_n_connected(CDC_N_UART)) {
// Do we have anything to display on the host's terminal?
if (rx_len) {
for (uint i = 0; i < rx_len; i++) { tud_cdc_n_write_char(CDC_N_UART, rx_buf[i]); }
tud_cdc_n_write_flush(CDC_N_UART);
}
if (tud_cdc_n_available(CDC_N_UART)) {
// Is there any data from the host for us to tx
uint tx_len = tud_cdc_n_read(CDC_N_UART, tx_buf, sizeof(tx_buf));
uart_write_blocking(PINOUT_UART_INTERFACE, tx_buf, tx_len);
}
}
if (tud_cdc_n_available(CDC_N_UART)) {
// Is there any data from the host for us to tx
uint tx_len = tud_cdc_n_read(CDC_N_UART, tx_buf, sizeof(tx_buf));
uart_write_blocking(PINOUT_UART_INTERFACE, tx_buf, tx_len);
}
}
}
void cdc_uart_set_hwflow(bool enable) {
uart_set_hw_flow(PINOUT_UART_INTERFACE, enable, enable);
}
void cdc_uart_set_hwflow(bool enable) { uart_set_hw_flow(PINOUT_UART_INTERFACE, enable, enable); }
void cdc_uart_set_baud_rate(uint32_t brate) {
uart_init(PINOUT_UART_INTERFACE, line_coding->bit_rate);
uart_init(PINOUT_UART_INTERFACE, line_coding->bit_rate);
}

View File

@ -1,426 +1,449 @@
// vim: set et:
#include <stdio.h>
#include <pico/stdlib.h>
#include <pico/binary_info.h>
#include <hardware/clocks.h>
#include <hardware/i2c.h>
#include <hardware/resets.h>
#include <hardware/clocks.h>
#include <pico/binary_info.h>
#include <pico/stdlib.h>
#include <pico/timeout_helper.h>
#include "protocfg.h"
#include "pinout.h"
#include "i2ctinyusb.h"
#include "pinout.h"
#include "protocfg.h"
static int delay = 10, delay2 = 5;
// I2C bitbang reimpl because ugh, synopsys
// (mostly inspired by original I2CTinyUSB AVR firmware)
__attribute__((__always_inline__)) inline static void i2cio_set_sda(bool hi) {
if (hi) {
sio_hw->gpio_oe_clr = (1<<PINOUT_I2C_SDA); // SDA is input
// => pullup configured, so it'll go high
} else {
sio_hw->gpio_oe_set = (1<<PINOUT_I2C_SDA); // SDA is output
sio_hw->gpio_clr = (1<<PINOUT_I2C_SDA); // and drive it low
}
if (hi) {
sio_hw->gpio_oe_clr = (1 << PINOUT_I2C_SDA); // SDA is input
// => pullup configured, so it'll go high
} else {
sio_hw->gpio_oe_set = (1 << PINOUT_I2C_SDA); // SDA is output
sio_hw->gpio_clr = (1 << PINOUT_I2C_SDA); // and drive it low
}
}
__attribute__((__always_inline__)) inline static bool i2cio_get_sda(void) {
return (sio_hw->gpio_in & (1<<PINOUT_I2C_SDA)) != 0;
return (sio_hw->gpio_in & (1 << PINOUT_I2C_SDA)) != 0;
}
__attribute__((__always_inline__)) inline static void i2cio_set_scl(bool hi) {
busy_wait_us_32(delay2);
sio_hw->gpio_oe_set = (1<<PINOUT_I2C_SCL); // SCL is output
if (hi)
sio_hw->gpio_set = (1<<PINOUT_I2C_SCL); // SCL is high
else
sio_hw->gpio_clr = (1<<PINOUT_I2C_SCL); // SCL is low
busy_wait_us_32(delay2);
busy_wait_us_32(delay2);
sio_hw->gpio_oe_set = (1 << PINOUT_I2C_SCL); // SCL is output
if (hi)
sio_hw->gpio_set = (1 << PINOUT_I2C_SCL); // SCL is high
else
sio_hw->gpio_clr = (1 << PINOUT_I2C_SCL); // SCL is low
busy_wait_us_32(delay2);
}
__attribute__((__always_inline__)) inline static void i2cio_scl_toggle(void) {
i2cio_set_scl(true );
i2cio_set_scl(false);
i2cio_set_scl(true);
i2cio_set_scl(false);
}
static void __no_inline_not_in_flash_func(i2cio_start)(void) { // start condition
i2cio_set_sda(false);
i2cio_set_scl(false);
static void __no_inline_not_in_flash_func(i2cio_start)(void) { // start condition
i2cio_set_sda(false);
i2cio_set_scl(false);
}
static void __no_inline_not_in_flash_func(i2cio_repstart)(void) { // repstart condition
i2cio_set_sda(true);
i2cio_set_scl(true);
static void __no_inline_not_in_flash_func(i2cio_repstart)(void) { // repstart condition
i2cio_set_sda(true);
i2cio_set_scl(true);
i2cio_set_sda(false);
i2cio_set_scl(false);
i2cio_set_sda(false);
i2cio_set_scl(false);
}
static void __no_inline_not_in_flash_func(i2cio_stop)(void) { // stop condition
i2cio_set_sda(false);
i2cio_set_scl(true );
i2cio_set_sda(true );
static void __no_inline_not_in_flash_func(i2cio_stop)(void) { // stop condition
i2cio_set_sda(false);
i2cio_set_scl(true);
i2cio_set_sda(true);
}
static bool __no_inline_not_in_flash_func(i2cio_write7)(uint8_t v) { // return value: acked? // needed for 10bitaddr xfers
for (int i = 6; i >= 0; --i) {
i2cio_set_sda((v & (1<<i)) != 0);
i2cio_scl_toggle();
}
static bool __no_inline_not_in_flash_func(i2cio_write7)(
uint8_t v) { // return value: acked? // needed for 10bitaddr xfers
for (int i = 6; i >= 0; --i) {
i2cio_set_sda((v & (1 << i)) != 0);
i2cio_scl_toggle();
}
i2cio_set_sda(true);
i2cio_set_scl(true);
i2cio_set_sda(true);
i2cio_set_scl(true);
bool ack = !i2cio_get_sda();
i2cio_set_scl(false);
bool ack = !i2cio_get_sda();
i2cio_set_scl(false);
return ack;
return ack;
}
static bool __no_inline_not_in_flash_func(i2cio_write8)(uint8_t v) { // return value: acked?
for (int i = 7; i >= 0; --i) {
i2cio_set_sda((v & (1<<i)) != 0);
i2cio_scl_toggle();
}
static bool __no_inline_not_in_flash_func(i2cio_write8)(uint8_t v) { // return value: acked?
for (int i = 7; i >= 0; --i) {
i2cio_set_sda((v & (1 << i)) != 0);
i2cio_scl_toggle();
}
i2cio_set_sda(true);
i2cio_set_scl(true);
i2cio_set_sda(true);
i2cio_set_scl(true);
bool ack = !i2cio_get_sda();
i2cio_set_scl(false);
bool ack = !i2cio_get_sda();
i2cio_set_scl(false);
return ack;
return ack;
}
static uint8_t __no_inline_not_in_flash_func(i2cio_read8)(bool last) {
i2cio_set_sda(true );
i2cio_set_scl(false);
i2cio_set_sda(true);
i2cio_set_scl(false);
uint8_t rv = 0;
for (int i = 7; i >= 0; --i) {
i2cio_set_scl(true);
bool c = i2cio_get_sda();
rv <<= 1;
if (c) rv |= 1;
i2cio_set_scl(false);
}
uint8_t rv = 0;
for (int i = 7; i >= 0; --i) {
i2cio_set_scl(true);
bool c = i2cio_get_sda();
rv <<= 1;
if (c) rv |= 1;
i2cio_set_scl(false);
}
if (last) i2cio_set_sda(true);
else i2cio_set_sda(false);
if (last)
i2cio_set_sda(true);
else
i2cio_set_sda(false);
i2cio_scl_toggle();
i2cio_set_sda(true);
i2cio_scl_toggle();
i2cio_set_sda(true);
return rv;
return rv;
}
// replicating/rewriting some SDK functions because they don't do what I want
// so I'm making better ones
static int __no_inline_not_in_flash_func(i2cex_probe_address)(uint16_t addr, bool a10bit) {
// I2C pins to SIO
gpio_set_function(PINOUT_I2C_SCL, GPIO_FUNC_SIO);
gpio_set_function(PINOUT_I2C_SDA, GPIO_FUNC_SIO);
// I2C pins to SIO
gpio_set_function(PINOUT_I2C_SCL, GPIO_FUNC_SIO);
gpio_set_function(PINOUT_I2C_SDA, GPIO_FUNC_SIO);
int rv;
i2cio_start();
int rv;
i2cio_start();
if (a10bit) {
// A10 magic higher 2 addr bits r/#w bit
uint8_t addr1 = 0x70 | (((addr >> 8) & 3) << 1) | 0,
addr2 = addr & 0xff;
if (a10bit) {
// A10 magic higher 2 addr bits r/#w bit
uint8_t addr1 = 0x70 | (((addr >> 8) & 3) << 1) | 0, addr2 = addr & 0xff;
if (i2cio_write7(addr1)) {
if (i2cio_write8(addr2)) rv = 0;
else rv = PICO_ERROR_GENERIC;
} else rv = PICO_ERROR_GENERIC;
} else {
if (i2cio_write8((addr << 1) & 0xff)) rv = 0; // acked: ok
else rv = PICO_ERROR_GENERIC; // nak :/
}
i2cio_stop();
if (i2cio_write7(addr1)) {
if (i2cio_write8(addr2))
rv = 0;
else
rv = PICO_ERROR_GENERIC;
} else
rv = PICO_ERROR_GENERIC;
} else {
if (i2cio_write8((addr << 1) & 0xff))
rv = 0; // acked: ok
else
rv = PICO_ERROR_GENERIC; // nak :/
}
i2cio_stop();
// I2C back to I2C
gpio_set_function(PINOUT_I2C_SCL, GPIO_FUNC_I2C);
gpio_set_function(PINOUT_I2C_SDA, GPIO_FUNC_I2C);
// I2C back to I2C
gpio_set_function(PINOUT_I2C_SCL, GPIO_FUNC_I2C);
gpio_set_function(PINOUT_I2C_SDA, GPIO_FUNC_I2C);
return rv;
return rv;
}
inline static void i2cex_abort_xfer(i2c_inst_t* i2c) {
#if 1
// may be bugged??? so doesnt do anything for now
(void)i2c;
return;
// may be bugged??? so doesnt do anything for now
(void)i2c;
return;
#else
// now do the abort
i2c->hw->enable = 1 /*| (1<<2)*/ | (1<<1);
// wait for M_TX_ABRT irq
do {
/*if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}*/
tight_loop_contents();
} while (/*!timeout &&*/ !(i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_TX_ABRT_BITS));
// reset irq
//if (!timeout)
(void)i2c->hw->clr_tx_abrt;
// now do the abort
i2c->hw->enable = 1 /*| (1<<2)*/ | (1 << 1);
// wait for M_TX_ABRT irq
do {
/*if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}*/
tight_loop_contents();
} while (/*!timeout &&*/ !(i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_TX_ABRT_BITS));
// reset irq
// if (!timeout)
(void)i2c->hw->clr_tx_abrt;
#endif
}
static int i2cex_write_blocking_until(i2c_inst_t* i2c, uint16_t addr, bool a10bit,
const uint8_t* src, size_t len, bool nostop, absolute_time_t until) {
timeout_state_t ts_;
struct timeout_state* ts = &ts_;
check_timeout_fn timeout_check = init_single_timeout_until(&ts_, until);
const uint8_t* src, size_t len, bool nostop, absolute_time_t until) {
timeout_state_t ts_;
if ((int)len < 0) return PICO_ERROR_GENERIC;
if (a10bit) { // addr too high
if (addr & ~(uint16_t)((1<<10)-1)) return PICO_ERROR_GENERIC;
} else if (addr & 0x80)
return PICO_ERROR_GENERIC;
struct timeout_state* ts = &ts_;
if (len == 0) return i2cex_probe_address(addr, a10bit);
check_timeout_fn timeout_check = init_single_timeout_until(&ts_, until);
bool abort = false, timeout = false;
uint32_t abort_reason = 0;
int byte_ctr;
if ((int)len < 0) return PICO_ERROR_GENERIC;
if (a10bit) { // addr too high
if (addr & ~(uint16_t)((1 << 10) - 1)) return PICO_ERROR_GENERIC;
} else if (addr & 0x80)
return PICO_ERROR_GENERIC;
i2c->hw->enable = 0;
// enable 10bit mode if requested
hw_write_masked(&i2c->hw->con, I2C_IC_CON_IC_10BITADDR_MASTER_BITS, (a10bit
? I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_10BITS
: I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_7BITS ) << I2C_IC_CON_IC_10BITADDR_MASTER_LSB);
i2c->hw->tar = addr;
i2c->hw->enable = 1;
if (len == 0) return i2cex_probe_address(addr, a10bit);
for (byte_ctr = 0; byte_ctr < (int)len; ++byte_ctr) {
bool first = byte_ctr == 0,
last = byte_ctr == (int)len - 1;
bool abort = false, timeout = false;
uint32_t abort_reason = 0;
int byte_ctr;
i2c->hw->data_cmd =
bool_to_bit(first && i2c->restart_on_next) << I2C_IC_DATA_CMD_RESTART_LSB |
bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB |
*src++;
i2c->hw->enable = 0;
// enable 10bit mode if requested
// clang-format off
hw_write_masked(&i2c->hw->con, I2C_IC_CON_IC_10BITADDR_MASTER_BITS,
(a10bit ? I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_10BITS
: I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_7BITS)
<< I2C_IC_CON_IC_10BITADDR_MASTER_LSB);
// clang-format on
i2c->hw->tar = addr;
i2c->hw->enable = 1;
do {
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
tight_loop_contents();
} while (!timeout && !(i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_TX_EMPTY_BITS));
for (byte_ctr = 0; byte_ctr < (int)len; ++byte_ctr) {
bool first = byte_ctr == 0, last = byte_ctr == (int)len - 1;
if (!timeout) {
abort_reason = i2c->hw->tx_abrt_source;
if (abort_reason) {
(void)i2c->hw->clr_tx_abrt;
abort = true;
}
i2c->hw->data_cmd = (bool_to_bit(first && i2c->restart_on_next) << I2C_IC_DATA_CMD_RESTART_LSB)
| (bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB)
| *src++;
if (abort || (last && !nostop)) {
do {
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
tight_loop_contents();
} while (!timeout && !(i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_STOP_DET_BITS));
do {
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
tight_loop_contents();
} while (!timeout && !(i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_TX_EMPTY_BITS));
if (!timeout) (void)i2c->hw->clr_stop_det;
else
// if we had a timeout, send an abort request to the hardware,
// so that the bus gets released
i2cex_abort_xfer(i2c);
}
} else i2cex_abort_xfer(i2c);
if (!timeout) {
abort_reason = i2c->hw->tx_abrt_source;
if (abort_reason) {
(void)i2c->hw->clr_tx_abrt;
abort = true;
}
if (abort) break;
}
if (abort || (last && !nostop)) {
do {
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
tight_loop_contents();
// clang-format off
} while (!timeout && !(i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_STOP_DET_BITS));
// clang-format on
int rval;
if (!timeout)
(void)i2c->hw->clr_stop_det;
else
// if we had a timeout, send an abort request to the hardware,
// so that the bus gets released
i2cex_abort_xfer(i2c);
}
} else
i2cex_abort_xfer(i2c);
if (abort) {
const int addr_noack = I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS
| I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_BITS
| I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_BITS;
if (abort) break;
}
if (timeout) rval = PICO_ERROR_TIMEOUT;
else if (!abort_reason || (abort_reason & addr_noack))
rval = PICO_ERROR_GENERIC;
else if (abort_reason & I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_BITS)
rval = byte_ctr;
else rval = PICO_ERROR_GENERIC;
} else rval = byte_ctr;
int rval;
i2c->restart_on_next = nostop;
return rval;
if (abort) {
// clang-format off
const int addr_noack = I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS
| I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_BITS
| I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_BITS;
// clang-format on
if (timeout)
rval = PICO_ERROR_TIMEOUT;
else if (!abort_reason || (abort_reason & addr_noack))
rval = PICO_ERROR_GENERIC;
else if (abort_reason & I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_BITS)
rval = byte_ctr;
else
rval = PICO_ERROR_GENERIC;
} else
rval = byte_ctr;
i2c->restart_on_next = nostop;
return rval;
}
static int i2cex_read_blocking_until(i2c_inst_t* i2c, uint16_t addr, bool a10bit,
uint8_t* dst, size_t len, bool nostop, absolute_time_t until) {
timeout_state_t ts_;
struct timeout_state* ts = &ts_;
check_timeout_fn timeout_check = init_single_timeout_until(&ts_, until);
static int i2cex_read_blocking_until(i2c_inst_t* i2c, uint16_t addr, bool a10bit, uint8_t* dst,
size_t len, bool nostop, absolute_time_t until) {
timeout_state_t ts_;
struct timeout_state* ts = &ts_;
check_timeout_fn timeout_check = init_single_timeout_until(&ts_, until);
if ((int)len < 0) return PICO_ERROR_GENERIC;
if (a10bit) { // addr too high
if (addr & ~(uint16_t)((1<<10)-1)) return PICO_ERROR_GENERIC;
} else if (addr & 0x80)
return PICO_ERROR_GENERIC;
if ((int)len < 0) return PICO_ERROR_GENERIC;
if (a10bit) { // addr too high
if (addr & ~(uint16_t)((1 << 10) - 1)) return PICO_ERROR_GENERIC;
} else if (addr & 0x80)
return PICO_ERROR_GENERIC;
i2c->hw->enable = 0;
// enable 10bit mode if requested
hw_write_masked(&i2c->hw->con, I2C_IC_CON_IC_10BITADDR_MASTER_BITS, (a10bit
? I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_10BITS
: I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_7BITS ) << I2C_IC_CON_IC_10BITADDR_MASTER_LSB);
i2c->hw->tar = addr;
i2c->hw->enable = 1;
i2c->hw->enable = 0;
// enable 10bit mode if requested
hw_write_masked(&i2c->hw->con, I2C_IC_CON_IC_10BITADDR_MASTER_BITS,
(a10bit ? I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_10BITS
: I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_7BITS)
<< I2C_IC_CON_IC_10BITADDR_MASTER_LSB);
i2c->hw->tar = addr;
i2c->hw->enable = 1;
if (len == 0) return i2cex_probe_address(addr, a10bit);
if (len == 0) return i2cex_probe_address(addr, a10bit);
bool abort = false, timeout = false;
uint32_t abort_reason = 0;
int byte_ctr;
bool abort = false, timeout = false;
uint32_t abort_reason = 0;
int byte_ctr;
for (byte_ctr = 0; byte_ctr < (int)len; ++byte_ctr) {
bool first = byte_ctr == 0;
bool last = byte_ctr == (int)len - 1;
for (byte_ctr = 0; byte_ctr < (int)len; ++byte_ctr) {
bool first = byte_ctr == 0;
bool last = byte_ctr == (int)len - 1;
while (!i2c_get_write_available(i2c) && !abort) {
tight_loop_contents();
// ?
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
}
while (!i2c_get_write_available(i2c) && !abort) {
tight_loop_contents();
// ?
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
}
if (timeout) {
// if we had a timeout, send an abort request to the hardware,
// so that the bus gets released
i2cex_abort_xfer(i2c);
}
if (abort) break;
if (timeout) {
// if we had a timeout, send an abort request to the hardware,
// so that the bus gets released
i2cex_abort_xfer(i2c);
}
if (abort) break;
i2c->hw->data_cmd =
bool_to_bit(first && i2c->restart_on_next) << I2C_IC_DATA_CMD_RESTART_LSB |
bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB |
I2C_IC_DATA_CMD_CMD_BITS; // -> 1 for read
i2c->hw->data_cmd = bool_to_bit(first && i2c->restart_on_next)
<< I2C_IC_DATA_CMD_RESTART_LSB |
bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB |
I2C_IC_DATA_CMD_CMD_BITS; // -> 1 for read
do {
abort_reason = i2c->hw->tx_abrt_source;
abort = (bool)i2c->hw->clr_tx_abrt;
do {
abort_reason = i2c->hw->tx_abrt_source;
abort = (bool)i2c->hw->clr_tx_abrt;
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
tight_loop_contents(); // ?
} while (!abort && !i2c_get_read_available(i2c));
if (timeout_check) {
timeout = timeout_check(ts);
abort |= timeout;
}
tight_loop_contents(); // ?
} while (!abort && !i2c_get_read_available(i2c));
if (timeout) {
// if we had a timeout, send an abort request to the hardware,
// so that the bus gets released
i2cex_abort_xfer(i2c);
}
if (abort) break;
if (timeout) {
// if we had a timeout, send an abort request to the hardware,
// so that the bus gets released
i2cex_abort_xfer(i2c);
}
if (abort) break;
uint8_t v = (uint8_t)i2c->hw->data_cmd;
//printf("\ngot read %02x\n", v);
*dst++ = v;
}
uint8_t v = (uint8_t)i2c->hw->data_cmd;
// printf("\ngot read %02x\n", v);
*dst++ = v;
}
int rval;
int rval;
if (abort) {
//printf("\ngot abrt: ");
const int addr_noack = I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS
| I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_BITS
| I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_BITS;
if (abort) {
// printf("\ngot abrt: ");
const int addr_noack = I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS |
I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_BITS |
I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_BITS;
if (timeout) { /*printf("timeout\n");*/ rval = PICO_ERROR_TIMEOUT; }
else if (!abort_reason || (abort_reason & addr_noack)) {//printf("disconn\n");
rval = PICO_ERROR_GENERIC; }
else {/*printf("unk\n");*/ rval = PICO_ERROR_GENERIC;}
} else rval = byte_ctr;
if (timeout) { /*printf("timeout\n");*/
rval = PICO_ERROR_TIMEOUT;
} else if (!abort_reason || (abort_reason & addr_noack)) { // printf("disconn\n");
rval = PICO_ERROR_GENERIC;
} else { /*printf("unk\n");*/
rval = PICO_ERROR_GENERIC;
}
} else
rval = byte_ctr;
i2c->restart_on_next = nostop;
return rval;
i2c->restart_on_next = nostop;
return rval;
}
static inline int i2cex_write_timeout_us(i2c_inst_t* i2c, uint16_t addr, bool a10bit,
const uint8_t* src, size_t len, bool nostop, uint32_t timeout_us) {
absolute_time_t t = make_timeout_time_us(timeout_us);
return i2cex_write_blocking_until(i2c, addr, a10bit, src, len, nostop, t);
const uint8_t* src, size_t len, bool nostop, uint32_t timeout_us) {
absolute_time_t t = make_timeout_time_us(timeout_us);
return i2cex_write_blocking_until(i2c, addr, a10bit, src, len, nostop, t);
}
static inline int i2cex_read_timeout_us(i2c_inst_t* i2c, uint16_t addr, bool a10bit,
uint8_t* dst, size_t len, bool nostop, uint32_t timeout_us) {
absolute_time_t t = make_timeout_time_us(timeout_us);
return i2cex_read_blocking_until(i2c, addr, a10bit, dst, len, nostop, t);
static inline int i2cex_read_timeout_us(i2c_inst_t* i2c, uint16_t addr, bool a10bit, uint8_t* dst,
size_t len, bool nostop, uint32_t timeout_us) {
absolute_time_t t = make_timeout_time_us(timeout_us);
return i2cex_read_blocking_until(i2c, addr, a10bit, dst, len, nostop, t);
}
__attribute__((__const__))
enum ki2c_funcs i2ctu_get_func(void) {
// TODO: SMBUS_EMUL_ALL => I2C_M_RECV_LEN
// TODO: maybe also PROTOCOL_MANGLING, NOSTART
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
__attribute__((__const__)) enum ki2c_funcs i2ctu_get_func(void) {
// TODO: SMBUS_EMUL_ALL => I2C_M_RECV_LEN
// TODO: maybe also PROTOCOL_MANGLING, NOSTART
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
}
void i2ctu_init(void) {
// default to 100 kHz (SDK example default so should be ok)
delay = 10; delay2 = 5;
i2c_init(PINOUT_I2C_DEV, 100*1000);
// default to 100 kHz (SDK example default so should be ok)
delay = 10;
delay2 = 5;
i2c_init(PINOUT_I2C_DEV, 100 * 1000);
gpio_set_function(PINOUT_I2C_SCL, GPIO_FUNC_I2C);
gpio_set_function(PINOUT_I2C_SDA, GPIO_FUNC_I2C);
gpio_pull_up(PINOUT_I2C_SCL);
gpio_pull_up(PINOUT_I2C_SDA);
gpio_set_function(PINOUT_I2C_SCL, GPIO_FUNC_I2C);
gpio_set_function(PINOUT_I2C_SDA, GPIO_FUNC_I2C);
gpio_pull_up(PINOUT_I2C_SCL);
gpio_pull_up(PINOUT_I2C_SDA);
bi_decl(bi_2pins_with_func(PINOUT_I2C_SCL, PINOUT_I2C_SDA, GPIO_FUNC_I2C));
bi_decl(bi_2pins_with_func(PINOUT_I2C_SCL, PINOUT_I2C_SDA, GPIO_FUNC_I2C));
}
uint32_t i2ctu_set_freq(uint32_t freq, uint32_t us) {
delay = us;
delay2 = us >> 1;
if (!delay2) delay2 = 1;
delay = us;
delay2 = us >> 1;
if (!delay2) delay2 = 1;
return i2c_set_baudrate(PINOUT_I2C_DEV, freq);
return i2c_set_baudrate(PINOUT_I2C_DEV, freq);
}
enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, const uint8_t* buf, size_t len) {
bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END);
//printf("nostop=%c ", nostop?'t':'f');
bool bit10 = flags & I2C_M_TEN;
enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr,
const uint8_t* buf, size_t len) {
bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END);
bool bit10 = flags & I2C_M_TEN;
/*if (len == 0) {
// do a read, that's less hazardous
uint8_t stuff = 0;
int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, &stuff, 1,
nostop, 1000*1000);
if (rv < 0) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
} else*/ {
int rv = i2cex_write_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len,
nostop, 1000*1000);
if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
}
/*if (len == 0) {
// do a read, that's less hazardous
uint8_t stuff = 0;
int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, &stuff, 1,
nostop, 1000*1000);
if (rv < 0) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
} else*/
{
int rv = i2cex_write_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len, nostop, 1000 * 1000);
if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
}
}
enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, uint8_t* buf, size_t len) {
bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END);
//printf("nostop=%c ", nostop?'t':'f');
bool bit10 = flags & I2C_M_TEN;
enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr,
uint8_t* buf, size_t len) {
bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END);
bool bit10 = flags & I2C_M_TEN;
/*if (len == 0) {
uint8_t stuff = 0;
int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, &stuff, 1,
nostop, 1000*1000);
if (rv < 0) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
} else*/ {
int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len,
nostop, 1000*1000);
//printf("p le rv=%d buf=%02x ", rv, buf[0]);
if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
}
/*if (len == 0) {
uint8_t stuff = 0;
int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, &stuff, 1,
nostop, 1000*1000);
if (rv < 0) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
} else*/
{
int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len, nostop, 1000 * 1000);
// printf("p le rv=%d buf=%02x ", rv, buf[0]);
if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK;
}
}

View File

@ -1,25 +1,26 @@
// vim: set et:
#ifndef PINOUT_H_
#define PINOUT_H_
// UART config
#define PINOUT_UART_TX 4
#define PINOUT_UART_RX 5
#define PINOUT_UART_CTS 10
#define PINOUT_UART_RTS 11
#define PINOUT_UART_TX 4
#define PINOUT_UART_RX 5
#define PINOUT_UART_CTS 10
#define PINOUT_UART_RTS 11
#define PINOUT_UART_INTERFACE uart1
#define PINOUT_UART_BAUDRATE 115200
#define PINOUT_UART_BAUDRATE 115200
// JTAG config
#define PINOUT_JTAG_TCK 2 // == SWCLK
#define PINOUT_JTAG_TMS 3 // == SWDIO
#define PINOUT_JTAG_TCK 2 // == SWCLK
#define PINOUT_JTAG_TMS 3 // == SWDIO
#define PINOUT_JTAG_TDI 6
#define PINOUT_JTAG_TDO 7
#define PINOUT_JTAG_nTRST 8
#define PINOUT_JTAG_nRESET 9
// SPI config
#define PINOUT_SPI_DEV spi1
#define PINOUT_SPI_DEV spi1
#define PINOUT_SPI_SCLK 14
#define PINOUT_SPI_MOSI 15
#define PINOUT_SPI_MISO 12

View File

@ -1,3 +1,4 @@
// vim: set et:
#ifndef PROTOCFG_H_
#define PROTOCFG_H_
@ -9,21 +10,21 @@
#define DBOARD_HAS_TEMPSENSOR
enum {
HID_N_CMSISDAP = 0,
HID_N_CMSISDAP = 0,
HID_N__NITF
HID_N__NITF
};
enum {
CDC_N_UART = 0,
CDC_N_SERPROG,
CDC_N_UART = 0,
CDC_N_SERPROG,
#ifdef USE_USBCDC_FOR_STDIO
CDC_N_STDIO,
CDC_N_STDIO,
#endif
CDC_N__NITF
CDC_N__NITF
};
enum {
VND_N__NITF = 0
VND_N__NITF = 0
};
#define CFG_TUD_HID 1
@ -35,7 +36,7 @@ enum {
#define CFG_TUD_VENDOR 0
/*#define USB_VID 0x2e8a*/ /* Raspberry Pi */
#define USB_VID 0xcafe /* TinyUSB */
#define USB_VID 0xcafe /* TinyUSB */
/*#define USB_VID 0x1209*/ /* Generic */
/*#define USB_VID 0x1d50*/ /* OpenMoko */
#define USB_PID 0x1312

View File

@ -1,74 +1,72 @@
// vim: set et:
#include <stdio.h>
#include <pico/stdlib.h>
#include <pico/binary_info.h>
#include <hardware/spi.h>
#include <pico/binary_info.h>
#include <pico/stdlib.h>
#include "pinout.h"
#include "protos.h"
#include "serprog.h"
static bool cs_asserted;
void sp_spi_init(void) {
//printf("spi init!\n");
cs_asserted = false;
cs_asserted = false;
spi_init(PINOUT_SPI_DEV, 512 * 1000); // default to 512 kHz
spi_init(PINOUT_SPI_DEV, 512*1000); // default to 512 kHz
gpio_set_function(PINOUT_SPI_MISO, GPIO_FUNC_SPI);
gpio_set_function(PINOUT_SPI_MOSI, GPIO_FUNC_SPI);
gpio_set_function(PINOUT_SPI_SCLK, GPIO_FUNC_SPI);
gpio_set_function(PINOUT_SPI_MISO, GPIO_FUNC_SPI);
gpio_set_function(PINOUT_SPI_MOSI, GPIO_FUNC_SPI);
gpio_set_function(PINOUT_SPI_SCLK, GPIO_FUNC_SPI);
// gpio_set_function(PINOUT_SPI_nCS, GPIO_FUNC_SIO);
gpio_init(PINOUT_SPI_nCS);
gpio_put(PINOUT_SPI_nCS, 1);
gpio_set_dir(PINOUT_SPI_nCS, GPIO_OUT);
//gpio_set_function(PINOUT_SPI_nCS, GPIO_FUNC_SIO);
gpio_init(PINOUT_SPI_nCS);
gpio_put(PINOUT_SPI_nCS, 1);
gpio_set_dir(PINOUT_SPI_nCS, GPIO_OUT);
bi_decl(bi_3pins_with_func(PINOUT_SPI_MISO, PINOUT_SPI_MOSI, PINOUT_SPI_SCLK, GPIO_FUNC_SPI));
bi_decl(bi_1pin_with_name(PINOUT_SPI_nCS, "SPI #CS"));
bi_decl(bi_3pins_with_func(PINOUT_SPI_MISO, PINOUT_SPI_MOSI, PINOUT_SPI_SCLK, GPIO_FUNC_SPI));
bi_decl(bi_1pin_with_name(PINOUT_SPI_nCS, "SPI #CS"));
}
uint32_t __not_in_flash_func(sp_spi_set_freq)(uint32_t freq_wanted) {
return spi_set_baudrate(PINOUT_SPI_DEV, freq_wanted);
return spi_set_baudrate(PINOUT_SPI_DEV, freq_wanted);
}
void __not_in_flash_func(sp_spi_cs_deselect)(void) {
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 1);
asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = false;
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 1);
asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = false;
}
void __not_in_flash_func(sp_spi_cs_select)(void) {
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = true;
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = true;
}
void __not_in_flash_func(sp_spi_op_begin)(void) {
//sp_spi_cs_select();
if (!cs_asserted) {
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed
}
// sp_spi_cs_select();
if (!cs_asserted) {
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed
}
}
void __not_in_flash_func(sp_spi_op_end)(void) {
//sp_spi_cs_deselect();
if (!cs_asserted) { // YES, this condition is the intended one!
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 1);
asm volatile("nop\nnop\nnop"); // idk if this is needed
}
// sp_spi_cs_deselect();
if (!cs_asserted) { // YES, this condition is the intended one!
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 1);
asm volatile("nop\nnop\nnop"); // idk if this is needed
}
}
// TODO: use dma?
void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const uint8_t* write_data) {
spi_write_blocking(PINOUT_SPI_DEV, write_data, write_len);
spi_write_blocking(PINOUT_SPI_DEV, write_data, write_len);
}
void __not_in_flash_func(sp_spi_op_read)(uint32_t read_len, uint8_t* read_data) {
spi_read_blocking(PINOUT_SPI_DEV, 0, read_data, read_len);
spi_read_blocking(PINOUT_SPI_DEV, 0, read_data, read_len);
}

View File

@ -1,8 +1,9 @@
#include <hardware/adc.h>
// vim: set et:
#include "tempsensor.h"
#include <hardware/adc.h>
#define T_SLOPE (-0.001721f)
#define T_BIAS (0.706f)
#define V_MAX (3.3f)
@ -10,38 +11,41 @@
#define T_OFF (27)
// convert float to x.4 fixed format
#define float2fix(x) (int)((x)*(1<<4))
#define float2fix(x) (int)((x) * (1 << 4))
// convert x.4 fixed to 8.4 fixed
__attribute__((__const__))
inline static int16_t trunc_8fix4(int fix) {
if (fix > 4095) fix = 4095;
if (fix < -4096) fix = -4096;
return fix;
__attribute__((__const__)) inline static int16_t trunc_8fix4(int fix) {
// clang-format off
if (fix > 4095) fix = 4095;
if (fix < -4096) fix = -4096;
// clang-format on
return fix;
}
void tempsense_dev_init(void) {
adc_init();
adc_set_temp_sensor_enabled(true);
adc_init();
adc_set_temp_sensor_enabled(true);
}
// 8.4
int16_t tempsense_dev_get_temp(void) {
adc_select_input(4); // select temp sensor
uint16_t result = adc_read();
adc_select_input(4); // select temp sensor
uint16_t result = adc_read();
float voltage = result * (V_MAX / D_RANGE);
float voltage = result * (V_MAX / D_RANGE);
float tempf = T_OFF + (voltage - T_BIAS) / T_SLOPE;
float tempf = T_OFF + (voltage - T_BIAS) / T_SLOPE;
// FIXME: use fixed point instead! but something's wrong with the formula below
/*int temperature = float2fix(T_OFF - T_BIAS / T_SLOPE)
+ (int)result * float2fix(V_MAX / (D_RANGE * T_SLOPE));*/
// FIXME: use fixed point instead! but something's wrong with the formula below
/*int temperature = float2fix(T_OFF - T_BIAS / T_SLOPE)
+ (int)result * float2fix(V_MAX / (D_RANGE * T_SLOPE));*/
return trunc_8fix4(/*temperature*/float2fix(tempf));
return trunc_8fix4(/*temperature*/ float2fix(tempf));
}
// RP2040 absolute min/max are -20/85
// clang-format off
int16_t tempsense_dev_get_lower(void) { return trunc_8fix4(float2fix(-15)); }
int16_t tempsense_dev_get_upper(void) { return trunc_8fix4(float2fix( 75)); }
int16_t tempsense_dev_get_crit (void) { return trunc_8fix4(float2fix( 80)); }
// clang-format on

View File

@ -1,41 +1,46 @@
// vim: set et:
#include <stdint.h>
#include <pico/stdlib.h>
#include <pico/unique_id.h>
#include "tusb.h"
#include "tusb.h"
#include "util.h"
uint8_t get_unique_id_u8(uint8_t *desc_str) {
pico_unique_board_id_t uid;
uint8_t chr_count = 0;
uint8_t get_unique_id_u8(uint8_t* desc_str) {
pico_unique_board_id_t uid;
pico_get_unique_board_id(&uid);
uint8_t chr_count = 0;
for (size_t byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
uint8_t tmp = uid.id[byte];
for (int digit = 0; digit < 2; digit++) {
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
tmp >>= 4;
}
}
pico_get_unique_board_id(&uid);
return chr_count;
for (size_t byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
uint8_t tmp = uid.id[byte];
for (int digit = 0; digit < 2; digit++) {
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
tmp >>= 4;
}
}
return chr_count;
}
uint8_t get_unique_id_u16(uint16_t *desc_str) {
pico_unique_board_id_t uid;
uint8_t chr_count = 0;
uint8_t get_unique_id_u16(uint16_t* desc_str) {
pico_unique_board_id_t uid;
pico_get_unique_board_id(&uid);
uint8_t chr_count = 0;
for (size_t byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
uint8_t tmp = uid.id[byte];
for (int digit = 0; digit < 2; digit++) {
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
tmp >>= 4;
}
}
pico_get_unique_board_id(&uid);
return chr_count;
for (size_t byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
uint8_t tmp = uid.id[byte];
for (int digit = 0; digit < 2; digit++) {
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
tmp >>= 4;
}
}
return chr_count;
}

View File

@ -1,3 +1,4 @@
// vim: set et:
/* derived from libco v20, by byuu (ISC) */

View File

@ -1,17 +1,16 @@
// vim: set et:
#include <stdio.h>
#include "tusb.h"
#include "protocfg.h"
#include "tusb.h"
#ifdef DBOARD_HAS_SERPROG
#include "protos.h"
#include "util.h"
#include "rtconf.h"
#include "serprog.h"
#include "util.h"
// TODO: refactor some of this stuff into another header & split off serprog
// protocol handling from the SPI stuff. one thing we should think about
@ -22,21 +21,23 @@
// kinda refactored this already but it still has a good note for non-SPI stuff,
// so leaving it here for now
// clang-format off
static const uint8_t serprog_cmdmap[32] = {
0x3f, // cmd 00..05 not 0x06 (Q_CHIPSIZE) and 0x07 (Q_OPBUF), as this is a SPI-only device
0x01, // only cmd 08
0x1f, // cmd 10..15 supported
0, // 18..1f
0, // 20..27
0, // 28..2f
0, // 30..37
0, // 38..3f
0, // 40..47
0, // 48..4f
(1<<3), // 50..57: enable 0x53
0, // 58..5f
0, // rest is 0
0x3f, // cmd 00..05 not 0x06 (Q_CHIPSIZE) and 0x07 (Q_OPBUF), as this is a SPI-only device
0x01, // only cmd 08
0x1f, // cmd 10..15 supported
0, // 18..1f
0, // 20..27
0, // 28..2f
0, // 30..37
0, // 38..3f
0, // 4<0..47
0, // 48..4f
(1 << 3), // 50..57: enable 0x53
0, // 58..5f
0, // rest is 0
};
// clang-format on
static const char serprog_pgmname[16] = INFO_PRODUCT_BARE;
static uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
@ -45,195 +46,197 @@ static uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
static uint32_t rxavail, rxpos;
void cdc_serprog_init(void) {
rxavail = 0;
rxpos = 0;
rxavail = 0;
rxpos = 0;
sp_spi_init();
sp_spi_init();
}
static uint8_t read_byte(void) {
while (rxavail <= 0) {
if (!tud_cdc_n_connected(CDC_N_SERPROG) || !tud_cdc_n_available(CDC_N_SERPROG)) {
thread_yield();
continue;
}
while (rxavail <= 0) {
if (!tud_cdc_n_connected(CDC_N_SERPROG) || !tud_cdc_n_available(CDC_N_SERPROG)) {
thread_yield();
continue;
}
rxpos = 0;
rxavail = tud_cdc_n_read(CDC_N_SERPROG, rx_buf, sizeof rx_buf);
rxpos = 0;
rxavail = tud_cdc_n_read(CDC_N_SERPROG, rx_buf, sizeof rx_buf);
if (rxavail == 0) thread_yield();
}
if (rxavail == 0) thread_yield();
}
uint8_t rv = rx_buf[rxpos];
++rxpos;
--rxavail;
return rv;
uint8_t rv = rx_buf[rxpos];
++rxpos;
--rxavail;
return rv;
}
static void handle_cmd(void) {
uint32_t nresp = 0;
uint32_t nresp = 0;
uint8_t cmd = read_byte();
switch (cmd) {
case S_CMD_NOP:
tx_buf[0] = S_ACK;
nresp = 1;
break;
case S_CMD_SYNCNOP:
tx_buf[0] = S_NAK;
tx_buf[1] = S_ACK;
nresp = 2;
break;
case S_CMD_Q_IFACE:
tx_buf[0] = S_ACK;
tx_buf[1] = SERPROG_IFACE_VERSION & 0xff;
tx_buf[2] = (SERPROG_IFACE_VERSION >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_Q_CMDMAP:
tx_buf[0] = S_ACK;
memcpy(&tx_buf[1], serprog_cmdmap, sizeof serprog_cmdmap);
nresp = sizeof(serprog_cmdmap) + 1;
break;
case S_CMD_Q_PGMNAME:
tx_buf[0] = S_ACK;
memcpy(&tx_buf[1], serprog_pgmname, sizeof serprog_pgmname);
nresp = sizeof(serprog_pgmname) + 1;
break;
case S_CMD_Q_SERBUF:
tx_buf[0] = S_ACK;
tx_buf[1] = sizeof(rx_buf) & 0xff;
tx_buf[2] = (sizeof(rx_buf) >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_Q_BUSTYPE:
tx_buf[0] = S_ACK;
tx_buf[1] = 1<<3; // SPI only
nresp = 2;
break;
case S_CMD_Q_WRNMAXLEN:
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(tx_buf)-1) & 0xff;
tx_buf[2] = ((sizeof(tx_buf)-1) >> 8) & 0xff;
tx_buf[3] = ((sizeof(tx_buf)-1) >>16) & 0xff;
nresp = 4;
break;
case S_CMD_Q_RDNMAXLEN:
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(rx_buf)-1) & 0xff;
tx_buf[2] = ((sizeof(rx_buf)-1) >> 8) & 0xff;
tx_buf[3] = ((sizeof(rx_buf)-1) >>16) & 0xff;
nresp = 4;
break;
case S_CMD_S_BUSTYPE:
if (read_byte()/* bus type to set */ == (1<<3)) {
tx_buf[0] = S_ACK;
} else {
tx_buf[0] = S_NAK;
}
nresp = 1;
break;
uint8_t cmd = read_byte();
switch (cmd) {
case S_CMD_NOP:
tx_buf[0] = S_ACK;
nresp = 1;
break;
case S_CMD_SYNCNOP:
tx_buf[0] = S_NAK;
tx_buf[1] = S_ACK;
nresp = 2;
break;
case S_CMD_Q_IFACE:
tx_buf[0] = S_ACK;
tx_buf[1] = SERPROG_IFACE_VERSION & 0xff;
tx_buf[2] = (SERPROG_IFACE_VERSION >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_Q_CMDMAP:
tx_buf[0] = S_ACK;
memcpy(&tx_buf[1], serprog_cmdmap, sizeof serprog_cmdmap);
nresp = sizeof(serprog_cmdmap) + 1;
break;
case S_CMD_Q_PGMNAME:
tx_buf[0] = S_ACK;
memcpy(&tx_buf[1], serprog_pgmname, sizeof serprog_pgmname);
nresp = sizeof(serprog_pgmname) + 1;
break;
case S_CMD_Q_SERBUF:
tx_buf[0] = S_ACK;
tx_buf[1] = sizeof(rx_buf) & 0xff;
tx_buf[2] = (sizeof(rx_buf) >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_Q_BUSTYPE:
tx_buf[0] = S_ACK;
tx_buf[1] = 1 << 3; // SPI only
nresp = 2;
break;
case S_CMD_Q_WRNMAXLEN:
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(tx_buf) - 1) & 0xff;
tx_buf[2] = ((sizeof(tx_buf) - 1) >> 8) & 0xff;
tx_buf[3] = ((sizeof(tx_buf) - 1) >> 16) & 0xff;
nresp = 4;
break;
case S_CMD_Q_RDNMAXLEN:
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(rx_buf) - 1) & 0xff;
tx_buf[2] = ((sizeof(rx_buf) - 1) >> 8) & 0xff;
tx_buf[3] = ((sizeof(rx_buf) - 1) >> 16) & 0xff;
nresp = 4;
break;
case S_CMD_S_BUSTYPE:
if (read_byte() /* bus type to set */ == (1 << 3)) {
tx_buf[0] = S_ACK;
} else {
tx_buf[0] = S_NAK;
}
nresp = 1;
break;
case S_CMD_SPIOP: {
uint32_t slen, rlen;
slen = (uint32_t)read_byte();
slen |= (uint32_t)read_byte() << 8;
slen |= (uint32_t)read_byte() << 16;
rlen = (uint32_t)read_byte();
rlen |= (uint32_t)read_byte() << 8;
rlen |= (uint32_t)read_byte() << 16;
case S_CMD_SPIOP: {
uint32_t slen, rlen;
sp_spi_op_begin();
size_t this_batch;
// clang-format off
slen = (uint32_t)read_byte();
slen |= (uint32_t)read_byte() << 8;
slen |= (uint32_t)read_byte() << 16;
rlen = (uint32_t)read_byte();
rlen |= (uint32_t)read_byte() << 8;
rlen |= (uint32_t)read_byte() << 16;
// clang-format on
// 1. write slen data bytes
// we're going to use the tx buf for all operations here
while (slen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > slen) this_batch = slen;
sp_spi_op_begin();
size_t this_batch;
for (size_t i = 0; i < this_batch; ++i) tx_buf[i] = read_byte();
sp_spi_op_write(this_batch, tx_buf);
// 1. write slen data bytes
// we're going to use the tx buf for all operations here
while (slen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > slen) this_batch = slen;
slen -= this_batch;
}
for (size_t i = 0; i < this_batch; ++i) tx_buf[i] = read_byte();
sp_spi_op_write(this_batch, tx_buf);
// 2. write data
// first, do a batch of 63, because we also need to send an ACK byte
this_batch = sizeof(tx_buf)-1;
if (this_batch > rlen) this_batch = rlen;
sp_spi_op_read(this_batch, &tx_buf[1]);
tx_buf[0] = S_ACK;
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch+1);
rlen -= this_batch;
slen -= this_batch;
}
// now do in batches of 64
while (rlen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > rlen) this_batch = rlen;
// 2. write data
// first, do a batch of 63, because we also need to send an ACK byte
this_batch = sizeof(tx_buf) - 1;
if (this_batch > rlen) this_batch = rlen;
sp_spi_op_read(this_batch, &tx_buf[1]);
tx_buf[0] = S_ACK;
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch + 1);
rlen -= this_batch;
sp_spi_op_read(this_batch, tx_buf);
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch);
// now do in batches of 64
while (rlen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > rlen) this_batch = rlen;
rlen -= this_batch;
}
tud_cdc_n_write_flush(CDC_N_SERPROG);
sp_spi_op_read(this_batch, tx_buf);
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch);
// that's it!
sp_spi_op_end();
nresp = 0; // we sent our own response manually
}
break;
case S_CMD_S_SPI_FREQ: {
uint32_t freq;
freq = (uint32_t)read_byte();
freq |= (uint32_t)read_byte() << 8;
freq |= (uint32_t)read_byte() << 16;
freq |= (uint32_t)read_byte() << 24;
rlen -= this_batch;
}
tud_cdc_n_write_flush(CDC_N_SERPROG);
uint32_t nfreq = sp_spi_set_freq(freq);
tx_buf[0] = S_ACK;
tx_buf[1] = nfreq & 0xff;
tx_buf[2] = (nfreq >> 8) & 0xff;
tx_buf[3] = (nfreq >> 16) & 0xff;
tx_buf[4] = (nfreq >> 24) & 0xff;
nresp = 5;
}
break;
case S_CMD_S_PINSTATE: {
if (read_byte() == 0) sp_spi_cs_deselect();
else sp_spi_cs_select();
// that's it!
sp_spi_op_end();
nresp = 0; // we sent our own response manually
} break;
case S_CMD_S_SPI_FREQ: {
uint32_t freq;
// clang-format off
freq = (uint32_t)read_byte();
freq |= (uint32_t)read_byte() << 8;
freq |= (uint32_t)read_byte() << 16;
freq |= (uint32_t)read_byte() << 24;
// clang-format on
tx_buf[0] = S_ACK;
nresp = 1;
}
break;
uint32_t nfreq = sp_spi_set_freq(freq);
case S_CMD_MAGIC_SETTINGS: {
uint8_t a = read_byte();
uint8_t b = read_byte();
tx_buf[0] = S_ACK;
tx_buf[1] = nfreq & 0xff;
tx_buf[2] = (nfreq >> 8) & 0xff;
tx_buf[3] = (nfreq >> 16) & 0xff;
tx_buf[4] = (nfreq >> 24) & 0xff;
nresp = 5;
} break;
case S_CMD_S_PINSTATE: {
if (read_byte() == 0)
sp_spi_cs_deselect();
else
sp_spi_cs_select();
tx_buf[0] = S_ACK;
tx_buf[1] = rtconf_do(a, b);
nresp = 2;
}
break;
tx_buf[0] = S_ACK;
nresp = 1;
} break;
default:
tx_buf[0] = S_NAK;
nresp = 1;
break;
}
case S_CMD_MAGIC_SETTINGS: {
uint8_t a = read_byte();
uint8_t b = read_byte();
if (nresp > 0) {
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, nresp);
tud_cdc_n_write_flush(CDC_N_SERPROG);
}
tx_buf[0] = S_ACK;
tx_buf[1] = rtconf_do(a, b);
nresp = 2;
} break;
default:
tx_buf[0] = S_NAK;
nresp = 1;
break;
}
if (nresp > 0) {
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, nresp);
tud_cdc_n_write_flush(CDC_N_SERPROG);
}
}
void cdc_serprog_task(void) {
handle_cmd();
}
void cdc_serprog_task(void) { handle_cmd(); }
#endif /* DBOARD_HAS_SERPROG */

View File

@ -1,106 +1,101 @@
// vim: set et:
#ifndef I2CTINYUSB_H_
#define I2CTINYUSB_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "protocfg.h"
enum itu_command {
ITU_CMD_ECHO = 0,
ITU_CMD_GET_FUNC = 1,
ITU_CMD_SET_DELAY = 2,
ITU_CMD_GET_STATUS = 3,
ITU_CMD_ECHO = 0,
ITU_CMD_GET_FUNC = 1,
ITU_CMD_SET_DELAY = 2,
ITU_CMD_GET_STATUS = 3,
ITU_CMD_I2C_IO_BEGIN_F = (1<<0),
ITU_CMD_I2C_IO_END_F = (1<<1),
ITU_CMD_I2C_IO_DIR_MASK = ITU_CMD_I2C_IO_BEGIN_F | ITU_CMD_I2C_IO_END_F,
ITU_CMD_I2C_IO_BEGIN_F = (1 << 0),
ITU_CMD_I2C_IO_END_F = (1 << 1),
ITU_CMD_I2C_IO_DIR_MASK = ITU_CMD_I2C_IO_BEGIN_F | ITU_CMD_I2C_IO_END_F,
ITU_CMD_I2C_IO = 4,
ITU_CMD_I2C_IO_BEGIN = 4 | ITU_CMD_I2C_IO_BEGIN_F,
ITU_CMD_I2C_IO_END = 4 | ITU_CMD_I2C_IO_END_F ,
ITU_CMD_I2C_IO_BEGINEND = 4 | ITU_CMD_I2C_IO_BEGIN_F | ITU_CMD_I2C_IO_END_F,
ITU_CMD_I2C_IO = 4,
ITU_CMD_I2C_IO_BEGIN = 4 | ITU_CMD_I2C_IO_BEGIN_F,
ITU_CMD_I2C_IO_END = 4 | ITU_CMD_I2C_IO_END_F,
ITU_CMD_I2C_IO_BEGINEND = 4 | ITU_CMD_I2C_IO_BEGIN_F | ITU_CMD_I2C_IO_END_F,
};
enum itu_status {
ITU_STATUS_IDLE = 0,
ITU_STATUS_ADDR_ACK = 1,
ITU_STATUS_ADDR_NAK = 2
};
enum itu_status { ITU_STATUS_IDLE = 0, ITU_STATUS_ADDR_ACK = 1, ITU_STATUS_ADDR_NAK = 2 };
// these two are lifted straight from the linux kernel, lmao
enum ki2c_flags {
I2C_M_RD = 0x0001, /* guaranteed to be 0x0001! */
I2C_M_TEN = 0x0010, /* use only if I2C_FUNC_10BIT_ADDR */
I2C_M_DMA_SAFE = 0x0200, /* use only in kernel space */
I2C_M_RECV_LEN = 0x0400, /* use only if I2C_FUNC_SMBUS_READ_BLOCK_DATA */
I2C_M_NO_RD_ACK = 0x0800, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
I2C_M_IGNORE_NAK = 0x1000, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
I2C_M_REV_DIR_ADDR = 0x2000, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
I2C_M_NOSTART = 0x4000, /* use only if I2C_FUNC_NOSTART */
I2C_M_STOP = 0x8000, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
I2C_M_RD = 0x0001, /* guaranteed to be 0x0001! */
I2C_M_TEN = 0x0010, /* use only if I2C_FUNC_10BIT_ADDR */
I2C_M_DMA_SAFE = 0x0200, /* use only in kernel space */
I2C_M_RECV_LEN = 0x0400, /* use only if I2C_FUNC_SMBUS_READ_BLOCK_DATA */
I2C_M_NO_RD_ACK = 0x0800, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
I2C_M_IGNORE_NAK = 0x1000, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
I2C_M_REV_DIR_ADDR = 0x2000, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
I2C_M_NOSTART = 0x4000, /* use only if I2C_FUNC_NOSTART */
I2C_M_STOP = 0x8000, /* use only if I2C_FUNC_PROTOCOL_MANGLING */
};
enum ki2c_funcs {
I2C_FUNC_I2C = 0x00000001,
I2C_FUNC_10BIT_ADDR = 0x00000002, /* required for I2C_M_TEN */
I2C_FUNC_PROTOCOL_MANGLING = 0x00000004, /* required for I2C_M_IGNORE_NAK etc. */
I2C_FUNC_SMBUS_PEC = 0x00000008,
I2C_FUNC_NOSTART = 0x00000010, /* required for I2C_M_NOSTART */
I2C_FUNC_SLAVE = 0x00000020,
I2C_FUNC_SMBUS_BLOCK_PROC_CALL = 0x00008000, /* SMBus 2.0 or later */
I2C_FUNC_SMBUS_QUICK = 0x00010000,
I2C_FUNC_SMBUS_READ_BYTE = 0x00020000,
I2C_FUNC_SMBUS_WRITE_BYTE = 0x00040000,
I2C_FUNC_SMBUS_READ_BYTE_DATA = 0x00080000,
I2C_FUNC_SMBUS_WRITE_BYTE_DATA = 0x00100000,
I2C_FUNC_SMBUS_READ_WORD_DATA = 0x00200000,
I2C_FUNC_SMBUS_WRITE_WORD_DATA = 0x00400000,
I2C_FUNC_SMBUS_PROC_CALL = 0x00800000,
I2C_FUNC_SMBUS_READ_BLOCK_DATA = 0x01000000, /* required for I2C_M_RECV_LEN */
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA = 0x02000000,
I2C_FUNC_SMBUS_READ_I2C_BLOCK = 0x04000000, /* I2C-like block xfer */
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK = 0x08000000, /* w/ 1-byte reg. addr. */
I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 = 0x10000000, /* I2C-like block xfer */
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 = 0x20000000, /* w/ 2-byte reg. addr. */
I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC = 0x40000000, /* SMBus 2.0 or later */
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC = 0x80000000, /* SMBus 2.0 or later */
I2C_FUNC_I2C = 0x00000001,
I2C_FUNC_10BIT_ADDR = 0x00000002, /* required for I2C_M_TEN */
I2C_FUNC_PROTOCOL_MANGLING = 0x00000004, /* required for I2C_M_IGNORE_NAK etc. */
I2C_FUNC_SMBUS_PEC = 0x00000008,
I2C_FUNC_NOSTART = 0x00000010, /* required for I2C_M_NOSTART */
I2C_FUNC_SLAVE = 0x00000020,
I2C_FUNC_SMBUS_BLOCK_PROC_CALL = 0x00008000, /* SMBus 2.0 or later */
I2C_FUNC_SMBUS_QUICK = 0x00010000,
I2C_FUNC_SMBUS_READ_BYTE = 0x00020000,
I2C_FUNC_SMBUS_WRITE_BYTE = 0x00040000,
I2C_FUNC_SMBUS_READ_BYTE_DATA = 0x00080000,
I2C_FUNC_SMBUS_WRITE_BYTE_DATA = 0x00100000,
I2C_FUNC_SMBUS_READ_WORD_DATA = 0x00200000,
I2C_FUNC_SMBUS_WRITE_WORD_DATA = 0x00400000,
I2C_FUNC_SMBUS_PROC_CALL = 0x00800000,
I2C_FUNC_SMBUS_READ_BLOCK_DATA = 0x01000000, /* required for I2C_M_RECV_LEN */
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA = 0x02000000,
I2C_FUNC_SMBUS_READ_I2C_BLOCK = 0x04000000, /* I2C-like block xfer */
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK = 0x08000000, /* w/ 1-byte reg. addr. */
I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 = 0x10000000, /* I2C-like block xfer */
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 = 0x20000000, /* w/ 2-byte reg. addr. */
I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC = 0x40000000, /* SMBus 2.0 or later */
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC = 0x80000000, /* SMBus 2.0 or later */
I2C_FUNC_SMBUS_BYTE = (I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE),
I2C_FUNC_SMBUS_BYTE_DATA = (I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA),
I2C_FUNC_SMBUS_WORD_DATA = (I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA),
I2C_FUNC_SMBUS_BLOCK_DATA = (I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA),
I2C_FUNC_SMBUS_I2C_BLOCK = (I2C_FUNC_SMBUS_READ_I2C_BLOCK | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK),
I2C_FUNC_SMBUS_BYTE = (I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE),
I2C_FUNC_SMBUS_BYTE_DATA = (I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA),
I2C_FUNC_SMBUS_WORD_DATA = (I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA),
I2C_FUNC_SMBUS_BLOCK_DATA = (I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA),
I2C_FUNC_SMBUS_I2C_BLOCK = (I2C_FUNC_SMBUS_READ_I2C_BLOCK | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK),
I2C_FUNC_SMBUS_EMUL = (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC),
I2C_FUNC_SMBUS_EMUL = (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK |
I2C_FUNC_SMBUS_PEC),
/* if I2C_M_RECV_LEN is also supported */
I2C_FUNC_SMBUS_EMUL_ALL = (I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
I2C_FUNC_SMBUS_BLOCK_PROC_CALL),
/* if I2C_M_RECV_LEN is also supported */
I2C_FUNC_SMBUS_EMUL_ALL =
(I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL),
};
__attribute__((__packed__))
struct itu_cmd {
uint16_t flags;
uint16_t addr;
uint16_t len;
uint8_t cmd;
__attribute__((__packed__)) struct itu_cmd {
uint16_t flags;
uint16_t addr;
uint16_t len;
uint8_t cmd;
};
#ifdef DBOARD_HAS_I2C
__attribute__((__const__))
enum ki2c_funcs i2ctu_get_func(void);
__attribute__((__const__)) enum ki2c_funcs i2ctu_get_func(void);
void i2ctu_init(void);
uint32_t i2ctu_set_freq(uint32_t freq, uint32_t us); // returns selected frequency, or 0 on error
enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, const uint8_t* buf, size_t len);
enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, uint8_t* buf, size_t len);
uint32_t i2ctu_set_freq(uint32_t freq, uint32_t us); // returns selected frequency, or 0 on error
enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr,
const uint8_t* buf, size_t len);
enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr,
uint8_t* buf, size_t len);
#endif
#endif

View File

@ -1,3 +1,4 @@
// vim: set et:
/*
* The MIT License (MIT)
*
@ -23,10 +24,12 @@
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// include order is sensitive here
// clang-format off
#include "tusb_config.h"
#include "bsp/board.h" /* a tinyusb header */
@ -39,109 +42,93 @@
#include "protocfg.h"
#include "protos.h"
#include "libco.h"
// clang-format on
#ifdef PICO_BOARD
#include <pico/binary_info.h>
/*#include <hardware/i2c.h>
#include "pinout.h"*/
#endif
static cothread_t mainthread;
void thread_yield(void) {
co_switch(mainthread);
}
void thread_yield(void) { co_switch(mainthread); }
#define DEFAULT_STACK_SIZE 1024
#ifdef DBOARD_HAS_UART
static cothread_t uartthread;
static uint8_t uartstack[DEFAULT_STACK_SIZE];
static uint8_t uartstack[DEFAULT_STACK_SIZE];
static void uart_thread_fn(void) {
cdc_uart_init();
thread_yield();
while (1) {
cdc_uart_task();
thread_yield();
}
cdc_uart_init();
thread_yield();
while (1) {
cdc_uart_task();
thread_yield();
}
}
#endif
#ifdef DBOARD_HAS_SERPROG
static cothread_t serprogthread;
static uint8_t serprogstack[DEFAULT_STACK_SIZE];
static uint8_t serprogstack[DEFAULT_STACK_SIZE];
static void serprog_thread_fn(void) {
cdc_serprog_init();
thread_yield();
while (1) {
cdc_serprog_task();
cdc_serprog_init();
thread_yield();
}
while (1) {
cdc_serprog_task();
thread_yield();
}
}
#endif
// FIXME
extern uint32_t co_active_buffer[64];
uint32_t co_active_buffer[64];
extern uint32_t co_active_buffer[64];
uint32_t co_active_buffer[64];
extern cothread_t co_active_handle;
cothread_t co_active_handle;
cothread_t co_active_handle;
int main(void) {
mainthread = co_active();
mainthread = co_active();
// TODO: split this out in a bsp-specific file
// TODO: split this out in a bsp-specific file
#if defined(PICO_BOARD) && !defined(USE_USBCDC_FOR_STDIO)
// use hardcoded values from TinyUSB board.h
bi_decl(bi_2pins_with_func(0, 1, GPIO_FUNC_UART));
/*i2c_init(PINOUT_I2C_DEV, 100*1000);
gpio_set_function(PINOUT_I2C_SCL, GPIO_FUNC_I2C);
gpio_set_function(PINOUT_I2C_SDA, GPIO_FUNC_I2C);
gpio_pull_up(PINOUT_I2C_SCL);
gpio_pull_up(PINOUT_I2C_SDA);
bi_decl(bi_2pins_with_func(PINOUT_I2C_SCL, PINOUT_I2C_SDA, GPIO_FUNC_I2C));*/
// use hardcoded values from TinyUSB board.h
bi_decl(bi_2pins_with_func(0, 1, GPIO_FUNC_UART));
#endif
board_init();
board_init();
#ifdef DBOARD_HAS_UART
uartthread = co_derive(uartstack, sizeof uartstack, uart_thread_fn);
co_switch(uartthread); // will call cdc_uart_init() on correct thread
uartthread = co_derive(uartstack, sizeof uartstack, uart_thread_fn);
co_switch(uartthread); // will call cdc_uart_init() on correct thread
#endif
#ifdef DBOARD_HAS_SERPROG
serprogthread = co_derive(serprogstack, sizeof serprogstack, serprog_thread_fn);
co_switch(serprogthread); // will call cdc_serprog_init() on correct thread
serprogthread = co_derive(serprogstack, sizeof serprogstack, serprog_thread_fn);
co_switch(serprogthread); // will call cdc_serprog_init() on correct thread
#endif
#ifdef DBOARD_HAS_CMSISDAP
DAP_Setup();
DAP_Setup();
#endif
tusb_init();
tusb_init();
#ifdef USE_USBCDC_FOR_STDIO
stdio_usb_init();
stdio_usb_init();
#endif
while (1) {
/*uint8_t val = 0x12;
i2c_write_timeout_us(PINOUT_I2C_DEV, 0x13, &val, 1, false, 1000*1000);*/
tud_task(); // tinyusb device task
while (1) {
tud_task(); // tinyusb device task
#ifdef DBOARD_HAS_UART
co_switch(uartthread);
co_switch(uartthread);
#endif
//i2c_write_timeout_us(PINOUT_I2C_DEV, 0x13, &val, 1, false, 1000*1000);
tud_task(); // tinyusb device task
tud_task(); // tinyusb device task
#ifdef DBOARD_HAS_SERPROG
co_switch(serprogthread);
co_switch(serprogthread);
#endif
}
}
return 0;
return 0;
}
//--------------------------------------------------------------------+
@ -151,32 +138,32 @@ int main(void) {
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id,
hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
// TODO not Implemented
(void) instance;
(void) report_id;
(void) report_type;
(void) buffer;
(void) reqlen;
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type,
uint8_t* buffer, uint16_t reqlen) {
// TODO not Implemented
(void)instance;
(void)report_id;
(void)report_type;
(void)buffer;
(void)reqlen;
return 0;
return 0;
}
void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id,
hid_report_type_t report_type, uint8_t const* RxDataBuffer, uint16_t bufsize) {
static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
uint32_t response_size = TU_MIN(CFG_TUD_HID_EP_BUFSIZE, bufsize);
void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type,
uint8_t const* RxDataBuffer, uint16_t bufsize) {
static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
uint32_t response_size = TU_MIN(CFG_TUD_HID_EP_BUFSIZE, bufsize);
// This doesn't use multiple report and report ID
(void) instance;
(void) report_id;
(void) report_type;
// This doesn't use multiple report and report ID
(void)instance;
(void)report_id;
(void)report_type;
#ifdef DBOARD_HAS_CMSISDAP
DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
#endif
tud_hid_report(0, TxDataBuffer, response_size);
tud_hid_report(0, TxDataBuffer, response_size);
}

View File

@ -1,3 +1,4 @@
// vim: set et:
#ifndef PROTOS_H_
#define PROTOS_H_
@ -6,7 +7,7 @@
#include "protocfg.h"
#define INFO_MANUFACTURER "BLAHAJ CTF"
#define INFO_MANUFACTURER "BLAHAJ CTF"
#define INFO_PRODUCT_BARE "Dragnbus"
#define INFO_PRODUCT(board) "Dragnbus (" board ")"

View File

@ -1,59 +1,58 @@
// vim: set et:
#include "rtconf.h"
#include <stdint.h>
#include <stdio.h>
#include "protos.h"
#include "rtconf.h"
#include "tempsensor.h"
enum {
implmap_val = 0
implmap_val = 0
#ifdef DBOARD_HAS_CMSISDAP
| 1
| 1
#endif
#ifdef DBOARD_HAS_UART
| 2
| 2
#endif
#ifdef DBOARD_HAS_SERPROG
| 4
#endif
// always true
/*#ifdef DBOARD_HAS_SERPROG
| 4
#endif*/
#ifdef DBOARD_HAS_I2C
| 4
| 4
#endif
#ifdef DBOARD_HAS_TEMPSENSOR
| 8
| 8
#endif
#ifdef USE_USBCDC_FOR_STDIO
| 128
| 128
#endif
};
uint8_t rtconf_do(uint8_t a, uint8_t b) {
switch ((enum rtconf_opt)a) {
switch ((enum rtconf_opt)a) {
#ifdef DBOARD_HAS_UART
case opt_uart_hwfc_endis:
cdc_uart_set_hwflow(b != 0);
return 0;
case opt_uart_hwfc_endis: cdc_uart_set_hwflow(b != 0); return 0;
#endif
#ifdef DBOARD_HAS_TEMPSENSOR
case opt_tempsense_enaddr: {
bool act = tempsense_get_active();
uint8_t addr = tempsense_get_addr();
printf("act=%c addr=%02x arg=%02x\n", act?'t':'f', addr, b);
uint8_t rv = tempsense_get_active() ? tempsense_get_addr() : 0xff;
if (b == 0x00) return rv;
else if (b == 0xff) tempsense_set_active(false);
else tempsense_set_addr(b);
return rv;
}
case opt_tempsense_enaddr: {
bool act = tempsense_get_active();
uint8_t addr = tempsense_get_addr();
printf("act=%c addr=%02x arg=%02x\n", act ? 't' : 'f', addr, b);
uint8_t rv = tempsense_get_active() ? tempsense_get_addr() : 0xff;
if (b == 0x00)
return rv;
else if (b == 0xff)
tempsense_set_active(false);
else
tempsense_set_addr(b);
return rv;
}
#endif
case opt_get_implmap:
return implmap_val;
default:
return 0xff;
}
case opt_get_implmap: return implmap_val;
default: return 0xff;
}
}

View File

@ -1,3 +1,4 @@
// vim: set et:
#ifndef RTCONF_H_
#define RTCONF_H_
@ -8,19 +9,19 @@
enum rtconf_opt {
#ifdef DBOARD_HAS_UART
// enable_disable UART flow control
// b: 0 -> disable, nonzero -> enable
// return: 0
opt_uart_hwfc_endis = 1,
// enable_disable UART flow control
// b: 0 -> disable, nonzero -> enable
// return: 0
opt_uart_hwfc_endis = 1,
#endif
#ifdef DBOARD_HAS_TEMPSENSOR
// 0x00: get I2C address or enable/disable status
// 0xff: disable
//other: set I2C address
opt_tempsense_enaddr = 2,
// 0x00: get I2C address or enable/disable status
// 0xff: disable
// other: set I2C address
opt_tempsense_enaddr = 2,
#endif
opt_get_implmap = 0xff
opt_get_implmap = 0xff
};
uint8_t rtconf_do(uint8_t a, uint8_t b);

View File

@ -1,43 +1,42 @@
// vim: set et:
#ifndef SERPROG_H_
#define SERPROG_H_
enum serprog_cmd {
S_CMD_NOP = 0x00,
S_CMD_Q_IFACE = 0x01,
S_CMD_Q_CMDMAP = 0x02,
S_CMD_Q_PGMNAME = 0x03,
S_CMD_Q_SERBUF = 0x04,
S_CMD_Q_BUSTYPE = 0x05,
S_CMD_Q_CHIPSIZE = 0x06,
S_CMD_Q_OPBUF = 0x07,
S_CMD_Q_WRNMAXLEN = 0x08,
S_CMD_R_BYTE = 0x09,
S_CMD_R_NBYTES = 0x0a,
S_CMD_O_INIT = 0x0b,
S_CMD_O_WRITEB = 0x0c,
S_CMD_O_WRITEN = 0x0d,
S_CMD_O_DELAY = 0x0e,
S_CMD_O_EXEC = 0x0f,
S_CMD_SYNCNOP = 0x10,
S_CMD_Q_RDNMAXLEN = 0x11,
S_CMD_S_BUSTYPE = 0x12,
S_CMD_SPIOP = 0x13,
S_CMD_S_SPI_FREQ = 0x14,
S_CMD_S_PINSTATE = 0x15,
S_CMD_NOP = 0x00,
S_CMD_Q_IFACE = 0x01,
S_CMD_Q_CMDMAP = 0x02,
S_CMD_Q_PGMNAME = 0x03,
S_CMD_Q_SERBUF = 0x04,
S_CMD_Q_BUSTYPE = 0x05,
S_CMD_Q_CHIPSIZE = 0x06,
S_CMD_Q_OPBUF = 0x07,
S_CMD_Q_WRNMAXLEN = 0x08,
S_CMD_R_BYTE = 0x09,
S_CMD_R_NBYTES = 0x0a,
S_CMD_O_INIT = 0x0b,
S_CMD_O_WRITEB = 0x0c,
S_CMD_O_WRITEN = 0x0d,
S_CMD_O_DELAY = 0x0e,
S_CMD_O_EXEC = 0x0f,
S_CMD_SYNCNOP = 0x10,
S_CMD_Q_RDNMAXLEN = 0x11,
S_CMD_S_BUSTYPE = 0x12,
S_CMD_SPIOP = 0x13,
S_CMD_S_SPI_FREQ = 0x14,
S_CMD_S_PINSTATE = 0x15,
S_CMD_MAGIC_SETTINGS = 0x53
S_CMD_MAGIC_SETTINGS = 0x53
};
enum serprog_response {
S_ACK = 0x06,
S_NAK = 0x15
};
enum serprog_response { S_ACK = 0x06, S_NAK = 0x15 };
#define SERPROG_IFACE_VERSION 0x0001
uint32_t /*freq_applied*/ sp_spi_set_freq(uint32_t freq_wanted);
void sp_spi_init(void);
uint32_t/*freq_applied*/ sp_spi_set_freq(uint32_t freq_wanted);
void sp_spi_cs_deselect(void);
void sp_spi_cs_select(void);
void sp_spi_op_begin(void);
@ -45,12 +44,12 @@ void sp_spi_op_write(uint32_t write_len, const uint8_t* write_data);
void sp_spi_op_read(uint32_t read_len, uint8_t* read_data);
void sp_spi_op_end(void);
static inline void sp_spi_op_do(uint32_t write_len, const uint8_t* write_data,
uint32_t read_len, uint8_t* read_data) {
sp_spi_op_begin();
sp_spi_op_write(write_len, write_data);
sp_spi_op_write(read_len, read_data);
sp_spi_op_end();
static inline void sp_spi_op_do(
uint32_t write_len, const uint8_t* write_data, uint32_t read_len, uint8_t* read_data) {
sp_spi_op_begin();
sp_spi_op_write(write_len, write_data);
sp_spi_op_write(read_len, read_data);
sp_spi_op_end();
}
#endif

View File

@ -4,64 +4,70 @@
#include <stdint.h>
static inline void tempsense_dev_init(void) { }
static inline void tempsense_dev_init(void) { }
static inline int16_t tempsense_dev_get_temp(void) { return 42 << 4; }
static inline int16_t tempsense_dev_get_lower(void) { return 0 << 4; }
static inline int16_t tempsense_dev_get_lower(void) { return 0 << 4; }
static inline int16_t tempsense_dev_get_upper(void) { return 75 << 4; }
static inline int16_t tempsense_dev_get_crit (void) { return 80 << 4; }
static inline int16_t tempsense_dev_get_crit(void) { return 80 << 4; }
#include "../tempsensor.c"
static int do_pkt(uint8_t cmd, bool read, uint16_t addr, uint16_t len, uint8_t* buf) {
int rv;
int rv;
if (cmd & 1) tempsense_do_start();
if (cmd & 1) tempsense_do_start();
if (read) {
rv = tempsense_do_read(len, buf);
} else {
rv = tempsense_do_write(len, buf);
}
if (read) {
rv = tempsense_do_read(len, buf);
} else {
rv = tempsense_do_write(len, buf);
}
if (cmd & 2) tempsense_do_stop();
if (cmd & 2) tempsense_do_stop();
printf("-> %d: %s\n", rv, (rv < 0 || rv != len) ? "nak" : "ack");
printf("-> %d: %s\n", rv, (rv < 0 || rv != len) ? "nak" : "ack");
return rv;
return rv;
}
static void pbuf(size_t len, const uint8_t* buf) {
printf("--> ");
size_t i;
for (i = 0; i < len; ++i) {
printf("%02x ", buf[i]);
if ((i & 0xf) == 0xf) printf("%c", '\n');
}
if ((i & 0xf) != 0x0) printf("%c", '\n');
printf("--> ");
size_t i;
for (i = 0; i < len; ++i) {
printf("%02x ", buf[i]);
if ((i & 0xf) == 0xf) printf("%c", '\n');
}
if ((i & 0xf) != 0x0) printf("%c", '\n');
}
int main(int argc, char* argv[]) {
tempsense_init();
tempsense_init();
tempsense_set_addr(0x18);
tempsense_set_addr(0x18);
// initial probe
uint8_t pk1[1] = {0}; do_pkt(0x05, false, 0x18, 1, pk1);
uint8_t pk2[2]; do_pkt(0x06, true , 0x18, 2, pk2); pbuf(2, pk2);
// initial probe
uint8_t pk1[1] = {0};
do_pkt(0x05, false, 0x18, 1, pk1);
uint8_t pk2[2];
do_pkt(0x06, true, 0x18, 2, pk2);
pbuf(2, pk2);
uint8_t pk3[1] = {1}; do_pkt(0x05, false, 0x18, 1, pk3);
uint8_t pk4[2]; do_pkt(0x06, true , 0x18, 2, pk4); pbuf(2, pk4);
uint8_t pk3[1] = {1};
do_pkt(0x05, false, 0x18, 1, pk3);
uint8_t pk4[2];
do_pkt(0x06, true, 0x18, 2, pk4);
pbuf(2, pk4);
// sensor data get
// sensor data get
// out 0x05 cmd5
// in 2byte cmd6
// out 0x04 cmd5
// in 2byte cmd6
// out 0x03 cmd5
// in 2byte cmd6
// out 0x02 cmd5
// in 2byte cmd6
// out 0x05 cmd5
// in 2byte cmd6
// out 0x04 cmd5
// in 2byte cmd6
// out 0x03 cmd5
// in 2byte cmd6
// out 0x02 cmd5
// in 2byte cmd6
}

View File

@ -1,223 +1,244 @@
// vim: set et:
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#ifndef VERY_FAKE
#include "protocfg.h"
#define printf(fmt, ...) do{}while(0)
// clang-format off
#define printf(fmt, ...) do { } while (0) \
// clang-format on
#endif
#ifdef DBOARD_HAS_TEMPSENSOR
#include "tempsensor.h"
static bool active;
static bool active;
static uint8_t addr;
static uint8_t reg;
static size_t index;
static bool instartstop, hasreg;
static size_t index;
static bool instartstop, hasreg;
enum regid {
cap = 0,
config,
t_upper,
t_lower,
t_crit,
t_a,
manuf_id,
dev_idrev,
reso
};
enum regid { cap = 0, config, t_upper, t_lower, t_crit, t_a, manuf_id, dev_idrev, reso };
#define MANUF_ID 0x0054
#define DEV_IDREV 0x0400
struct {
uint16_t config;
uint16_t t_upper, t_lower, t_crit;
uint8_t reso;
uint16_t config;
uint16_t t_upper, t_lower, t_crit;
uint8_t reso;
} mcp9808;
#define float2fix(x) (int)((x)*(1<<4))
__attribute__((__const__))
inline static int16_t trunc_8fix4(int fix) {
if (fix > 4095) fix = 4095;
if (fix < -4096) fix = -4096;
return fix;
#define float2fix(x) (int)((x) * (1 << 4))
__attribute__((__const__)) inline static int16_t trunc_8fix4(int fix) {
// clang-format off
if (fix > 4095) fix = 4095;
if (fix < -4096) fix = -4096;
// clang-format on
return fix;
}
void tempsense_init(void) {
active = false;
addr = 0xff;
reg = 0;
index = 0;
instartstop = false;
hasreg = false;
active = false;
addr = 0xff;
reg = 0;
index = 0;
instartstop = false;
hasreg = false;
tempsense_dev_init();
tempsense_dev_init();
mcp9808.t_lower = tempsense_dev_get_lower();
mcp9808.t_upper = tempsense_dev_get_upper();
mcp9808.t_crit = tempsense_dev_get_crit ();
// clang-format off
mcp9808.t_lower = tempsense_dev_get_lower();
mcp9808.t_upper = tempsense_dev_get_upper();
mcp9808.t_crit = tempsense_dev_get_crit ();
// clang-format on
}
bool tempsense_get_active(void) { return active; }
void tempsense_set_active(bool act) { active = act; if (!act) addr = 0xff; }
void tempsense_set_active(bool act) {
active = act;
if (!act) addr = 0xff;
}
uint8_t tempsense_get_addr(void) { return addr; }
void tempsense_set_addr(uint8_t a) {
addr = a;
active = addr >= 0x8 && addr <= 0x77;
printf("set: ad=%02x ac=%c\n", addr, active?'t':'f');
void tempsense_set_addr(uint8_t a) {
addr = a;
active = addr >= 0x8 && addr <= 0x77;
printf("set: ad=%02x ac=%c\n", addr, active ? 't' : 'f');
}
void tempsense_do_start(void) {
printf("ts start\n");
//reg = 0;
index = 0;
instartstop = true;
hasreg = false;
printf("ts start\n");
// reg = 0;
index = 0;
instartstop = true;
hasreg = false;
}
void tempsense_do_stop(void) {
printf("ts stop\n");
instartstop = false;
printf("ts stop\n");
instartstop = false;
}
int tempsense_do_read(int length, uint8_t* buf) {
printf("read l=%d reg=%02x ", length, reg);
printf("read l=%d reg=%02x ", length, reg);
if (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack
//if (!hasreg) return -1; // nak
if (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack
// if (!hasreg) return -1; // nak
int i;
for (i = 0; i < length; ++i, ++index) {
switch (reg) {
// TODO: big or little endian? seems to be big
case cap:
buf[index] = 0;
break;
case config:
if (index == 0) buf[0] = (mcp9808.config >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.config >> 0) & 0xff;
else return index;
break;
case t_upper:
if (index == 0) buf[0] = (mcp9808.t_upper >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_upper >> 0) & 0xff;
else return index;
break;
case t_lower:
if (index == 0) buf[0] = (mcp9808.t_lower >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_lower >> 0) & 0xff;
else return index;
break;
case t_crit:
if (index == 0) buf[0] = (mcp9808.t_crit >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_crit >> 0) & 0xff;
else return index;
break;
case t_a: {
static uint16_t temp;
if (index == 0) {
int16_t res = tempsense_dev_get_temp();
int i;
for (i = 0; i < length; ++i, ++index) {
switch (reg) {
// TODO: big or little endian? seems to be big
case cap: buf[index] = 0; break;
case config:
if (index == 0)
buf[0] = (mcp9808.config >> 8) & 0xff;
else if (index == 1)
buf[1] = (mcp9808.config >> 0) & 0xff;
else
return index;
break;
case t_upper:
if (index == 0)
buf[0] = (mcp9808.t_upper >> 8) & 0xff;
else if (index == 1)
buf[1] = (mcp9808.t_upper >> 0) & 0xff;
else
return index;
break;
case t_lower:
if (index == 0)
buf[0] = (mcp9808.t_lower >> 8) & 0xff;
else if (index == 1)
buf[1] = (mcp9808.t_lower >> 0) & 0xff;
else
return index;
break;
case t_crit:
if (index == 0)
buf[0] = (mcp9808.t_crit >> 8) & 0xff;
else if (index == 1)
buf[1] = (mcp9808.t_crit >> 0) & 0xff;
else
return index;
break;
case t_a: {
static uint16_t temp;
if (index == 0) {
int16_t res = tempsense_dev_get_temp();
uint32_t tup = mcp9808.t_upper & 0x1ffc;
if (tup & 0x1000) tup |= 0xffffe000; // make negative
uint32_t tlo = mcp9808.t_lower & 0x1ffc;
if (tlo & 0x1000) tlo |= 0xffffe000; // make negative
uint32_t tcr = mcp9808.t_crit & 0x1ffc;
if (tcr & 0x1000) tcr |= 0xffffe000; // make negative
// clang-format off
uint32_t tup = mcp9808.t_upper & 0x1ffc;
if (tup & 0x1000) tup |= 0xffffe000; // make negative
uint32_t tlo = mcp9808.t_lower & 0x1ffc;
if (tlo & 0x1000) tlo |= 0xffffe000; // make negative
uint32_t tcr = mcp9808.t_crit & 0x1ffc;
if (tcr & 0x1000) tcr |= 0xffffe000; // make negative
// clang-format on
temp = res & 0x1fff; // data bits and sign bit
temp = res & 0x1fff; // data bits and sign bit
if ((int32_t)tlo > res) temp |= 0x2000;
if ((int32_t)tup < res) temp |= 0x4000;
if ((int32_t)tcr < res) temp |= 0x8000;
if ((int32_t)tlo > res) temp |= 0x2000;
if ((int32_t)tup < res) temp |= 0x4000;
if ((int32_t)tcr < res) temp |= 0x8000;
buf[0] = (temp >> 8) & 0xff;
} else if (index == 1) buf[1] = (temp>>0) & 0xff;
else return index;
}
break;
case manuf_id:
if (index == 0) buf[0] = (MANUF_ID >> 8) & 0xff;
else if (index == 1) buf[1] = (MANUF_ID>>0)&0xff;
else return index;
break;
case dev_idrev:
if (index == 0) buf[0] = (DEV_IDREV >> 8) & 0xff;
else if (index == 1) buf[1] = (DEV_IDREV>>0)&0xff;
else return index;
break;
case reso:
if (index == 0) buf[0] = mcp9808.reso;
else return index;
break;
default: return -1;
}
}
buf[0] = (temp >> 8) & 0xff;
} else if (index == 1)
buf[1] = (temp >> 0) & 0xff;
else
return index;
} break;
case manuf_id:
if (index == 0)
buf[0] = (MANUF_ID >> 8) & 0xff;
else if (index == 1)
buf[1] = (MANUF_ID >> 0) & 0xff;
else
return index;
break;
case dev_idrev:
if (index == 0)
buf[0] = (DEV_IDREV >> 8) & 0xff;
else if (index == 1)
buf[1] = (DEV_IDREV >> 0) & 0xff;
else
return index;
break;
case reso:
if (index == 0)
buf[0] = mcp9808.reso;
else
return index;
break;
default: return -1;
}
}
return i;
return i;
}
int tempsense_do_write(int length, const uint8_t* buf) {
printf("write l=%d reg=%02x iss=%c ", length, reg, instartstop?'t':'f');
printf("write l=%d reg=%02x iss=%c ", length, reg, instartstop ? 't' : 'f');
if (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack
if (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack
if (!hasreg) {
printf("get reg %02x ", reg);
if (!hasreg) {
printf("get reg %02x ", reg);
reg = *buf & 0xf;
++buf;
--length;
hasreg = true;
}
reg = *buf & 0xf;
++buf;
--length;
hasreg = true;
}
if (length == 0) return 1; // ack, probably a read following
if (length == 0) return 1; // ack, probably a read following
int i;
for (i = 0; i < length; ++i, ++index) {
switch (reg) {
case config:
if (index == 0) {
mcp9808.config = (mcp9808.config & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.config = (mcp9808.config & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case t_upper:
if (index == 0) {
mcp9808.t_upper = (mcp9808.t_upper & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_upper = (mcp9808.t_upper & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case t_lower:
if (index == 0) {
mcp9808.t_lower = (mcp9808.t_lower & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_lower = (mcp9808.t_lower & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case t_crit:
if (index == 0) {
mcp9808.t_crit = (mcp9808.t_crit & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_crit = (mcp9808.t_crit & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case reso:
mcp9808.reso = buf[index];
break;
default:
printf("unk reg\n");
return -1;
}
}
int i;
for (i = 0; i < length; ++i, ++index) {
switch (reg) {
case config:
if (index == 0) {
mcp9808.config = (mcp9808.config & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.config = (mcp9808.config & 0xff00) | ((uint16_t)buf[1] << 0);
} else
return index;
break;
case t_upper:
if (index == 0) {
mcp9808.t_upper = (mcp9808.t_upper & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_upper = (mcp9808.t_upper & 0xff00) | ((uint16_t)buf[1] << 0);
} else
return index;
break;
case t_lower:
if (index == 0) {
mcp9808.t_lower = (mcp9808.t_lower & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_lower = (mcp9808.t_lower & 0xff00) | ((uint16_t)buf[1] << 0);
} else
return index;
break;
case t_crit:
if (index == 0) {
mcp9808.t_crit = (mcp9808.t_crit & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_crit = (mcp9808.t_crit & 0xff00) | ((uint16_t)buf[1] << 0);
} else
return index;
break;
case reso: mcp9808.reso = buf[index]; break;
default: printf("unk reg\n"); return -1;
}
}
return i;
return i;
}
#endif

View File

@ -1,30 +1,31 @@
// vim: set et:
#ifndef TEMPSENSOR_H_
#define TEMPSENSOR_H_
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
void tempsense_init(void);
bool tempsense_get_active(void);
void tempsense_set_active(bool active);
bool tempsense_get_active(void);
void tempsense_set_active(bool active);
uint8_t tempsense_get_addr(void);
void tempsense_set_addr(uint8_t addr);
void tempsense_set_addr(uint8_t addr);
void tempsense_do_start(void); // start cond
int tempsense_do_read(int length, uint8_t* buf);
int tempsense_do_write(int length, const uint8_t* buf);
void tempsense_do_stop(void); // stop cond
void tempsense_do_start(void); // start cond
int tempsense_do_read(int length, uint8_t* buf);
int tempsense_do_write(int length, const uint8_t* buf);
void tempsense_do_stop(void); // stop cond
#ifdef DBOARD_HAS_TEMPSENSOR
void tempsense_dev_init(void);
void tempsense_dev_init(void);
// 8.4
int16_t tempsense_dev_get_temp(void);
int16_t tempsense_dev_get_lower(void);
int16_t tempsense_dev_get_upper(void);
int16_t tempsense_dev_get_crit (void);
int16_t tempsense_dev_get_crit(void);
#endif
#endif

View File

@ -1,3 +1,4 @@
// vim: set et:
/*
* The MIT License (MIT)
*
@ -38,39 +39,42 @@ extern "C" {
// defined by board.mk
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#error CFG_TUSB_MCU must be defined
#endif
// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_DEVICE_RHPORT_NUM
#define BOARD_DEVICE_RHPORT_NUM 0
#define BOARD_DEVICE_RHPORT_NUM 0
#endif
// RHPort max operational speed can defined by board.mk
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise
// FullSpeed
#ifndef BOARD_DEVICE_RHPORT_SPEED
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
#else
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#endif
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || \
CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 || \
CFG_TUSB_MCU == OPT_MCU_CXD56) \
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
#else
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#endif
#endif
// Device mode with rhport and speed defined by board.mk
#if BOARD_DEVICE_RHPORT_NUM == 0
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#if BOARD_DEVICE_RHPORT_NUM == 0
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#elif BOARD_DEVICE_RHPORT_NUM == 1
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#else
#error "Incorrect RHPort configuration"
#error "Incorrect RHPort configuration"
#endif
// This example doesn't use an RTOS
#ifdef PICO_BOARD
#define CFG_TUSB_OS OPT_OS_PICO
#define CFG_TUSB_OS OPT_OS_PICO
#else
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
#endif
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
@ -88,7 +92,7 @@ extern "C" {
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4)))
#endif
//--------------------------------------------------------------------
@ -96,23 +100,23 @@ extern "C" {
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
//------------- CLASS -------------//
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_NET 0
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_NET 0
// see also: bsp/<family>/protocfg.h
#define CFG_TUD_HID_EP_BUFSIZE 64
#define CFG_TUD_HID_EP_BUFSIZE 64
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#ifdef __cplusplus
}
}
#endif
#endif /* _TUSB_CONFIG_H_ */

View File

@ -1,3 +1,4 @@
// vim: set et:
/*
* The MIT License (MIT)
*
@ -23,12 +24,13 @@
*
*/
#include "protos.h"
#include "tusb.h"
#include "util.h"
#include "protos.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
/* A combination of interfaces must have a unique product id, since PC will save device driver after
* the first plug. Same VID/PID with different interface e.g MSC (first), then CDC (later) will
* possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
@ -38,71 +40,74 @@
#else
#define USB_BCD_BASE 0x4000
#endif
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
#define USB_BCD (USB_BCD_BASE | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 3) | _PID_MAP(HID, 6) | \
_PID_MAP(MIDI, 9) | _PID_MAP(VENDOR, 12) ) \
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
#define USB_BCD \
(USB_BCD_BASE | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 3) | _PID_MAP(HID, 6) | _PID_MAP(MIDI, 9) | \
_PID_MAP(VENDOR, 12)) \
// String Descriptor Index
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
STRID_CONFIG,
STRID_CONFIG,
STRID_IF_HID_CMSISDAP,
STRID_IF_VND_I2CTINYUSB,
STRID_IF_CDC_UART,
STRID_IF_CDC_SERPROG,
STRID_IF_CDC_STDIO,
STRID_IF_HID_CMSISDAP,
STRID_IF_VND_I2CTINYUSB,
STRID_IF_CDC_UART,
STRID_IF_CDC_SERPROG,
STRID_IF_CDC_STDIO,
};
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
// clang-format off
tusb_desc_device_t const desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0110, // TODO: 0x0200 ?
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0110, // TODO: 0x0200 ?
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = USB_VID,
.idProduct = USB_PID,
.bcdDevice = USB_BCD,
.idVendor = USB_VID,
.idProduct = USB_PID,
.bcdDevice = USB_BCD,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.bNumConfigurations = 0x01
.bNumConfigurations = 0x01
};
// clang-format on
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
uint8_t const * tud_descriptor_device_cb(void) {
return (uint8_t const *) &desc_device;
}
uint8_t const* tud_descriptor_device_cb(void) { return (uint8_t const*)&desc_device; }
//--------------------------------------------------------------------+
// HID Report Descriptor
//--------------------------------------------------------------------+
// clang-format off
static uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE)
TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE)
};
// clang-format on
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) {
(void) instance;
uint8_t const* tud_hid_descriptor_report_cb(uint8_t instance) {
(void)instance;
return desc_hid_report;
return desc_hid_report;
}
//--------------------------------------------------------------------+
@ -111,48 +116,48 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) {
enum {
#ifdef DBOARD_HAS_I2C
ITF_NUM_VND_I2CTINYUSB,
ITF_NUM_VND_I2CTINYUSB,
#endif
#ifdef DBOARD_HAS_CMSISDAP
ITF_NUM_HID_CMSISDAP,
ITF_NUM_HID_CMSISDAP,
#endif
#ifdef DBOARD_HAS_UART
ITF_NUM_CDC_UART_COM,
ITF_NUM_CDC_UART_DATA,
ITF_NUM_CDC_UART_COM,
ITF_NUM_CDC_UART_DATA,
#endif
#ifdef DBOARD_HAS_SERPROG
ITF_NUM_CDC_SERPROG_COM,
ITF_NUM_CDC_SERPROG_DATA,
ITF_NUM_CDC_SERPROG_COM,
ITF_NUM_CDC_SERPROG_DATA,
#endif
#ifdef USE_USBCDC_FOR_STDIO
ITF_NUM_CDC_STDIO_COM,
ITF_NUM_CDC_STDIO_DATA,
ITF_NUM_CDC_STDIO_COM,
ITF_NUM_CDC_STDIO_DATA,
#endif
ITF_NUM_TOTAL
ITF_NUM_TOTAL
};
#define TUD_I2CTINYUSB_LEN (9)
#define TUD_I2CTINYUSB_DESCRIPTOR(_itfnum, _stridx) \
9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, 0, 0, 0, _stridx \
9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, 0, 0, 0, _stridx \
enum {
CONFIG_TOTAL_LEN = TUD_CONFIG_DESC_LEN
CONFIG_TOTAL_LEN = TUD_CONFIG_DESC_LEN
#ifdef DBOARD_HAS_I2C
+ TUD_I2CTINYUSB_LEN
+ TUD_I2CTINYUSB_LEN
#endif
#ifdef DBOARD_HAS_UART
+ TUD_CDC_DESC_LEN
+ TUD_CDC_DESC_LEN
#endif
#ifdef DBOARD_HAS_CMSISDAP
+ TUD_HID_INOUT_DESC_LEN
+ TUD_HID_INOUT_DESC_LEN
#endif
#ifdef DBOARD_HAS_SERPROG
+ TUD_CDC_DESC_LEN
+ TUD_CDC_DESC_LEN
#endif
#ifdef USE_USBCDC_FOR_STDIO
+ TUD_CDC_DESC_LEN
+ TUD_CDC_DESC_LEN
#endif
};
@ -169,36 +174,44 @@ enum {
// NOTE: if you modify this table, don't forget to keep tusb_config.h up to date as well!
// TODO: maybe add some strings to all these interfaces
// clang-format off
uint8_t const desc_configuration[] = {
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, STRID_CONFIG, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, STRID_CONFIG, CONFIG_TOTAL_LEN,
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
#ifdef DBOARD_HAS_CMSISDAP
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID_CMSISDAP, STRID_IF_HID_CMSISDAP, 0/*HID_PROTOCOL_NONE*/, sizeof(desc_hid_report), EPNUM_HID_CMSISDAP, 0x80 | (EPNUM_HID_CMSISDAP+0), CFG_TUD_HID_EP_BUFSIZE, 1),
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID_CMSISDAP, STRID_IF_HID_CMSISDAP,
0 /*HID_PROTOCOL_NONE*/, sizeof(desc_hid_report), EPNUM_HID_CMSISDAP,
0x80 | (EPNUM_HID_CMSISDAP + 0), CFG_TUD_HID_EP_BUFSIZE, 1),
#endif
#ifdef DBOARD_HAS_I2C
TUD_I2CTINYUSB_DESCRIPTOR(ITF_NUM_VND_I2CTINYUSB, STRID_IF_VND_I2CTINYUSB),
TUD_I2CTINYUSB_DESCRIPTOR(ITF_NUM_VND_I2CTINYUSB, STRID_IF_VND_I2CTINYUSB),
#endif
#ifdef DBOARD_HAS_UART
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_UART_COM, STRID_IF_CDC_UART, EPNUM_CDC_UART_NOTIF, 64, EPNUM_CDC_UART_OUT, EPNUM_CDC_UART_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_UART_COM, STRID_IF_CDC_UART, EPNUM_CDC_UART_NOTIF, 64,
EPNUM_CDC_UART_OUT, EPNUM_CDC_UART_IN, 64),
#endif
#ifdef DBOARD_HAS_SERPROG
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SERPROG_COM, STRID_IF_CDC_SERPROG, EPNUM_CDC_SERPROG_NOTIF, 64, EPNUM_CDC_SERPROG_OUT, EPNUM_CDC_SERPROG_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SERPROG_COM, STRID_IF_CDC_SERPROG, EPNUM_CDC_SERPROG_NOTIF,
64, EPNUM_CDC_SERPROG_OUT, EPNUM_CDC_SERPROG_IN, 64),
#endif
#ifdef USE_USBCDC_FOR_STDIO
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_STDIO_COM, STRID_IF_CDC_STDIO, EPNUM_CDC_STDIO_NOTIF, 64, EPNUM_CDC_STDIO_OUT, EPNUM_CDC_STDIO_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_STDIO_COM, STRID_IF_CDC_STDIO, EPNUM_CDC_STDIO_NOTIF, 64,
EPNUM_CDC_STDIO_OUT, EPNUM_CDC_STDIO_IN, 64),
#endif
};
// clang-format on
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
return desc_configuration;
uint8_t const* tud_descriptor_configuration_cb(uint8_t index) {
(void)index; // for multiple configurations
return desc_configuration;
}
//--------------------------------------------------------------------+
@ -206,61 +219,59 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
//--------------------------------------------------------------------+
// array of pointer to string descriptors
char const* string_desc_arr [] = {
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
[STRID_MANUFACTURER] = INFO_MANUFACTURER, // Manufacturer
[STRID_PRODUCT] = INFO_PRODUCT(INFO_BOARDNAME), // Product
// clang-format off
char const* string_desc_arr[] = {
[STRID_LANGID] = (const char[]){0x09, 0x04}, // supported language is English (0x0409)
[STRID_MANUFACTURER] = INFO_MANUFACTURER, // Manufacturer
[STRID_PRODUCT] = INFO_PRODUCT(INFO_BOARDNAME), // Product
[STRID_CONFIG] = "Configuration descriptor",
// max string length check: |||||||||||||||||||||||||||||||
[STRID_IF_HID_CMSISDAP] = "CMSIS-DAP HID interface",
[STRID_IF_VND_I2CTINYUSB] = "I2C-Tiny-USB interface",
[STRID_IF_CDC_UART] = "UART CDC interface",
[STRID_IF_CDC_SERPROG] = "Serprog CDC interface",
[STRID_IF_CDC_STDIO] = "stdio CDC interface (debug)",
[STRID_CONFIG] = "Configuration descriptor",
// max string length check: |||||||||||||||||||||||||||||||
[STRID_IF_HID_CMSISDAP] = "CMSIS-DAP HID interface",
[STRID_IF_VND_I2CTINYUSB] = "I2C-Tiny-USB interface",
[STRID_IF_CDC_UART] = "UART CDC interface",
[STRID_IF_CDC_SERPROG] = "Serprog CDC interface",
[STRID_IF_CDC_STDIO] = "stdio CDC interface (debug)",
};
// clang-format on
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
// Application return pointer to descriptor, whose contents must exist long enough for transfer to
// complete
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
static uint16_t _desc_str[32];
static uint16_t _desc_str[32];
(void) langid;
(void)langid;
uint8_t chr_count = 0;
uint8_t chr_count = 0;
if (STRID_LANGID == index) {
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
} else if (STRID_SERIAL == index) {
chr_count = get_unique_id_u16(_desc_str + 1);
} else {
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if (STRID_LANGID == index) {
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
} else if (STRID_SERIAL == index) {
chr_count = get_unique_id_u16(_desc_str + 1);
} else {
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if (!(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])))
return NULL;
if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) return NULL;
const char* str = string_desc_arr[index];
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = TU_MIN(strlen(str), 31);
// Cap at max char
chr_count = TU_MIN(strlen(str), 31);
// Convert ASCII string into UTF-16
for (int i = 0; i < chr_count; i++) {
_desc_str[1+i] = str[i];
}
}
// Convert ASCII string into UTF-16
for (int i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; }
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8) | (2*chr_count + 2);
// first byte is length (including header), second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * chr_count + 2);
return _desc_str;
return _desc_str;
}
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) {
if (itf == CDC_N_UART) {
cdc_uart_set_baudrate(line_coding->bit_rate);
}
if (itf == CDC_N_UART) { cdc_uart_set_baudrate(line_coding->bit_rate); }
}

View File

@ -1,16 +1,21 @@
// vim: set et:
#ifndef UTIL_H_
#define UTIL_H_
static inline char nyb2hex(int x) {
if (x < 0xa) return '0'+(x-0);
else return 'A'+(x-0xa);
if (x < 0xa)
return '0' + (x - 0x0);
else
return 'A' + (x - 0xa);
}
void thread_yield(void);
// clang-format off
uint8_t get_unique_id_u8 (uint8_t * desc_str);
uint8_t get_unique_id_u16(uint16_t* desc_str);
// clang-format on
#endif

View File

@ -3,6 +3,7 @@
#ifdef DBOARD_HAS_I2C
// clang-format off
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
@ -18,235 +19,247 @@
#include "i2ctinyusb.h"
#include "tempsensor.h"
// clang-format on
static uint8_t itf_num;
static enum itu_status status;
static struct itu_cmd curcmd;
static struct itu_cmd curcmd;
static uint8_t rxbuf[128];
static uint8_t txbuf[128];
static void iub_init(void) {
status = ITU_STATUS_IDLE;
memset(&curcmd, 0, sizeof curcmd);
status = ITU_STATUS_IDLE;
memset(&curcmd, 0, sizeof curcmd);
i2ctu_init();
i2ctu_init();
#ifdef DBOARD_HAS_TEMPSENSOR
tempsense_init();
tempsense_init();
#endif
}
static void iub_reset(uint8_t rhport) {
(void)rhport;
(void)rhport;
status = ITU_STATUS_IDLE;
memset(&curcmd, 0, sizeof curcmd);
status = ITU_STATUS_IDLE;
memset(&curcmd, 0, sizeof curcmd);
i2ctu_init();
i2ctu_init();
#ifdef DBOARD_HAS_TEMPSENSOR
tempsense_init();
tempsense_init();
#endif
itf_num = 0;
itf_num = 0;
}
static uint16_t iub_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc,
uint16_t max_len) {
(void)rhport;
static uint16_t iub_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16_t max_len) {
(void)rhport;
TU_VERIFY(itf_desc->bInterfaceClass == 0
&& itf_desc->bInterfaceSubClass == 0
&& itf_desc->bInterfaceProtocol == 0, 0);
// clang-format off
TU_VERIFY(itf_desc->bInterfaceClass == 0
&& itf_desc->bInterfaceSubClass == 0
&& itf_desc->bInterfaceProtocol == 0,
0);
// clang-format on
const uint16_t drv_len = sizeof(tusb_desc_interface_t);
TU_VERIFY(max_len >= drv_len, 0);
const uint16_t drv_len = sizeof(tusb_desc_interface_t);
TU_VERIFY(max_len >= drv_len, 0);
itf_num = itf_desc->bInterfaceNumber;
itf_num = itf_desc->bInterfaceNumber;
return drv_len;
return drv_len;
}
static bool iub_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const* req) {
(void)rhport;
(void)rhport;
/*static char* stages[]={"SETUP","DATA","ACK"};
static char* types[]={"STD","CLS","VND","INV"};
/*static char* stages[]={"SETUP","DATA","ACK"};
static char* types[]={"STD","CLS","VND","INV"};
printf("ctl req stage=%s rt=%s, wIndex=%04x, bReq=%02x, wValue=%04x wLength=%04x\n",
stages[stage], types[req->bmRequestType_bit.type],
req->wIndex, req->bRequest, req->wValue, req->wLength);*/
printf("ctl req stage=%s rt=%s, wIndex=%04x, bReq=%02x, wValue=%04x wLength=%04x\n",
stages[stage], types[req->bmRequestType_bit.type],
req->wIndex, req->bRequest, req->wValue, req->wLength);*/
if (req->bmRequestType_bit.type != TUSB_REQ_TYPE_VENDOR) return true;
if (req->bmRequestType_bit.type != TUSB_REQ_TYPE_VENDOR) return true;
if (stage == CONTROL_STAGE_DATA) {
struct itu_cmd cmd = curcmd;
if (stage == CONTROL_STAGE_DATA) {
struct itu_cmd cmd = curcmd;
if (req->bRequest >= ITU_CMD_I2C_IO && req->bRequest <= ITU_CMD_I2C_IO_BEGINEND
&& cmd.cmd == req->bRequest && cmd.flags == req->wValue
&& cmd.addr == req->wIndex && cmd.len == req->wLength) {
//printf("WDATA a=%04hx l=%04hx ", cmd.addr, cmd.len);
if (req->bRequest >= ITU_CMD_I2C_IO && req->bRequest <= ITU_CMD_I2C_IO_BEGINEND &&
cmd.cmd == req->bRequest && cmd.flags == req->wValue && cmd.addr == req->wIndex &&
cmd.len == req->wLength) {
// printf("WDATA a=%04hx l=%04hx ", cmd.addr, cmd.len);
//printf("data=%02x %02x...\n", rxbuf[0], rxbuf[1]);
// printf("data=%02x %02x...\n", rxbuf[0], rxbuf[1]);
#ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
// FIXME: fix status handling
int rv = tempsense_do_write(cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len, rxbuf);
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
else status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
// FIXME: fix status handling
int rv = tempsense_do_write(cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len, rxbuf);
if (rv < 0 || rv != cmd.len)
status = ITU_STATUS_ADDR_NAK;
else
status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
} else
#endif
{
status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
cmd.addr, rxbuf, cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len);
}
{
status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd.addr, rxbuf,
cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len);
}
// cancel curcmd
curcmd.cmd = 0xff;
}
return true;
} else if (stage == CONTROL_STAGE_SETUP) {
switch (req->bRequest) {
case ITU_CMD_ECHO: { // flags to be echoed back, addr unused, len=2
if (req->wLength != 2) return false; // bad length -> let's stall
// cancel curcmd
curcmd.cmd = 0xff;
}
return true;
} else if (stage == CONTROL_STAGE_SETUP) {
switch (req->bRequest) {
case ITU_CMD_ECHO: { // flags to be echoed back, addr unused, len=2
uint8_t rv[2];
rv[0] = req->wValue&0xff;
rv[1] = (req->wValue>>8)&0xff;
return tud_control_xfer(rhport, req, rv, sizeof rv);
}
break;
case ITU_CMD_GET_FUNC: { // flags unused, addr unused, len=4
if (req->wLength != 4) return false;
if (req->wLength != 2) return false; // bad length -> let's stall
const uint32_t func = i2ctu_get_func();
txbuf[0]=func&0xff;
txbuf[1]=(func>>8)&0xff;
txbuf[2]=(func>>16)&0xff;
txbuf[3]=(func>>24)&0xff;
return tud_control_xfer(rhport, req, txbuf, 4);
}
break;
case ITU_CMD_SET_DELAY: { // flags=delay, addr unused, len=0
if (req->wLength != 0) return false;
uint8_t rv[2];
rv[0] = req->wValue & 0xff;
rv[1] = (req->wValue >> 8) & 0xff;
return tud_control_xfer(rhport, req, rv, sizeof rv);
} break;
case ITU_CMD_GET_FUNC: { // flags unused, addr unused, len=4
if (req->wLength != 4) return false;
uint32_t us = req->wValue ? req->wValue : 1;
uint32_t freq = 1000*1000 / us;
const uint32_t func = i2ctu_get_func();
txbuf[0] = func & 0xff;
txbuf[1] = (func >> 8) & 0xff;
txbuf[2] = (func >> 16) & 0xff;
txbuf[3] = (func >> 24) & 0xff;
return tud_control_xfer(rhport, req, txbuf, 4);
} break;
case ITU_CMD_SET_DELAY: { // flags=delay, addr unused, len=0
if (req->wLength != 0) return false;
//printf("set freq us=%u freq=%u\n", us, freq);
if (i2ctu_set_freq(freq, us) != 0) // returned an ok frequency
return tud_control_status(rhport, req);
else return false;
}
break;
case ITU_CMD_GET_STATUS: { // flags unused, addr unused, len=1
if (req->wLength != 1) return false;
uint32_t us = req->wValue ? req->wValue : 1;
uint32_t freq = 1000 * 1000 / us;
uint8_t rv = status;
return tud_control_xfer(rhport, req, &rv, 1);
}
break;
// printf("set freq us=%u freq=%u\n", us, freq);
if (i2ctu_set_freq(freq, us) != 0) // returned an ok frequency
return tud_control_status(rhport, req);
else
return false;
} break;
case ITU_CMD_GET_STATUS: { // flags unused, addr unused, len=1
if (req->wLength != 1) return false;
case ITU_CMD_I2C_IO: // flags: ki2c_flags
case ITU_CMD_I2C_IO_BEGIN: // addr: I2C address
case ITU_CMD_I2C_IO_END: // len: transfer size
case ITU_CMD_I2C_IO_BEGINEND: { // (transfer dir is in flags)
struct itu_cmd cmd;
cmd.flags = req->wValue;
cmd.addr = req->wIndex;
cmd.len = req->wLength;
cmd.cmd = req->bRequest;
uint8_t rv = status;
return tud_control_xfer(rhport, req, &rv, 1);
} break;
if (cmd.flags & I2C_M_RD) { // read from I2C device
//printf("read addr=%04hx len=%04hx ", cmd.addr, cmd.len);
case ITU_CMD_I2C_IO: // flags: ki2c_flags
case ITU_CMD_I2C_IO_BEGIN: // addr: I2C address
case ITU_CMD_I2C_IO_END: // len: transfer size
case ITU_CMD_I2C_IO_BEGINEND: { // (transfer dir is in flags)
struct itu_cmd cmd;
cmd.flags = req->wValue;
cmd.addr = req->wIndex;
cmd.len = req->wLength;
cmd.cmd = req->bRequest;
if (cmd.flags & I2C_M_RD) { // read from I2C device
// printf("read addr=%04hx len=%04hx ", cmd.addr, cmd.len);
#ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
int rv = tempsense_do_read(cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len, txbuf);
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
else status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
int rv = tempsense_do_read(
cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len, txbuf);
if (rv < 0 || rv != cmd.len)
status = ITU_STATUS_ADDR_NAK;
else
status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
} else
#endif
{
status = i2ctu_read(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
cmd.addr, txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
}
//printf("data=%02x %02x...\n", txbuf[0], txbuf[1]);
return tud_control_xfer(rhport, req, txbuf,
cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
} else { // write
//printf("write addr=%04hx len=%04hx ", cmd.addr, cmd.len);
if (cmd.len == 0) { // address probe -> do this here
uint8_t bleh = 0;
{
status = i2ctu_read(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd.addr,
txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
}
// printf("data=%02x %02x...\n", txbuf[0], txbuf[1]);
return tud_control_xfer(
rhport, req, txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
} else { // write
// printf("write addr=%04hx len=%04hx ", cmd.addr, cmd.len);
if (cmd.len == 0) { // address probe -> do this here
uint8_t bleh = 0;
#ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
int rv = tempsense_do_write(0, &bleh);
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
else status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
int rv = tempsense_do_write(0, &bleh);
if (rv < 0 || rv != cmd.len)
status = ITU_STATUS_ADDR_NAK;
else
status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
} else
#endif
{
status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
cmd.addr, &bleh, 0);
}
//printf("probe -> %d\n", status);
return tud_control_status(rhport, req);
} else {
// handled in DATA stage!
curcmd = cmd;
bool rv = tud_control_xfer(rhport, req, rxbuf,
cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len);
return rv;
}
}
}
break;
default:
//printf("I2C-Tiny-USB: unknown command %02x\n", req->bRequest);
return false;
}
} else return true; // other stage...
{
status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
cmd.addr, &bleh, 0);
}
// printf("probe -> %d\n", status);
return tud_control_status(rhport, req);
} else {
// handled in DATA stage!
curcmd = cmd;
bool rv = tud_control_xfer(rhport, req, rxbuf,
cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len);
return rv;
}
}
} break;
default:
// printf("I2C-Tiny-USB: unknown command %02x\n", req->bRequest);
return false;
}
} else
return true; // other stage...
}
// never actually called fsr
static bool iub_xfer(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void)rhport;
(void)ep_addr;
(void)result;
(void)xferred_bytes;
static bool iub_xfer(
uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void)rhport;
(void)ep_addr;
(void)result;
(void)xferred_bytes;
return true;
return true;
}
// interfacing stuff for TinyUSB API, actually defines the driver
// clang-format off
static usbd_class_driver_t const i2ctinyusb_driver = {
#if CFG_TUSB_DEBUG >= 2
.name = "i2c-tiny-usb",
.name = "i2c-tiny-usb",
#endif
.init = iub_init,
.reset = iub_reset,
.open = iub_open,
.control_xfer_cb = iub_ctl_req,
.xfer_cb = iub_xfer,
.sof = NULL
.init = iub_init,
.reset = iub_reset,
.open = iub_open,
.control_xfer_cb = iub_ctl_req,
.xfer_cb = iub_xfer,
.sof = NULL
};
// clang-format on
usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) {
*driver_count = 1;
return &i2ctinyusb_driver;
*driver_count = 1;
return &i2ctinyusb_driver;
}
// we need to implement this one, because tinyusb uses hardcoded stuff for
// endpoint 0, which is what the i2c-tiny-usb kernel module uses
bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_control_request_t const* req) {
return iub_ctl_req(rhport, ep_addr, req);
bool tud_vendor_control_xfer_cb(
uint8_t rhport, uint8_t ep_addr, tusb_control_request_t const* req) {
return iub_ctl_req(rhport, ep_addr, req);
}
#endif /* DBOARD_HAS_I2C */