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) * The MIT License (MIT)
* *
@ -45,100 +46,99 @@ This information includes:
*/ */
#include "cmsis_compiler.h" #include "cmsis_compiler.h"
#include "util.h" #include "util.h"
/// Processor Clock of the Cortex-M MCU used in the Debug Unit. /// Processor Clock of the Cortex-M MCU used in the Debug Unit.
/// This value is used to calculate the SWD/JTAG clock speed. /// 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. /// 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 /// 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 /// 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 /// 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. /// 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. /// 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>. /// 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. /// 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>. /// 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. /// 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. /// 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. /// Default communication mode on the Debug Access Port.
/// Used for the command \ref DAP_Connect when Port Default mode is selected. /// 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. /// Default communication speed on the Debug Access Port for SWD and JTAG mode.
/// Used to initialize the default SWD/JTAG clock frequency. /// Used to initialize the default SWD/JTAG clock frequency.
/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. /// 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. /// Maximum Package Size for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the /// 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, /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or
/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. /// 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. #define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes.
/// Maximum Package Buffers for Command and Response data. /// Maximum Package Buffers for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the /// 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 /// 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). /// 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. /// 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>. /// 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. /// 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. /// 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>. /// 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. /// 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. /// 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. /// Indicate that UART Communication Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>. /// 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. /// 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. /// 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. /// 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. /// 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>. /// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#ifdef USE_USBCDC_FOR_STDIO #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 #else
#define DAP_UART_USB_COM_PORT 0 #define DAP_UART_USB_COM_PORT 0
#endif #endif
/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. /// 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. /// Debug Unit is connected to fixed Target Device.
/// The Debug Unit may be part of an evaluation board and always connected to a fixed /// 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 /// 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. /// 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" #include "DAP.h"
@ -146,72 +146,84 @@ This information includes:
\param str Pointer to buffer to store the string. \param str Pointer to buffer to store the string.
\return String length. \return String length.
*/ */
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) { __STATIC_INLINE uint8_t DAP_GetVendorString(char* str) {
static const char vnd[] = INFO_MANUFACTURER; static const char vnd[] = INFO_MANUFACTURER;
for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i]; for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i];
return sizeof(vnd)-1; return sizeof(vnd) - 1;
} }
/** Get Product ID string. /** Get Product ID string.
\param str Pointer to buffer to store the string. \param str Pointer to buffer to store the string.
\return String length. \return String length.
*/ */
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) { __STATIC_INLINE uint8_t DAP_GetProductString(char* str) {
static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME); static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i]; for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i];
return sizeof(prd)-1; return sizeof(prd) - 1;
} }
/** Get Serial Number string. /** Get Serial Number string.
\param str Pointer to buffer to store the string. \param str Pointer to buffer to store the string.
\return String length. \return String length.
*/ */
__STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) { __STATIC_INLINE uint8_t DAP_GetSerNumString(char* str) { return get_unique_id_u8((uint8_t*)str); }
return get_unique_id_u8((uint8_t*)str);
}
/** Get Target Device Vendor string. /** Get Target Device Vendor string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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. /** Get Target Device Name string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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. /** Get Target Board Vendor string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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. /** Get Target Board Name string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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! */ /* TODO! */
/** Get Product Firmware Version string. /** Get Product Firmware Version string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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 \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 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: interface of a device. The following I/O Pins are provided:
JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode 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 TCK: Test Clock | SWCLK: Clock | Output Push/Pull
TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data)
TDI: Test Data Input | | Output Push/Pull 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 nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor
nRESET: Device Reset | nRESET: Device Reset | 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 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 The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins. these I/O Pins.
For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. 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 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 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: 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_ENABLE to enable the output mode from the DAP hardware.
- \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to 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. - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed.
*/ */
// Configure DAP I/O pins ------------------------------ // Configure DAP I/O pins ------------------------------
/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. /** 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. - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level.
- TDO to input mode. - 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. /** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET.
Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: 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. - SWCLK, SWDIO, nRESET to output mode and set to default high level.
- TDI, nTRST to HighZ mode (pins are unused in SWD mode). - 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. /** Disable JTAG/SWD I/O Pins.
Disables the DAP Hardware I/O pins which configures: Disables the DAP Hardware I/O pins which configures:
- TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. - 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 -------------------------------------
/** SWCLK/TCK I/O pin: Get Input. /** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin. \return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) { return 0; }
return 0;
}
/** SWCLK/TCK I/O pin: Set Output to High. /** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level. 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. /** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level. 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 Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input. /** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin. \return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) { return 0; }
return 0;
}
/* PIN_SWDIO_TMS_SET and PIN_SWDIO_TMS_CLR are used by SWJ_Sequence */ /* PIN_SWDIO_TMS_SET and PIN_SWDIO_TMS_CLR are used by SWJ_Sequence */
/** SWDIO/TMS I/O pin: Set Output to High. /** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level. 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. /** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level. 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). /** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin. \return Current status of the SWDIO DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) { return 0; }
return 0;
}
/** SWDIO I/O pin: Set Output (used in SWD mode only). /** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin. \param bit Output value for the SWDIO DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) { (void)bit; }
(void)bit;
}
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only). /** 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 Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls. 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). /** 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 Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls. 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 Pin I/O ---------------------------------------------
/** TDI I/O pin: Get Input. /** TDI I/O pin: Get Input.
\return Current status of the TDI DAP hardware I/O pin. \return Current status of the TDI DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) { return 0; }
return 0;
}
/** TDI I/O pin: Set Output. /** TDI I/O pin: Set Output.
\param bit Output value for the TDI DAP hardware I/O pin. \param bit Output value for the TDI DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) { (void)bit; }
(void)bit;
}
// TDO Pin I/O --------------------------------------------- // TDO Pin I/O ---------------------------------------------
/** TDO I/O pin: Get Input. /** TDO I/O pin: Get Input.
\return Current status of the TDO DAP hardware I/O pin. \return Current status of the TDO DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) { return 0; }
return 0;
}
// nTRST Pin I/O ------------------------------------------- // nTRST Pin I/O -------------------------------------------
/** nTRST I/O pin: Get Input. /** nTRST I/O pin: Get Input.
\return Current status of the nTRST DAP hardware I/O pin. \return Current status of the nTRST DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) { return 0; }
return 0;
}
/** nTRST I/O pin: Set Output. /** nTRST I/O pin: Set Output.
\param bit JTAG TRST Test Reset pin status: \param bit JTAG TRST Test Reset pin status:
- 0: issue a JTAG TRST Test Reset. - 0: issue a JTAG TRST Test Reset.
- 1: release JTAG TRST Test Reset. - 1: release JTAG TRST Test Reset.
*/ */
__STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) { (void)bit; }
(void)bit;
}
// nRESET Pin I/O------------------------------------------ // nRESET Pin I/O------------------------------------------
/** nRESET I/O pin: Get Input. /** nRESET I/O pin: Get Input.
\return Current status of the nRESET DAP hardware I/O pin. \return Current status of the nRESET DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) { return 0; }
return 0;
}
/** nRESET I/O pin: Set Output. /** nRESET I/O pin: Set Output.
\param bit target device hardware reset pin status: \param bit target device hardware reset pin status:
- 0: issue a device hardware reset. - 0: issue a device hardware reset.
- 1: release device hardware reset. - 1: release device hardware reset.
*/ */
__STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) { (void)bit; }
(void)bit;
}
///@} ///@}
//************************************************************************************************** //**************************************************************************************************
/** /**
\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs
\ingroup DAP_ConfigIO_gr \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. - 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. - 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) { (void)bit; }
(void)bit;
}
/** Debug Unit: Set status Target Running LED. /** Debug Unit: Set status Target Running LED.
\param bit status of the Target Running LED. \param bit status of the Target Running LED.
- 1: Target Running LED ON: program execution in target started. - 1: Target Running LED ON: program execution in target started.
- 0: Target Running LED OFF: program execution in target stopped. - 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) { (void)bit; }
(void)bit;
}
///@} ///@}
//************************************************************************************************** //**************************************************************************************************
/** /**
\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp \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. 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 The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET.
default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. By default, the DWT timer is used. The frequency of this timer is configured with \ref
TIMESTAMP_CLOCK.
*/ */
/** Get timestamp of Test Domain Timer. /** Get timestamp of Test Domain Timer.
\return Current timestamp value. \return Current timestamp value.
*/ */
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) { __STATIC_INLINE uint32_t TIMESTAMP_GET(void) {
#if TIMESTAMP_CLOCK > 0 #if TIMESTAMP_CLOCK > 0
return (DWT->CYCCNT); return (DWT->CYCCNT);
#else #else
return 0; return 0;
#endif #endif
} }
///@} ///@}
//************************************************************************************************** //**************************************************************************************************
/** /**
\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization \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). /** 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: Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set:
- I/O clock system enabled. - I/O clock system enabled.
- all I/O pins: input buffer enabled, output pins are set to HighZ mode. - 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. - for nTRST, nRESET a weak pull-up (if available) is enabled.
- LED output pins are enabled and LEDs are turned off. - 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. /** Reset Target Device with custom specific I/O pin or command sequence.
This function allows the optional implementation of a device specific reset 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. when a device needs a time-critical unlock sequence that enables the debug port.
\return 0 = no device specific reset sequence is implemented.\n \return 0 = no device specific reset sequence is implemented.\n
1 = a device specific reset sequence is implemented. 1 = a device specific reset sequence is implemented.
*/ */
__STATIC_INLINE uint8_t RESET_TARGET (void) { __STATIC_INLINE uint8_t RESET_TARGET(void) {
return (0U); // change to '1' when a device reset sequence is implemented return (0U); // change to '1' when a device reset sequence is implemented
} }
///@} ///@}

View File

@ -1,11 +1,10 @@
// vim: set et:
#include "protos.h" #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_hwflow(bool enable) { (void)enable; }
void cdc_uart_set_baud_rate(uint32_t brate) { (void)brate; } void cdc_uart_set_baud_rate(uint32_t brate) { (void)brate; }

View File

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

View File

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

View File

@ -1,3 +1,4 @@
// vim: set et:
#include "protos.h" #include "protos.h"
#include "serprog.h" #include "serprog.h"
@ -5,8 +6,8 @@
void sp_spi_init(void) { } void sp_spi_init(void) { }
uint32_t __not_in_flash_func(sp_spi_set_freq)(uint32_t freq_wanted) { uint32_t __not_in_flash_func(sp_spi_set_freq)(uint32_t freq_wanted) {
(void)freq_wanted; (void)freq_wanted;
return 0; return 0;
} }
void __not_in_flash_func(sp_spi_cs_deselect)(void) { } 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_end)(void) { }
void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const uint8_t* write_data) { void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const uint8_t* write_data) {
(void)write_len; (void)write_len;
(void)write_data; (void)write_data;
} }
void __not_in_flash_func(sp_spi_op_read)(uint32_t read_len, uint8_t* read_data) { void __not_in_flash_func(sp_spi_op_read)(uint32_t read_len, uint8_t* read_data) {
(void)read_len; (void)read_len;
(void)read_data; (void)read_data;
} }

View File

@ -1,11 +1,14 @@
// vim: set et:
#include "tempsensor.h" #include "tempsensor.h"
void tempsense_dev_init(void) { } void tempsense_dev_init(void) { }
// clang-format off
// 8.4 // 8.4
int16_t tempsense_dev_get_temp (void) { return 0 << 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_lower(void) { return trunc_8fix4(float2fix( 0)); }
int16_t tempsense_dev_get_upper(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)); } 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 <stdint.h>
#include "util.h" #include "util.h"

View File

@ -1,3 +1,4 @@
// vim: set et:
/* /*
* The MIT License (MIT) * The MIT License (MIT)
* *
@ -44,21 +45,21 @@ This information includes:
- Optional information about a connected Target Device (for Evaluation Boards). - Optional information about a connected Target Device (for Evaluation Boards).
*/ */
#include "cmsis_compiler.h"
#include "bsp/board.h"
#include <stdint.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/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 <pico/binary_info.h>
#include "bsp/board.h"
#include "cmsis_compiler.h"
#include "pinout.h" #include "pinout.h"
#include "protos.h" #include "protos.h"
#include "util.h" #include "util.h"
@ -69,110 +70,110 @@ This information includes:
#define PINOUT_SWCLK_MASK (1UL << PINOUT_SWCLK) #define PINOUT_SWCLK_MASK (1UL << PINOUT_SWCLK)
#define PINOUT_SWDIO_MASK (1UL << PINOUT_SWDIO) #define PINOUT_SWDIO_MASK (1UL << PINOUT_SWDIO)
#define PINOUT_TCK_MASK (1UL << PINOUT_JTAG_TCK) #define PINOUT_TCK_MASK (1UL << PINOUT_JTAG_TCK)
#define PINOUT_TMS_MASK (1UL << PINOUT_JTAG_TMS) #define PINOUT_TMS_MASK (1UL << PINOUT_JTAG_TMS)
#define PINOUT_TDI_MASK (1UL << PINOUT_JTAG_TDI) #define PINOUT_TDI_MASK (1UL << PINOUT_JTAG_TDI)
#define PINOUT_TDO_MASK (1UL << PINOUT_JTAG_TDO) #define PINOUT_TDO_MASK (1UL << PINOUT_JTAG_TDO)
#define PINOUT_nTRST_MASK (1UL << PINOUT_JTAG_nTRST) #define PINOUT_nTRST_MASK (1UL << PINOUT_JTAG_nTRST)
#define PINOUT_nRESET_MASK (1UL << PINOUT_JTAG_nRESET) #define PINOUT_nRESET_MASK (1UL << PINOUT_JTAG_nRESET)
#define PINOUT_LED_MASK (1UL << PINOUT_LED) #define PINOUT_LED_MASK (1UL << PINOUT_LED)
/// Processor Clock of the Cortex-M MCU used in the Debug Unit. /// Processor Clock of the Cortex-M MCU used in the Debug Unit.
/// This value is used to calculate the SWD/JTAG clock speed. /// 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. /// 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 /// 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 /// 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 /// 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. /// 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. /// 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>. /// 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. /// 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>. /// 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. /// 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. /// 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. /// Default communication mode on the Debug Access Port.
/// Used for the command \ref DAP_Connect when Port Default mode is selected. /// 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. /// Default communication speed on the Debug Access Port for SWD and JTAG mode.
/// Used to initialize the default SWD/JTAG clock frequency. /// Used to initialize the default SWD/JTAG clock frequency.
/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. /// 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. /// Maximum Package Size for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the /// 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, /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or
/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. /// 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. #define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes.
/// Maximum Package Buffers for Command and Response data. /// Maximum Package Buffers for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the /// 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 /// 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). /// 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. /// 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>. /// 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. /// 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. /// 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>. /// 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. /// 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. /// 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. /// Indicate that UART Communication Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>. /// 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. /// 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. /// 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. /// 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. /// 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>. /// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#ifdef USE_USBCDC_FOR_STDIO #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 #else
#define DAP_UART_USB_COM_PORT 0 #define DAP_UART_USB_COM_PORT 0
#endif #endif
/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. /// 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. /// Debug Unit is connected to fixed Target Device.
/// The Debug Unit may be part of an evaluation board and always connected to a fixed /// 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 /// 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. /// 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 #if TARGET_DEVICE_FIXED
#define TARGET_DEVICE_VENDOR "Raspberry Pi" ///< String indicating the Silicon Vendor #define TARGET_DEVICE_VENDOR "Raspberry Pi" ///< String indicating the Silicon Vendor
#define TARGET_DEVICE_NAME "Pico" ///< String indicating the Target Device #define TARGET_DEVICE_NAME "Pico" ///< String indicating the Target Device
#endif #endif
#include "DAP.h" #include "DAP.h"
@ -181,72 +182,84 @@ This information includes:
\param str Pointer to buffer to store the string. \param str Pointer to buffer to store the string.
\return String length. \return String length.
*/ */
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) { __STATIC_INLINE uint8_t DAP_GetVendorString(char* str) {
static const char vnd[] = INFO_MANUFACTURER; static const char vnd[] = INFO_MANUFACTURER;
for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i]; for (size_t i = 0; i < sizeof(vnd); ++i) str[i] = vnd[i];
return sizeof(vnd)-1; return sizeof(vnd) - 1;
} }
/** Get Product ID string. /** Get Product ID string.
\param str Pointer to buffer to store the string. \param str Pointer to buffer to store the string.
\return String length. \return String length.
*/ */
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) { __STATIC_INLINE uint8_t DAP_GetProductString(char* str) {
static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME); static const char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i]; for (size_t i = 0; i < sizeof(prd); ++i) str[i] = prd[i];
return sizeof(prd)-1; return sizeof(prd) - 1;
} }
/** Get Serial Number string. /** Get Serial Number string.
\param str Pointer to buffer to store the string. \param str Pointer to buffer to store the string.
\return String length. \return String length.
*/ */
__STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) { __STATIC_INLINE uint8_t DAP_GetSerNumString(char* str) { return get_unique_id_u8((uint8_t*)str); }
return get_unique_id_u8((uint8_t*)str);
}
/** Get Target Device Vendor string. /** Get Target Device Vendor string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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. /** Get Target Device Name string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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. /** Get Target Board Vendor string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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. /** Get Target Board Name string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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! */ /* TODO! */
/** Get Product Firmware Version string. /** Get Product Firmware Version string.
\param str Pointer to buffer to store the string (max 60 characters). \param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string). \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 \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 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: interface of a device. The following I/O Pins are provided:
JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode 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 TCK: Test Clock | SWCLK: Clock | Output Push/Pull
TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data)
TDI: Test Data Input | | Output Push/Pull 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 nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor
nRESET: Device Reset | nRESET: Device Reset | 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 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 The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins. these I/O Pins.
For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. 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 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 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: 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_ENABLE to enable the output mode from the DAP hardware.
- \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to 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. - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed.
*/ */
// Configure DAP I/O pins ------------------------------ // Configure DAP I/O pins ------------------------------
/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. /** 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. - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level.
- TDO to input mode. - TDO to input mode.
*/ */
__STATIC_INLINE void PORT_JTAG_SETUP (void) { __STATIC_INLINE void PORT_JTAG_SETUP(void) {
resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS); resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS);
/* set to default high level */ /* 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_oe_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK |
sio_hw->gpio_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK | PINOUT_nRESET_MASK; PINOUT_nRESET_MASK;
/* TDO needs to be an input */ sio_hw->gpio_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK |
sio_hw->gpio_oe_clr = PINOUT_TDO_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], hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TCK],
PADS_BANK0_GPIO0_IE_BITS, // bits to set: input enable 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 PADS_BANK0_GPIO0_IE_BITS |
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TMS], PADS_BANK0_GPIO0_OD_BITS); // bits to mask out: input enable, output disable
PADS_BANK0_GPIO0_IE_BITS, hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TMS], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDI], hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDI], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDO],
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDO], PADS_BANK0_GPIO0_IE_BITS |
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS, // TDO needs to have its output disabled PADS_BANK0_GPIO0_OD_BITS, // TDO needs to have its output disabled
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nTRST], hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nTRST], PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_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,
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nRESET], PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
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); // NOTE: hiZ: ctrl = (ctrl & ~(CTRL_OEOVER_BITS)) | (GPIO_OVERRIDE_LOW << CTRL_OEOVER_LSB);
// normal == 0, low == 2 // normal == 0, low == 2
// set pin modes to general IO (SIO) // 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_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_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_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) 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)*/; /*| (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_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; 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. /** 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. - SWCLK, SWDIO, nRESET to output mode and set to default high level.
- TDI, nTRST to HighZ mode (pins are unused in SWD mode). - 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) {
resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS); resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS);
/* set to default high level */ /* set to default high level */
sio_hw->gpio_oe_set = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK; sio_hw->gpio_oe_set = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK;
sio_hw->gpio_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_SWCLK], PADS_BANK0_GPIO0_IE_BITS,
hw_write_masked(&padsbank0_hw->io[PINOUT_SWDIO], PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_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; hw_write_masked(&padsbank0_hw->io[PINOUT_SWDIO], PADS_BANK0_GPIO0_IE_BITS,
iobank0_hw->io[PINOUT_SWDIO].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; 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. /** Disable JTAG/SWD I/O Pins.
Disables the DAP Hardware I/O pins which configures: Disables the DAP Hardware I/O pins which configures:
- TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode.
*/ */
__STATIC_INLINE void PORT_OFF (void) { __STATIC_INLINE void PORT_OFF(void) {
sio_hw->gpio_oe_clr = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK sio_hw->gpio_oe_clr = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK |
| PINOUT_TDI_MASK //| PINOUT_TDO_MASK PINOUT_TDI_MASK //| PINOUT_TDO_MASK
| PINOUT_nTRST_MASK | PINOUT_nRESET_MASK; | PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
} }
// SWCLK/TCK I/O pin ------------------------------------- // SWCLK/TCK I/O pin -------------------------------------
/** SWCLK/TCK I/O pin: Get Input. /** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin. \return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) {
return (sio_hw->gpio_in & PINOUT_SWCLK_MASK) >> PINOUT_SWCLK; return (sio_hw->gpio_in & PINOUT_SWCLK_MASK) >> PINOUT_SWCLK;
} }
/** SWCLK/TCK I/O pin: Set Output to High. /** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level. 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) { sio_hw->gpio_set = PINOUT_SWCLK_MASK; }
sio_hw->gpio_set = PINOUT_SWCLK_MASK;
}
/** SWCLK/TCK I/O pin: Set Output to Low. /** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level. 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) { sio_hw->gpio_clr = PINOUT_SWCLK_MASK; }
sio_hw->gpio_clr = PINOUT_SWCLK_MASK;
}
// SWDIO/TMS Pin I/O -------------------------------------- // SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input. /** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin. \return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) {
return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) >> PINOUT_SWDIO; return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) >> PINOUT_SWDIO;
} }
/* PIN_SWDIO_TMS_SET and PIN_SWDIO_TMS_CLR are used by SWJ_Sequence */ /* 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. /** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level. 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) { sio_hw->gpio_set = PINOUT_SWDIO_MASK; }
sio_hw->gpio_set = PINOUT_SWDIO_MASK;
}
/** SWDIO/TMS I/O pin: Set Output to Low. /** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level. 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) { sio_hw->gpio_clr = PINOUT_SWDIO_MASK; }
sio_hw->gpio_clr = PINOUT_SWDIO_MASK;
}
/** SWDIO I/O pin: Get Input (used in SWD mode only). /** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin. \return Current status of the SWDIO DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) {
return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) ? 1U : 0U; return (sio_hw->gpio_in & PINOUT_SWDIO_MASK) ? 1U : 0U;
} }
/** SWDIO I/O pin: Set Output (used in SWD mode only). /** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin. \param bit Output value for the SWDIO DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) {
if (bit & 1) if (bit & 1)
sio_hw->gpio_set = PINOUT_SWDIO_MASK; sio_hw->gpio_set = PINOUT_SWDIO_MASK;
else else
sio_hw->gpio_clr = PINOUT_SWDIO_MASK; sio_hw->gpio_clr = PINOUT_SWDIO_MASK;
} }
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only). /** 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 Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls. called prior \ref PIN_SWDIO_OUT function calls.
*/ */
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) { __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) { sio_hw->gpio_oe_set = PINOUT_SWDIO_MASK; }
sio_hw->gpio_oe_set = PINOUT_SWDIO_MASK;
}
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only). /** 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 Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls. called prior \ref PIN_SWDIO_IN function calls.
*/ */
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) { __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) { sio_hw->gpio_oe_clr = PINOUT_SWDIO_MASK; }
sio_hw->gpio_oe_clr = PINOUT_SWDIO_MASK;
}
// TDI Pin I/O --------------------------------------------- // TDI Pin I/O ---------------------------------------------
/** TDI I/O pin: Get Input. /** TDI I/O pin: Get Input.
\return Current status of the TDI DAP hardware I/O pin. \return Current status of the TDI DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) {
return (sio_hw->gpio_in & PINOUT_TDI_MASK) >> PINOUT_JTAG_TDI; return (sio_hw->gpio_in & PINOUT_TDI_MASK) >> PINOUT_JTAG_TDI;
} }
/** TDI I/O pin: Set Output. /** TDI I/O pin: Set Output.
\param bit Output value for the TDI DAP hardware I/O pin. \param bit Output value for the TDI DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) {
if (bit & 1) if (bit & 1)
sio_hw->gpio_set = PINOUT_TDI_MASK; sio_hw->gpio_set = PINOUT_TDI_MASK;
else else
sio_hw->gpio_clr = PINOUT_TDI_MASK; sio_hw->gpio_clr = PINOUT_TDI_MASK;
} }
// TDO Pin I/O --------------------------------------------- // TDO Pin I/O ---------------------------------------------
/** TDO I/O pin: Get Input. /** TDO I/O pin: Get Input.
\return Current status of the TDO DAP hardware I/O pin. \return Current status of the TDO DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) {
return (sio_hw->gpio_in & PINOUT_TDO_MASK) >> PINOUT_JTAG_TDO; return (sio_hw->gpio_in & PINOUT_TDO_MASK) >> PINOUT_JTAG_TDO;
} }
// nTRST Pin I/O ------------------------------------------- // nTRST Pin I/O -------------------------------------------
/** nTRST I/O pin: Get Input. /** nTRST I/O pin: Get Input.
\return Current status of the nTRST DAP hardware I/O pin. \return Current status of the nTRST DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) {
return (sio_hw->gpio_in & PINOUT_nTRST_MASK) >> PINOUT_JTAG_nTRST; return (sio_hw->gpio_in & PINOUT_nTRST_MASK) >> PINOUT_JTAG_nTRST;
} }
/** nTRST I/O pin: Set Output. /** 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. - 0: issue a JTAG TRST Test Reset.
- 1: release JTAG TRST Test Reset. - 1: release JTAG TRST Test Reset.
*/ */
__STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) {
if (bit & 1) if (bit & 1)
sio_hw->gpio_set = PINOUT_nTRST_MASK; sio_hw->gpio_set = PINOUT_nTRST_MASK;
else else
sio_hw->gpio_clr = PINOUT_nTRST_MASK; sio_hw->gpio_clr = PINOUT_nTRST_MASK;
} }
// nRESET Pin I/O------------------------------------------ // nRESET Pin I/O------------------------------------------
@ -491,8 +488,8 @@ __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
/** nRESET I/O pin: Get Input. /** nRESET I/O pin: Get Input.
\return Current status of the nRESET DAP hardware I/O pin. \return Current status of the nRESET DAP hardware I/O pin.
*/ */
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) { __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) {
return (sio_hw->gpio_in & PINOUT_nRESET_MASK) >> PINOUT_JTAG_nRESET; return (sio_hw->gpio_in & PINOUT_nRESET_MASK) >> PINOUT_JTAG_nRESET;
} }
/** nRESET I/O pin: Set Output. /** nRESET I/O pin: Set Output.
@ -500,18 +497,17 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
- 0: issue a device hardware reset. - 0: issue a device hardware reset.
- 1: release device hardware reset. - 1: release device hardware reset.
*/ */
__STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) { __STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) {
if (bit & 1) if (bit & 1)
sio_hw->gpio_set = PINOUT_nRESET_MASK; sio_hw->gpio_set = PINOUT_nRESET_MASK;
else else
sio_hw->gpio_clr = PINOUT_nRESET_MASK; sio_hw->gpio_clr = PINOUT_nRESET_MASK;
} }
///@} ///@}
//************************************************************************************************** //**************************************************************************************************
/** /**
\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs
\ingroup DAP_ConfigIO_gr \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. - 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. - 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 PINOUT_LED_CONNECTED
if (bit & 1) if (bit & 1)
sio_hw->gpio_set = PINOUT_LED_MASK; sio_hw->gpio_set = PINOUT_LED_MASK;
else else
sio_hw->gpio_clr = PINOUT_LED_MASK; sio_hw->gpio_clr = PINOUT_LED_MASK;
#else #else
(void)bit; (void)bit;
#endif #endif
} }
@ -544,20 +540,19 @@ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
- 1: Target Running LED ON: program execution in target started. - 1: Target Running LED ON: program execution in target started.
- 0: Target Running LED OFF: program execution in target stopped. - 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 PINOUT_LED_RUNNING
if (bit & 1) if (bit & 1)
sio_hw->gpio_set = PINOUT_LED_MASK; sio_hw->gpio_set = PINOUT_LED_MASK;
else else
sio_hw->gpio_clr = PINOUT_LED_MASK; sio_hw->gpio_clr = PINOUT_LED_MASK;
#else #else
(void)bit; (void)bit;
#endif #endif
} }
///@} ///@}
//************************************************************************************************** //**************************************************************************************************
/** /**
\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp \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. 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 The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET.
default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. By default, the DWT timer is used. The frequency of this timer is configured with \ref
TIMESTAMP_CLOCK.
*/ */
/** Get timestamp of Test Domain Timer. /** Get timestamp of Test Domain Timer.
\return Current timestamp value. \return Current timestamp value.
*/ */
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) { __STATIC_INLINE uint32_t TIMESTAMP_GET(void) {
#if TIMESTAMP_CLOCK > 0 #if TIMESTAMP_CLOCK > 0
return (DWT->CYCCNT); return (DWT->CYCCNT);
#else #else
return 0; return 0;
#endif #endif
} }
///@} ///@}
//************************************************************************************************** //**************************************************************************************************
/** /**
\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization \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). /** 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: Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set:
- I/O clock system enabled. - I/O clock system enabled.
- all I/O pins: input buffer enabled, output pins are set to HighZ mode. - 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. - for nTRST, nRESET a weak pull-up (if available) is enabled.
- LED output pins are enabled and LEDs are turned off. - LED output pins are enabled and LEDs are turned off.
*/ */
__STATIC_INLINE void DAP_SETUP (void) { __STATIC_INLINE void DAP_SETUP(void) {
sio_hw->gpio_oe_set = PINOUT_LED_MASK; sio_hw->gpio_oe_set = PINOUT_LED_MASK;
sio_hw->gpio_clr = 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); hw_write_masked(
iobank0_hw->io[PINOUT_LED].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; &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( bi_decl(bi_2pins_with_names(PINOUT_JTAG_TCK, "TCK / SWCLK", PINOUT_JTAG_TMS, "TMS / SWDIO"));
PINOUT_JTAG_TCK, "TCK / SWCLK", bi_decl(bi_4pins_with_names(PINOUT_JTAG_TDI, "TDI", PINOUT_JTAG_TDO, "TDO", PINOUT_JTAG_nTRST,
PINOUT_JTAG_TMS, "TMS / SWDIO" "nTRST", PINOUT_JTAG_nRESET, "nRESET"));
));
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. /** Reset Target Device with custom specific I/O pin or command sequence.
This function allows the optional implementation of a device specific reset 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. when a device needs a time-critical unlock sequence that enables the debug port.
\return 0 = no device specific reset sequence is implemented.\n \return 0 = no device specific reset sequence is implemented.\n
1 = a device specific reset sequence is implemented. 1 = a device specific reset sequence is implemented.
*/ */
__STATIC_INLINE uint8_t RESET_TARGET (void) { __STATIC_INLINE uint8_t RESET_TARGET(void) {
return (0U); // change to '1' when a device reset sequence is implemented 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) * The MIT License (MIT)
* *
* Copyright (c) 2021, Ha Thach (tinyusb.org) * Copyright (c) 2021, Ha Thach (tinyusb.org)
@ -32,18 +33,19 @@ extern "C" {
#endif #endif
#ifdef PICO_DEFAULT_LED_PIN #ifdef PICO_DEFAULT_LED_PIN
#define LED_PIN PICO_DEFAULT_LED_PIN #define LED_PIN PICO_DEFAULT_LED_PIN
#define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED)) #define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED))
#endif #endif
// Button pin is BOOTSEL which is flash CS pin // Button pin is BOOTSEL which is flash CS pin
#define BUTTON_BOOTSEL #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) #if !defined(USE_USBCDC_FOR_STDIO) && defined(PICO_DEFAULT_UART_TX_PIN) && \
#define UART_DEV PICO_DEFAULT_UART defined(PICO_DEFAULT_UART_RX_PIN) && defined(PICO_DEFAULT_UART)
#define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN #define UART_DEV PICO_DEFAULT_UART
#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN #define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN
#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

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

View File

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

View File

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

View File

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

View File

@ -1,74 +1,72 @@
// vim: set et:
#include <stdio.h> #include <stdio.h>
#include <pico/stdlib.h>
#include <pico/binary_info.h>
#include <hardware/spi.h> #include <hardware/spi.h>
#include <pico/binary_info.h>
#include <pico/stdlib.h>
#include "pinout.h" #include "pinout.h"
#include "protos.h" #include "protos.h"
#include "serprog.h" #include "serprog.h"
static bool cs_asserted; static bool cs_asserted;
void sp_spi_init(void) { 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_nCS, GPIO_FUNC_SIO);
gpio_set_function(PINOUT_SPI_MOSI, GPIO_FUNC_SPI); gpio_init(PINOUT_SPI_nCS);
gpio_set_function(PINOUT_SPI_SCLK, GPIO_FUNC_SPI); gpio_put(PINOUT_SPI_nCS, 1);
gpio_set_dir(PINOUT_SPI_nCS, GPIO_OUT);
//gpio_set_function(PINOUT_SPI_nCS, GPIO_FUNC_SIO); bi_decl(bi_3pins_with_func(PINOUT_SPI_MISO, PINOUT_SPI_MOSI, PINOUT_SPI_SCLK, GPIO_FUNC_SPI));
gpio_init(PINOUT_SPI_nCS); bi_decl(bi_1pin_with_name(PINOUT_SPI_nCS, "SPI #CS"));
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"));
} }
uint32_t __not_in_flash_func(sp_spi_set_freq)(uint32_t freq_wanted) { 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) { void __not_in_flash_func(sp_spi_cs_deselect)(void) {
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 1); gpio_put(PINOUT_SPI_nCS, 1);
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = false; cs_asserted = false;
} }
void __not_in_flash_func(sp_spi_cs_select)(void) { void __not_in_flash_func(sp_spi_cs_select)(void) {
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 0); gpio_put(PINOUT_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = true; cs_asserted = true;
} }
void __not_in_flash_func(sp_spi_op_begin)(void) { void __not_in_flash_func(sp_spi_op_begin)(void) {
//sp_spi_cs_select(); // sp_spi_cs_select();
if (!cs_asserted) { if (!cs_asserted) {
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 0); gpio_put(PINOUT_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
} }
} }
void __not_in_flash_func(sp_spi_op_end)(void) { void __not_in_flash_func(sp_spi_op_end)(void) {
//sp_spi_cs_deselect(); // sp_spi_cs_deselect();
if (!cs_asserted) { // YES, this condition is the intended one! if (!cs_asserted) { // YES, this condition is the intended one!
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 1); gpio_put(PINOUT_SPI_nCS, 1);
asm volatile("nop\nnop\nnop"); // idk if this is needed asm volatile("nop\nnop\nnop"); // idk if this is needed
} }
} }
// TODO: use dma? // TODO: use dma?
void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const uint8_t* write_data) { 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) { 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 @@
// vim: set et:
#include <hardware/adc.h>
#include "tempsensor.h" #include "tempsensor.h"
#include <hardware/adc.h>
#define T_SLOPE (-0.001721f) #define T_SLOPE (-0.001721f)
#define T_BIAS (0.706f) #define T_BIAS (0.706f)
#define V_MAX (3.3f) #define V_MAX (3.3f)
@ -10,38 +11,41 @@
#define T_OFF (27) #define T_OFF (27)
// convert float to x.4 fixed format // 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 // convert x.4 fixed to 8.4 fixed
__attribute__((__const__)) __attribute__((__const__)) inline static int16_t trunc_8fix4(int fix) {
inline static int16_t trunc_8fix4(int fix) { // clang-format off
if (fix > 4095) fix = 4095; if (fix > 4095) fix = 4095;
if (fix < -4096) fix = -4096; if (fix < -4096) fix = -4096;
return fix; // clang-format on
return fix;
} }
void tempsense_dev_init(void) { void tempsense_dev_init(void) {
adc_init(); adc_init();
adc_set_temp_sensor_enabled(true); adc_set_temp_sensor_enabled(true);
} }
// 8.4 // 8.4
int16_t tempsense_dev_get_temp(void) { int16_t tempsense_dev_get_temp(void) {
adc_select_input(4); // select temp sensor adc_select_input(4); // select temp sensor
uint16_t result = adc_read(); 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 // FIXME: use fixed point instead! but something's wrong with the formula below
/*int temperature = float2fix(T_OFF - T_BIAS / T_SLOPE) /*int temperature = float2fix(T_OFF - T_BIAS / T_SLOPE)
+ (int)result * float2fix(V_MAX / (D_RANGE * 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 // 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_lower(void) { return trunc_8fix4(float2fix(-15)); }
int16_t tempsense_dev_get_upper(void) { return trunc_8fix4(float2fix( 75)); } int16_t tempsense_dev_get_upper(void) { return trunc_8fix4(float2fix( 75)); }
int16_t tempsense_dev_get_crit (void) { return trunc_8fix4(float2fix( 80)); } 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 <stdint.h>
#include <pico/stdlib.h> #include <pico/stdlib.h>
#include <pico/unique_id.h> #include <pico/unique_id.h>
#include "tusb.h"
#include "tusb.h"
#include "util.h" #include "util.h"
uint8_t get_unique_id_u8(uint8_t *desc_str) { uint8_t get_unique_id_u8(uint8_t* desc_str) {
pico_unique_board_id_t uid; pico_unique_board_id_t uid;
uint8_t chr_count = 0;
pico_get_unique_board_id(&uid); uint8_t chr_count = 0;
for (size_t byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) { pico_get_unique_board_id(&uid);
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; 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) { uint8_t get_unique_id_u16(uint16_t* desc_str) {
pico_unique_board_id_t uid; pico_unique_board_id_t uid;
uint8_t chr_count = 0;
pico_get_unique_board_id(&uid); uint8_t chr_count = 0;
for (size_t byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) { pico_get_unique_board_id(&uid);
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; 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) */ /* derived from libco v20, by byuu (ISC) */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,64 +4,70 @@
#include <stdint.h> #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_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_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" #include "../tempsensor.c"
static int do_pkt(uint8_t cmd, bool read, uint16_t addr, uint16_t len, uint8_t* buf) { 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) { if (read) {
rv = tempsense_do_read(len, buf); rv = tempsense_do_read(len, buf);
} else { } else {
rv = tempsense_do_write(len, buf); 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) { static void pbuf(size_t len, const uint8_t* buf) {
printf("--> "); printf("--> ");
size_t i; size_t i;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
printf("%02x ", buf[i]); printf("%02x ", buf[i]);
if ((i & 0xf) == 0xf) printf("%c", '\n'); if ((i & 0xf) == 0xf) printf("%c", '\n');
} }
if ((i & 0xf) != 0x0) printf("%c", '\n'); if ((i & 0xf) != 0x0) printf("%c", '\n');
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
tempsense_init(); tempsense_init();
tempsense_set_addr(0x18); tempsense_set_addr(0x18);
// initial probe // initial probe
uint8_t pk1[1] = {0}; do_pkt(0x05, false, 0x18, 1, pk1); uint8_t pk1[1] = {0};
uint8_t pk2[2]; do_pkt(0x06, true , 0x18, 2, pk2); pbuf(2, pk2); 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 pk3[1] = {1};
uint8_t pk4[2]; do_pkt(0x06, true , 0x18, 2, pk4); pbuf(2, pk4); 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 // out 0x05 cmd5
// in 2byte cmd6 // in 2byte cmd6
// out 0x04 cmd5 // out 0x04 cmd5
// in 2byte cmd6 // in 2byte cmd6
// out 0x03 cmd5 // out 0x03 cmd5
// in 2byte cmd6 // in 2byte cmd6
// out 0x02 cmd5 // out 0x02 cmd5
// in 2byte cmd6 // in 2byte cmd6
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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