initial formatting changes
replace DOS endings with UNIX endings, and replace leading tabs with 4x spaces in all files. any non-leading tabs (ie, alignment tabs) are preserved as originally in the files. additionally, a .clang-format has been committed with the hopes that any new changes past this commit will be formatted with it the commands for this change were dos2unix <files that were using DOS endings> fd -e c -e h -e cc -e cxx | ag -v CMSIS | \ while read line; do \ expand -t4 -i $line > $line.new; mv $line.new $line; \ done
This commit is contained in:
parent
87acd775bf
commit
01e30c8e59
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
BasedOnStyle: Google
|
||||||
|
IndentWidth: 4
|
||||||
|
ColumnLimit: 100
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
PointerAlignment: Left
|
||||||
|
...
|
|
@ -135,9 +135,9 @@ This information includes:
|
||||||
\return String length.
|
\return String length.
|
||||||
*/
|
*/
|
||||||
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
||||||
const static char vnd[] = INFO_MANUFACTURER;
|
const static 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.
|
||||||
|
@ -145,9 +145,9 @@ __STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
||||||
\return String length.
|
\return String length.
|
||||||
*/
|
*/
|
||||||
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
||||||
const static char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
|
const static 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.
|
||||||
|
@ -155,7 +155,7 @@ __STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
||||||
\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(str);
|
return get_unique_id_u8(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -205,7 +205,7 @@ Configures the DAP Hardware I/O pins for JTAG mode:
|
||||||
- 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.
|
||||||
|
@ -214,7 +214,7 @@ Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
|
||||||
- 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.
|
||||||
|
@ -222,7 +222,7 @@ 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) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,21 +232,21 @@ __STATIC_INLINE void PORT_OFF (void) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -256,35 +256,35 @@ __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 (board_millis() & 1); /* pacify GCC warning */
|
return (board_millis() & 1); /* pacify GCC warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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).
|
||||||
|
@ -292,7 +292,7 @@ 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).
|
||||||
|
@ -300,7 +300,7 @@ 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) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -310,14 +310,14 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ __STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) {
|
||||||
\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 (board_millis() & 1); /* pacify GCC warning */
|
return (board_millis() & 1); /* pacify GCC warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ __STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** nTRST I/O pin: Set Output.
|
/** nTRST I/O pin: Set Output.
|
||||||
|
@ -346,7 +346,7 @@ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) {
|
||||||
- 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------------------------------------------
|
||||||
|
@ -355,7 +355,7 @@ __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** nRESET I/O pin: Set Output.
|
/** nRESET I/O pin: Set Output.
|
||||||
|
@ -364,7 +364,7 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
|
||||||
- 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -389,7 +389,7 @@ It is recommended to provide the following LEDs for status indication:
|
||||||
- 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.
|
||||||
|
@ -398,7 +398,7 @@ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
|
||||||
- 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -421,9 +421,9 @@ default, the DWT timer is used. The frequency of this timer is configured with
|
||||||
*/
|
*/
|
||||||
__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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +448,7 @@ Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled an
|
||||||
- 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.
|
||||||
|
@ -459,7 +459,7 @@ when a device needs a time-critical unlock sequence that enables the debug port.
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
|
@ -6,22 +6,22 @@
|
||||||
/* in the absence of the board-specific directory providing a unique ID, we provide a canned one */
|
/* in the absence of the board-specific directory providing a unique ID, we provide a canned one */
|
||||||
|
|
||||||
__attribute__((__weak__)) uint8_t get_unique_id_u8(uint8_t *desc_str) {
|
__attribute__((__weak__)) uint8_t get_unique_id_u8(uint8_t *desc_str) {
|
||||||
static const char canned[] = "123456";
|
static const char canned[] = "123456";
|
||||||
|
|
||||||
for (int i=0; i<TU_ARRAY_SIZE(canned); i++) {
|
for (int i=0; i<TU_ARRAY_SIZE(canned); i++) {
|
||||||
desc_str[i] = canned[i];
|
desc_str[i] = canned[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((__weak__)) uint8_t get_unique_id_u16(uint16_t *desc_str) {
|
__attribute__((__weak__)) uint8_t get_unique_id_u16(uint16_t *desc_str) {
|
||||||
static const char canned[] = "123456";
|
static const char canned[] = "123456";
|
||||||
|
|
||||||
for (int i=0; i<TU_ARRAY_SIZE(canned); i++) {
|
for (int i=0; i<TU_ARRAY_SIZE(canned); i++) {
|
||||||
desc_str[i] = canned[i];
|
desc_str[i] = canned[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,9 +161,9 @@ This information includes:
|
||||||
\return String length.
|
\return String length.
|
||||||
*/
|
*/
|
||||||
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
||||||
const static char vnd[] = INFO_MANUFACTURER;
|
const static 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.
|
||||||
|
@ -171,9 +171,9 @@ __STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
||||||
\return String length.
|
\return String length.
|
||||||
*/
|
*/
|
||||||
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
||||||
const static char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
|
const static 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.
|
||||||
|
@ -181,7 +181,7 @@ __STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
||||||
\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);
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -231,44 +231,44 @@ Configures the DAP Hardware I/O pins for JTAG mode:
|
||||||
- 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 | PINOUT_nRESET_MASK;
|
||||||
sio_hw->gpio_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
|
sio_hw->gpio_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
|
||||||
/* TDO needs to be an input */
|
/* TDO needs to be an input */
|
||||||
sio_hw->gpio_oe_clr = PINOUT_TDO_MASK;
|
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 | PADS_BANK0_GPIO0_OD_BITS); // bits to mask out: input enable, output disable
|
||||||
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TMS],
|
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TMS],
|
||||||
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_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_OD_BITS, // TDO needs to have its output disabled
|
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS, // TDO needs to have its output disabled
|
||||||
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
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],
|
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nRESET],
|
||||||
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);
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -277,16 +277,16 @@ Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
|
||||||
- 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, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
||||||
hw_write_masked(&padsbank0_hw->io[PINOUT_SWDIO], PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
hw_write_masked(&padsbank0_hw->io[PINOUT_SWDIO], PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
||||||
iobank0_hw->io[PINOUT_SWCLK].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
iobank0_hw->io[PINOUT_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;
|
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.
|
||||||
|
@ -294,9 +294,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -306,21 +306,21 @@ __STATIC_INLINE void PORT_OFF (void) {
|
||||||
\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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
|
||||||
\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 */
|
||||||
|
@ -339,31 +339,31 @@ __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
|
||||||
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).
|
||||||
|
@ -371,7 +371,7 @@ 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).
|
||||||
|
@ -379,7 +379,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -389,17 +389,17 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
|
||||||
\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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ __STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) {
|
||||||
\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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ __STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) {
|
||||||
\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.
|
||||||
|
@ -428,10 +428,10 @@ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) {
|
||||||
- 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------------------------------------------
|
||||||
|
@ -440,7 +440,7 @@ __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
|
||||||
\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.
|
||||||
|
@ -449,10 +449,10 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
|
||||||
- 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -478,12 +478,12 @@ It is recommended to provide the following LEDs for status indication:
|
||||||
*/
|
*/
|
||||||
__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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,12 +494,12 @@ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
|
||||||
*/
|
*/
|
||||||
__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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,9 +523,9 @@ default, the DWT timer is used. The frequency of this timer is configured with
|
||||||
*/
|
*/
|
||||||
__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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,22 +550,22 @@ Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled an
|
||||||
- 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(&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;
|
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_TCK, "TCK / SWCLK",
|
||||||
PINOUT_JTAG_TMS, "TMS / SWDIO"
|
PINOUT_JTAG_TMS, "TMS / SWDIO"
|
||||||
));
|
));
|
||||||
bi_decl(bi_4pins_with_names(
|
bi_decl(bi_4pins_with_names(
|
||||||
PINOUT_JTAG_TDI , "TDI",
|
PINOUT_JTAG_TDI , "TDI",
|
||||||
PINOUT_JTAG_TDO , "TDO",
|
PINOUT_JTAG_TDO , "TDO",
|
||||||
PINOUT_JTAG_nTRST , "nTRST",
|
PINOUT_JTAG_nTRST , "nTRST",
|
||||||
PINOUT_JTAG_nRESET, "nRESET"
|
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.
|
||||||
|
@ -576,7 +576,7 @@ when a device needs a time-critical unlock sequence that enables the debug port.
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
|
@ -22,85 +22,85 @@
|
||||||
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;
|
rc = count ? count : PICO_ERROR_NO_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_exit(&stdio_usb_mutex);
|
mutex_exit(&stdio_usb_mutex);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern stdio_driver_t stdio_usb;
|
extern stdio_driver_t stdio_usb;
|
||||||
stdio_driver_t stdio_usb = {
|
stdio_driver_t stdio_usb = {
|
||||||
.out_chars = stdio_usb_out_chars,
|
.out_chars = stdio_usb_out_chars,
|
||||||
. in_chars = stdio_usb_in_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
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,43 +35,43 @@ 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 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) {
|
||||||
//picoprobe_info("New baud rate %d\n", line_coding->bit_rate);
|
//picoprobe_info("New baud rate %d\n", line_coding->bit_rate);
|
||||||
uart_init(PINOUT_UART_INTERFACE, line_coding->bit_rate);
|
uart_init(PINOUT_UART_INTERFACE, line_coding->bit_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,407 +17,407 @@ 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)(uint8_t v) { // return value: acked? // needed for 10bitaddr xfers
|
||||||
for (int i = 6; i >= 0; --i) {
|
for (int i = 6; 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 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) i2cio_set_sda(true);
|
||||||
else i2cio_set_sda(false);
|
else i2cio_set_sda(false);
|
||||||
|
|
||||||
i2cio_scl_toggle();
|
i2cio_scl_toggle();
|
||||||
i2cio_set_sda(true);
|
i2cio_set_sda(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)) rv = 0;
|
||||||
else rv = PICO_ERROR_GENERIC;
|
else rv = PICO_ERROR_GENERIC;
|
||||||
} else rv = PICO_ERROR_GENERIC;
|
} else rv = PICO_ERROR_GENERIC;
|
||||||
} else {
|
} else {
|
||||||
if (i2cio_write8((addr << 1) & 0xff)) rv = 0; // acked: ok
|
if (i2cio_write8((addr << 1) & 0xff)) rv = 0; // acked: ok
|
||||||
else rv = PICO_ERROR_GENERIC; // nak :/
|
else rv = PICO_ERROR_GENERIC; // nak :/
|
||||||
}
|
}
|
||||||
i2cio_stop();
|
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
|
||||||
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_;
|
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;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
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, (a10bit
|
||||||
? I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_10BITS
|
? 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_IC_CON_IC_10BITADDR_MASTER_LSB);
|
||||||
i2c->hw->tar = addr;
|
i2c->hw->tar = addr;
|
||||||
i2c->hw->enable = 1;
|
i2c->hw->enable = 1;
|
||||||
|
|
||||||
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,
|
||||||
last = byte_ctr == (int)len - 1;
|
last = byte_ctr == (int)len - 1;
|
||||||
|
|
||||||
i2c->hw->data_cmd =
|
i2c->hw->data_cmd =
|
||||||
bool_to_bit(first && i2c->restart_on_next) << I2C_IC_DATA_CMD_RESTART_LSB |
|
bool_to_bit(first && i2c->restart_on_next) << I2C_IC_DATA_CMD_RESTART_LSB |
|
||||||
bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB |
|
bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB |
|
||||||
*src++;
|
*src++;
|
||||||
|
|
||||||
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_TX_EMPTY_BITS));
|
||||||
|
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
abort_reason = i2c->hw->tx_abrt_source;
|
abort_reason = i2c->hw->tx_abrt_source;
|
||||||
if (abort_reason) {
|
if (abort_reason) {
|
||||||
(void)i2c->hw->clr_tx_abrt;
|
(void)i2c->hw->clr_tx_abrt;
|
||||||
abort = true;
|
abort = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abort || (last && !nostop)) {
|
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_STOP_DET_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) (void)i2c->hw->clr_stop_det;
|
||||||
else
|
else
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
} else i2cex_abort_xfer(i2c);
|
} else i2cex_abort_xfer(i2c);
|
||||||
|
|
||||||
if (abort) break;
|
if (abort) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
if (abort) {
|
if (abort) {
|
||||||
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) rval = PICO_ERROR_TIMEOUT;
|
if (timeout) rval = PICO_ERROR_TIMEOUT;
|
||||||
else if (!abort_reason || (abort_reason & addr_noack))
|
else if (!abort_reason || (abort_reason & addr_noack))
|
||||||
rval = PICO_ERROR_GENERIC;
|
rval = PICO_ERROR_GENERIC;
|
||||||
else if (abort_reason & I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_BITS)
|
else if (abort_reason & I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_BITS)
|
||||||
rval = byte_ctr;
|
rval = byte_ctr;
|
||||||
else rval = PICO_ERROR_GENERIC;
|
else rval = PICO_ERROR_GENERIC;
|
||||||
} else rval = byte_ctr;
|
} else rval = byte_ctr;
|
||||||
|
|
||||||
i2c->restart_on_next = nostop;
|
i2c->restart_on_next = nostop;
|
||||||
return rval;
|
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, size_t len, bool nostop, absolute_time_t until) {
|
uint8_t* dst, 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, (a10bit
|
||||||
? I2C_IC_CON_IC_10BITADDR_MASTER_VALUE_ADDR_10BITS
|
? 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_IC_CON_IC_10BITADDR_MASTER_LSB);
|
||||||
i2c->hw->tar = addr;
|
i2c->hw->tar = addr;
|
||||||
i2c->hw->enable = 1;
|
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) << I2C_IC_DATA_CMD_RESTART_LSB |
|
bool_to_bit(first && i2c->restart_on_next) << I2C_IC_DATA_CMD_RESTART_LSB |
|
||||||
bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB |
|
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");*/ rval = PICO_ERROR_TIMEOUT; }
|
||||||
else if (!abort_reason || (abort_reason & addr_noack)) {//printf("disconn\n");
|
else if (!abort_reason || (abort_reason & addr_noack)) {//printf("disconn\n");
|
||||||
rval = PICO_ERROR_GENERIC; }
|
rval = PICO_ERROR_GENERIC; }
|
||||||
else {/*printf("unk\n");*/ rval = PICO_ERROR_GENERIC;}
|
else {/*printf("unk\n");*/ rval = PICO_ERROR_GENERIC;}
|
||||||
} else rval = byte_ctr;
|
} 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, size_t len, bool nostop, uint32_t timeout_us) {
|
uint8_t* dst, 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; delay2 = 5;
|
||||||
i2c_init(PINOUT_I2C_DEV, 100*1000);
|
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, const uint8_t* buf, size_t len) {
|
uint16_t addr, 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');
|
//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,
|
int rv = i2cex_write_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len,
|
||||||
nostop, 1000*1000);
|
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, uint8_t* buf, size_t len) {
|
uint16_t addr, 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');
|
//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,
|
int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len,
|
||||||
nostop, 1000*1000);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,21 +9,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
|
||||||
|
|
|
@ -13,62 +13,62 @@
|
||||||
static bool cs_asserted;
|
static bool cs_asserted;
|
||||||
|
|
||||||
void sp_spi_init(void) {
|
void sp_spi_init(void) {
|
||||||
//printf("spi init!\n");
|
//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_MISO, GPIO_FUNC_SPI);
|
||||||
gpio_set_function(PINOUT_SPI_MOSI, 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_SCLK, GPIO_FUNC_SPI);
|
||||||
|
|
||||||
//gpio_set_function(PINOUT_SPI_nCS, GPIO_FUNC_SIO);
|
//gpio_set_function(PINOUT_SPI_nCS, GPIO_FUNC_SIO);
|
||||||
gpio_init(PINOUT_SPI_nCS);
|
gpio_init(PINOUT_SPI_nCS);
|
||||||
gpio_put(PINOUT_SPI_nCS, 1);
|
gpio_put(PINOUT_SPI_nCS, 1);
|
||||||
gpio_set_dir(PINOUT_SPI_nCS, GPIO_OUT);
|
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_3pins_with_func(PINOUT_SPI_MISO, PINOUT_SPI_MOSI, PINOUT_SPI_SCLK, GPIO_FUNC_SPI));
|
||||||
bi_decl(bi_1pin_with_name(PINOUT_SPI_nCS, "SPI #CS"));
|
bi_decl(bi_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,29 +15,29 @@
|
||||||
// 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) {
|
||||||
if (fix > 4095) fix = 4095;
|
if (fix > 4095) fix = 4095;
|
||||||
if (fix < -4096) fix = -4096;
|
if (fix < -4096) fix = -4096;
|
||||||
return fix;
|
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
|
||||||
|
|
|
@ -6,36 +6,36 @@
|
||||||
#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;
|
uint8_t chr_count = 0;
|
||||||
|
|
||||||
pico_get_unique_board_id(&uid);
|
pico_get_unique_board_id(&uid);
|
||||||
|
|
||||||
for (int byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
|
for (int byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
|
||||||
uint8_t tmp = uid.id[byte];
|
uint8_t tmp = uid.id[byte];
|
||||||
for (int digit = 0; digit < 2; digit++) {
|
for (int digit = 0; digit < 2; digit++) {
|
||||||
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
||||||
tmp >>= 4;
|
tmp >>= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chr_count;
|
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;
|
uint8_t chr_count = 0;
|
||||||
|
|
||||||
pico_get_unique_board_id(&uid);
|
pico_get_unique_board_id(&uid);
|
||||||
|
|
||||||
for (int byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
|
for (int byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) {
|
||||||
uint8_t tmp = uid.id[byte];
|
uint8_t tmp = uid.id[byte];
|
||||||
for (int digit = 0; digit < 2; digit++) {
|
for (int digit = 0; digit < 2; digit++) {
|
||||||
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
||||||
tmp >>= 4;
|
tmp >>= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chr_count;
|
return chr_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,9 +137,9 @@ This information includes:
|
||||||
\return String length.
|
\return String length.
|
||||||
*/
|
*/
|
||||||
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
||||||
const static char vnd[] = INFO_MANUFACTURER;
|
const static 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.
|
||||||
|
@ -147,9 +147,9 @@ __STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
|
||||||
\return String length.
|
\return String length.
|
||||||
*/
|
*/
|
||||||
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
||||||
const static char prd[] = INFO_PRODUCT(INFO_BOARDNAME);
|
const static 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.
|
||||||
|
@ -157,7 +157,7 @@ __STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
|
||||||
\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(str);
|
return get_unique_id_u8(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -232,7 +232,7 @@ Configures the DAP Hardware I/O pins for JTAG mode:
|
||||||
- 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.
|
||||||
|
@ -241,10 +241,10 @@ Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
|
||||||
- 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) {
|
||||||
CLK_ENABLE;
|
CLK_ENABLE;
|
||||||
DATA_ENABLE;
|
DATA_ENABLE;
|
||||||
SWDIO_INIT;
|
SWDIO_INIT;
|
||||||
CLK_HIGH; DATA_HIGH;
|
CLK_HIGH; DATA_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Disable JTAG/SWD I/O Pins.
|
/** Disable JTAG/SWD I/O Pins.
|
||||||
|
@ -252,9 +252,9 @@ 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) {
|
||||||
CLK_HIZ;
|
CLK_HIZ;
|
||||||
DATA_HIZ;
|
DATA_HIZ;
|
||||||
RESET_HIZ;
|
RESET_HIZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SWCLK/TCK I/O pin -------------------------------------
|
// SWCLK/TCK I/O pin -------------------------------------
|
||||||
|
@ -263,21 +263,21 @@ __STATIC_INLINE void PORT_OFF (void) {
|
||||||
\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 (CLK_READ) ? 1 : 0;
|
return (CLK_READ) ? 1 : 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) {
|
||||||
CLK_HIGH;
|
CLK_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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) {
|
||||||
CLK_LOW;
|
CLK_LOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -287,35 +287,35 @@ __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
|
||||||
\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 (DATA_READ) ? 1 : 0;
|
return (DATA_READ) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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) {
|
||||||
DATA_HIGH;
|
DATA_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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) {
|
||||||
DATA_LOW;
|
DATA_LOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 (DATA_READ) ? 1 : 0;
|
return (DATA_READ) ? 1 : 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) {
|
||||||
if (bit & 1) { DATA_HIGH; } else { DATA_LOW; }
|
if (bit & 1) { DATA_HIGH; } else { DATA_LOW; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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).
|
||||||
|
@ -323,7 +323,7 @@ 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) {
|
||||||
DATA_ENABLE;
|
DATA_ENABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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).
|
||||||
|
@ -331,7 +331,7 @@ 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) {
|
||||||
DATA_HIZ;
|
DATA_HIZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,14 +341,14 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ __STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ __STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) {
|
||||||
\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 (0U);
|
return (0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** nTRST I/O pin: Set Output.
|
/** nTRST I/O pin: Set Output.
|
||||||
|
@ -377,7 +377,7 @@ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) {
|
||||||
- 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------------------------------------------
|
||||||
|
@ -386,7 +386,7 @@ __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
|
||||||
\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 (RESET_READ) ? 1 : 0;
|
return (RESET_READ) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** nRESET I/O pin: Set Output.
|
/** nRESET I/O pin: Set Output.
|
||||||
|
@ -395,7 +395,7 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
|
||||||
- 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) { RESET_HIGH; } else { RESET_LOW; }
|
if (bit & 1) { RESET_HIGH; } else { RESET_LOW; }
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -420,7 +420,7 @@ It is recommended to provide the following LEDs for status indication:
|
||||||
- 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.
|
||||||
|
@ -429,7 +429,7 @@ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
|
||||||
- 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
@ -452,9 +452,9 @@ default, the DWT timer is used. The frequency of this timer is configured with
|
||||||
*/
|
*/
|
||||||
__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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +479,7 @@ Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled an
|
||||||
- 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.
|
||||||
|
@ -490,7 +490,7 @@ when a device needs a time-critical unlock sequence that enables the debug port.
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
|
|
||||||
bool stdio_usb_init(void) {
|
bool stdio_usb_init(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,22 @@
|
||||||
|
|
||||||
__attribute__((__const__))
|
__attribute__((__const__))
|
||||||
enum ki2c_funcs i2ctu_get_func(void) {
|
enum ki2c_funcs i2ctu_get_func(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2ctu_init(void) {
|
void i2ctu_init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t i2ctu_set_freq(uint32_t freq) {
|
uint32_t i2ctu_set_freq(uint32_t freq) {
|
||||||
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, const uint8_t* buf, size_t len) {
|
uint16_t addr, const uint8_t* buf, size_t len) {
|
||||||
return ITU_STATUS_IDLE;
|
return ITU_STATUS_IDLE;
|
||||||
}
|
}
|
||||||
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, uint8_t* buf, size_t len) {
|
uint16_t addr, uint8_t* buf, size_t len) {
|
||||||
return ITU_STATUS_IDLE;
|
return ITU_STATUS_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,15 @@
|
||||||
/*#define DBOARD_HAS_TINYI2C*/
|
/*#define DBOARD_HAS_TINYI2C*/
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
HID_N_CMSISDAP = 0,
|
HID_N_CMSISDAP = 0,
|
||||||
|
|
||||||
HID_N__NITF
|
HID_N__NITF
|
||||||
};
|
};
|
||||||
enum {
|
enum {
|
||||||
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
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
void sp_spi_init(void) {
|
void sp_spi_init(void) {
|
||||||
}
|
}
|
||||||
uint32_t sp_spi_set_freq(uint32_t freq_wanted) {
|
uint32_t sp_spi_set_freq(uint32_t freq_wanted) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void sp_spi_cs_deselect(void) {
|
void sp_spi_cs_deselect(void) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,30 +4,30 @@
|
||||||
#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) {
|
||||||
const uint32_t *idpnt = (uint32_t*)(0x1FFFF7AC); /*DEVICE_ID1*/
|
const uint32_t *idpnt = (uint32_t*)(0x1FFFF7AC); /*DEVICE_ID1*/
|
||||||
uint32_t tmp = 0;
|
uint32_t tmp = 0;
|
||||||
uint8_t chr_count = 0;
|
uint8_t chr_count = 0;
|
||||||
|
|
||||||
for (int digit = 0; digit < 24; digit++) {
|
for (int digit = 0; digit < 24; digit++) {
|
||||||
if (0 == (digit & 7)) tmp = *idpnt++;
|
if (0 == (digit & 7)) tmp = *idpnt++;
|
||||||
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
||||||
tmp >>= 4;
|
tmp >>= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return chr_count;
|
return chr_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t get_unique_id_u16(uint16_t *desc_str) {
|
uint8_t get_unique_id_u16(uint16_t *desc_str) {
|
||||||
const uint32_t *idpnt = (uint32_t*)(0x1FFFF7AC); /*DEVICE_ID1*/
|
const uint32_t *idpnt = (uint32_t*)(0x1FFFF7AC); /*DEVICE_ID1*/
|
||||||
uint32_t tmp = 0;
|
uint32_t tmp = 0;
|
||||||
uint8_t chr_count = 0;
|
uint8_t chr_count = 0;
|
||||||
|
|
||||||
for (int digit = 0; digit < 24; digit++) {
|
for (int digit = 0; digit < 24; digit++) {
|
||||||
if (0 == (digit & 7)) tmp = *idpnt++;
|
if (0 == (digit & 7)) tmp = *idpnt++;
|
||||||
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
desc_str[chr_count++] = nyb2hex(tmp & 0xf);
|
||||||
tmp >>= 4;
|
tmp >>= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return chr_count;
|
return chr_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,13 +34,13 @@
|
||||||
static unsigned short delay = 10;
|
static unsigned short delay = 10;
|
||||||
module_param(delay, ushort, 0);
|
module_param(delay, ushort, 0);
|
||||||
MODULE_PARM_DESC(delay, "bit delay in microseconds "
|
MODULE_PARM_DESC(delay, "bit delay in microseconds "
|
||||||
"(default is 10us for 100kHz max)");
|
"(default is 10us for 100kHz max)");
|
||||||
|
|
||||||
static int usb_read(struct i2c_adapter *adapter, int cmd,
|
static int usb_read(struct i2c_adapter *adapter, int cmd,
|
||||||
int value, int index, void *data, int len);
|
int value, int index, void *data, int len);
|
||||||
|
|
||||||
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||||
int value, int index, void *data, int len);
|
int value, int index, void *data, int len);
|
||||||
|
|
||||||
/* ----- begin of i2c layer ---------------------------------------------- */
|
/* ----- begin of i2c layer ---------------------------------------------- */
|
||||||
|
|
||||||
|
@ -50,102 +50,102 @@ static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||||
|
|
||||||
static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
||||||
{
|
{
|
||||||
unsigned char *pstatus;
|
unsigned char *pstatus;
|
||||||
struct i2c_msg *pmsg;
|
struct i2c_msg *pmsg;
|
||||||
int i, ret, r;
|
int i, ret, r;
|
||||||
|
|
||||||
dev_dbg(&adapter->dev, "master xfer %d messages:\n", num);
|
dev_dbg(&adapter->dev, "master xfer %d messages:\n", num);
|
||||||
|
|
||||||
pstatus = kmalloc(sizeof(*pstatus), GFP_KERNEL);
|
pstatus = kmalloc(sizeof(*pstatus), GFP_KERNEL);
|
||||||
if (!pstatus)
|
if (!pstatus)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0 ; i < num ; i++) {
|
for (i = 0 ; i < num ; i++) {
|
||||||
int cmd = CMD_I2C_IO;
|
int cmd = CMD_I2C_IO;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
cmd |= CMD_I2C_IO_BEGIN;
|
cmd |= CMD_I2C_IO_BEGIN;
|
||||||
|
|
||||||
if (i == num-1)
|
if (i == num-1)
|
||||||
cmd |= CMD_I2C_IO_END;
|
cmd |= CMD_I2C_IO_END;
|
||||||
|
|
||||||
pmsg = &msgs[i];
|
pmsg = &msgs[i];
|
||||||
|
|
||||||
dev_dbg(&adapter->dev,
|
dev_dbg(&adapter->dev,
|
||||||
" %d: %s (flags %d) %d bytes to 0x%02x\n",
|
" %d: %s (flags %d) %d bytes to 0x%02x\n",
|
||||||
i, pmsg->flags & I2C_M_RD ? "read" : "write",
|
i, pmsg->flags & I2C_M_RD ? "read" : "write",
|
||||||
pmsg->flags, pmsg->len, pmsg->addr);
|
pmsg->flags, pmsg->len, pmsg->addr);
|
||||||
|
|
||||||
/* and directly send the message */
|
/* and directly send the message */
|
||||||
if (pmsg->flags & I2C_M_RD) {
|
if (pmsg->flags & I2C_M_RD) {
|
||||||
/* read data */
|
/* read data */
|
||||||
if ((r = usb_read(adapter, cmd,
|
if ((r = usb_read(adapter, cmd,
|
||||||
pmsg->flags, pmsg->addr,
|
pmsg->flags, pmsg->addr,
|
||||||
pmsg->buf, pmsg->len)) != pmsg->len) {
|
pmsg->buf, pmsg->len)) != pmsg->len) {
|
||||||
dev_err(&adapter->dev,
|
dev_err(&adapter->dev,
|
||||||
"failure reading data: %i\n", r);
|
"failure reading data: %i\n", r);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* write data */
|
/* write data */
|
||||||
if ((r = usb_write(adapter, cmd,
|
if ((r = usb_write(adapter, cmd,
|
||||||
pmsg->flags, pmsg->addr,
|
pmsg->flags, pmsg->addr,
|
||||||
pmsg->buf, pmsg->len)) != pmsg->len) {
|
pmsg->buf, pmsg->len)) != pmsg->len) {
|
||||||
dev_err(&adapter->dev,
|
dev_err(&adapter->dev,
|
||||||
"failure writing data: %i\n", r);
|
"failure writing data: %i\n", r);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read status */
|
/* read status */
|
||||||
if ((r = usb_read(adapter, CMD_GET_STATUS, 0, 0, pstatus, 1)) != 1) {
|
if ((r = usb_read(adapter, CMD_GET_STATUS, 0, 0, pstatus, 1)) != 1) {
|
||||||
dev_err(&adapter->dev, "failure reading status: %i\n", r);
|
dev_err(&adapter->dev, "failure reading status: %i\n", r);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&adapter->dev, " status = %d\n", *pstatus);
|
dev_dbg(&adapter->dev, " status = %d\n", *pstatus);
|
||||||
if (*pstatus == STATUS_ADDRESS_NAK) {
|
if (*pstatus == STATUS_ADDRESS_NAK) {
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = i;
|
ret = i;
|
||||||
out:
|
out:
|
||||||
kfree(pstatus);
|
kfree(pstatus);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 usb_func(struct i2c_adapter *adapter)
|
static u32 usb_func(struct i2c_adapter *adapter)
|
||||||
{
|
{
|
||||||
__le32 *pfunc;
|
__le32 *pfunc;
|
||||||
u32 ret;
|
u32 ret;
|
||||||
int i=-1;
|
int i=-1;
|
||||||
|
|
||||||
pfunc = kmalloc(sizeof(*pfunc), GFP_KERNEL);
|
pfunc = kmalloc(sizeof(*pfunc), GFP_KERNEL);
|
||||||
|
|
||||||
/* get functionality from adapter */
|
/* get functionality from adapter */
|
||||||
if (!pfunc || (i=usb_read(adapter, CMD_GET_FUNC, 0, 0, pfunc,
|
if (!pfunc || (i=usb_read(adapter, CMD_GET_FUNC, 0, 0, pfunc,
|
||||||
sizeof(*pfunc))) != sizeof(*pfunc)) {
|
sizeof(*pfunc))) != sizeof(*pfunc)) {
|
||||||
dev_err(&adapter->dev, "failure reading functionality: %i\n", i);
|
dev_err(&adapter->dev, "failure reading functionality: %i\n", i);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = le32_to_cpup(pfunc);
|
ret = le32_to_cpup(pfunc);
|
||||||
//dev_warn(&adapter->dev, "itu func=%08x\n", ret);
|
//dev_warn(&adapter->dev, "itu func=%08x\n", ret);
|
||||||
out:
|
out:
|
||||||
kfree(pfunc);
|
kfree(pfunc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the actual algorithm we define */
|
/* This is the actual algorithm we define */
|
||||||
static const struct i2c_algorithm usb_algorithm = {
|
static const struct i2c_algorithm usb_algorithm = {
|
||||||
.master_xfer = usb_xfer,
|
.master_xfer = usb_xfer,
|
||||||
.functionality = usb_func,
|
.functionality = usb_func,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----- end of i2c layer ------------------------------------------------ */
|
/* ----- end of i2c layer ------------------------------------------------ */
|
||||||
|
@ -158,152 +158,152 @@ static const struct i2c_algorithm usb_algorithm = {
|
||||||
* bought from EZPrototypes
|
* bought from EZPrototypes
|
||||||
*/
|
*/
|
||||||
static const struct usb_device_id i2c_tiny_usb_table[] = {
|
static const struct usb_device_id i2c_tiny_usb_table[] = {
|
||||||
{ USB_DEVICE(0x0403, 0xc631) }, /* FTDI */
|
{ USB_DEVICE(0x0403, 0xc631) }, /* FTDI */
|
||||||
{ USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */
|
{ USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */
|
||||||
{ /* TinyUSB DapperMime: we want the Vendor interface on I2C-enabled ones */
|
{ /* TinyUSB DapperMime: we want the Vendor interface on I2C-enabled ones */
|
||||||
.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | USB_DEVICE_ID_MATCH_INT_CLASS,
|
.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | USB_DEVICE_ID_MATCH_INT_CLASS,
|
||||||
.idVendor = 0xcafe, .idProduct = 0x1312,
|
.idVendor = 0xcafe, .idProduct = 0x1312,
|
||||||
.bcdDevice_lo = 0x6000, .bcdDevice_hi = 0x6fff,
|
.bcdDevice_lo = 0x6000, .bcdDevice_hi = 0x6fff,
|
||||||
.bInterfaceClass = 0
|
.bInterfaceClass = 0
|
||||||
},
|
},
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(usb, i2c_tiny_usb_table);
|
MODULE_DEVICE_TABLE(usb, i2c_tiny_usb_table);
|
||||||
|
|
||||||
/* Structure to hold all of our device specific stuff */
|
/* Structure to hold all of our device specific stuff */
|
||||||
struct i2c_tiny_usb {
|
struct i2c_tiny_usb {
|
||||||
struct usb_device *usb_dev; /* the usb device for this device */
|
struct usb_device *usb_dev; /* the usb device for this device */
|
||||||
struct usb_interface *interface; /* the interface for this device */
|
struct usb_interface *interface; /* the interface for this device */
|
||||||
struct i2c_adapter adapter; /* i2c related things */
|
struct i2c_adapter adapter; /* i2c related things */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int usb_read(struct i2c_adapter *adapter, int cmd,
|
static int usb_read(struct i2c_adapter *adapter, int cmd,
|
||||||
int value, int index, void *data, int len)
|
int value, int index, void *data, int len)
|
||||||
{
|
{
|
||||||
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||||
uint8_t *dmadata;
|
uint8_t *dmadata;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dmadata = kmalloc(len, GFP_KERNEL);
|
dmadata = kmalloc(len, GFP_KERNEL);
|
||||||
|
|
||||||
if (!dmadata)
|
if (!dmadata)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* do control transfer */
|
/* do control transfer */
|
||||||
ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
|
ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
|
||||||
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_IN,
|
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||||
value, index, dmadata, len, 2000);
|
value, index, dmadata, len, 2000);
|
||||||
|
|
||||||
memcpy(data, dmadata, len);
|
memcpy(data, dmadata, len);
|
||||||
|
|
||||||
kfree(dmadata);
|
kfree(dmadata);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||||
int value, int index, void *data, int len)
|
int value, int index, void *data, int len)
|
||||||
{
|
{
|
||||||
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||||
uint8_t *dmadata;
|
uint8_t *dmadata;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dmadata = (uint8_t*)kmemdup(data, len, GFP_KERNEL);
|
dmadata = (uint8_t*)kmemdup(data, len, GFP_KERNEL);
|
||||||
if (!dmadata)
|
if (!dmadata)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* do control transfer */
|
/* do control transfer */
|
||||||
ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
|
ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
|
||||||
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
value, index, dmadata, len, 2000);
|
value, index, dmadata, len, 2000);
|
||||||
|
|
||||||
kfree(dmadata);
|
kfree(dmadata);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
|
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
|
||||||
{
|
{
|
||||||
usb_put_dev(dev->usb_dev);
|
usb_put_dev(dev->usb_dev);
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_tiny_usb_probe(struct usb_interface *interface,
|
static int i2c_tiny_usb_probe(struct usb_interface *interface,
|
||||||
const struct usb_device_id *id)
|
const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
struct i2c_tiny_usb *dev;
|
struct i2c_tiny_usb *dev;
|
||||||
int retval = -ENOMEM;
|
int retval = -ENOMEM;
|
||||||
u16 version;
|
u16 version;
|
||||||
|
|
||||||
dev_dbg(&interface->dev, "probing usb device\n");
|
dev_dbg(&interface->dev, "probing usb device\n");
|
||||||
|
|
||||||
/* allocate memory for our device state and initialize it */
|
/* allocate memory for our device state and initialize it */
|
||||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
dev_err(&interface->dev, "Out of memory\n");
|
dev_err(&interface->dev, "Out of memory\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
|
dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
|
||||||
dev->interface = interface;
|
dev->interface = interface;
|
||||||
|
|
||||||
/* save our data pointer in this interface device */
|
/* save our data pointer in this interface device */
|
||||||
usb_set_intfdata(interface, dev);
|
usb_set_intfdata(interface, dev);
|
||||||
|
|
||||||
version = le16_to_cpu(dev->usb_dev->descriptor.bcdDevice);
|
version = le16_to_cpu(dev->usb_dev->descriptor.bcdDevice);
|
||||||
dev_info(&interface->dev,
|
dev_info(&interface->dev,
|
||||||
"version %x.%02x found at bus %03d address %03d\n",
|
"version %x.%02x found at bus %03d address %03d\n",
|
||||||
version >> 8, version & 0xff,
|
version >> 8, version & 0xff,
|
||||||
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
|
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
|
||||||
|
|
||||||
/* setup i2c adapter description */
|
/* setup i2c adapter description */
|
||||||
dev->adapter.owner = THIS_MODULE;
|
dev->adapter.owner = THIS_MODULE;
|
||||||
dev->adapter.class = I2C_CLASS_HWMON;
|
dev->adapter.class = I2C_CLASS_HWMON;
|
||||||
dev->adapter.algo = &usb_algorithm;
|
dev->adapter.algo = &usb_algorithm;
|
||||||
dev->adapter.algo_data = dev;
|
dev->adapter.algo_data = dev;
|
||||||
snprintf(dev->adapter.name, sizeof(dev->adapter.name),
|
snprintf(dev->adapter.name, sizeof(dev->adapter.name),
|
||||||
"i2c-tiny-usb at bus %03d device %03d",
|
"i2c-tiny-usb at bus %03d device %03d",
|
||||||
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
|
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
|
||||||
|
|
||||||
if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) {
|
if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) {
|
||||||
dev_err(/*&dev->adapter.dev*/ &dev->usb_dev->dev, /* adapter.dev is null at this point */
|
dev_err(/*&dev->adapter.dev*/ &dev->usb_dev->dev, /* adapter.dev is null at this point */
|
||||||
"failure setting delay to %dus\n", delay);
|
"failure setting delay to %dus\n", delay);
|
||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->adapter.dev.parent = &dev->interface->dev;
|
dev->adapter.dev.parent = &dev->interface->dev;
|
||||||
|
|
||||||
/* and finally attach to i2c layer */
|
/* and finally attach to i2c layer */
|
||||||
i2c_add_adapter(&dev->adapter);
|
i2c_add_adapter(&dev->adapter);
|
||||||
|
|
||||||
/* inform user about successful attachment to i2c layer */
|
/* inform user about successful attachment to i2c layer */
|
||||||
dev_info(&dev->adapter.dev, "connected i2c-tiny-usb device\n");
|
dev_info(&dev->adapter.dev, "connected i2c-tiny-usb device\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (dev)
|
if (dev)
|
||||||
i2c_tiny_usb_free(dev);
|
i2c_tiny_usb_free(dev);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i2c_tiny_usb_disconnect(struct usb_interface *interface)
|
static void i2c_tiny_usb_disconnect(struct usb_interface *interface)
|
||||||
{
|
{
|
||||||
struct i2c_tiny_usb *dev = usb_get_intfdata(interface);
|
struct i2c_tiny_usb *dev = usb_get_intfdata(interface);
|
||||||
|
|
||||||
i2c_del_adapter(&dev->adapter);
|
i2c_del_adapter(&dev->adapter);
|
||||||
usb_set_intfdata(interface, NULL);
|
usb_set_intfdata(interface, NULL);
|
||||||
i2c_tiny_usb_free(dev);
|
i2c_tiny_usb_free(dev);
|
||||||
|
|
||||||
dev_dbg(&interface->dev, "disconnected\n");
|
dev_dbg(&interface->dev, "disconnected\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_driver i2c_tiny_usb_driver = {
|
static struct usb_driver i2c_tiny_usb_driver = {
|
||||||
.name = "i2c-tiny-usb",
|
.name = "i2c-tiny-usb",
|
||||||
.probe = i2c_tiny_usb_probe,
|
.probe = i2c_tiny_usb_probe,
|
||||||
.disconnect = i2c_tiny_usb_disconnect,
|
.disconnect = i2c_tiny_usb_disconnect,
|
||||||
.id_table = i2c_tiny_usb_table,
|
.id_table = i2c_tiny_usb_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_usb_driver(i2c_tiny_usb_driver);
|
module_usb_driver(i2c_tiny_usb_driver);
|
||||||
|
|
|
@ -23,19 +23,19 @@
|
||||||
// so leaving it here for now
|
// so leaving it here for now
|
||||||
|
|
||||||
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, // 40..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
|
||||||
};
|
};
|
||||||
static const char serprog_pgmname[16] = INFO_PRODUCT_BARE;
|
static const char serprog_pgmname[16] = INFO_PRODUCT_BARE;
|
||||||
|
|
||||||
|
@ -45,194 +45,194 @@ 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();
|
||||||
slen |= (uint32_t)read_byte() << 8;
|
slen |= (uint32_t)read_byte() << 8;
|
||||||
slen |= (uint32_t)read_byte() << 16;
|
slen |= (uint32_t)read_byte() << 16;
|
||||||
rlen = (uint32_t)read_byte();
|
rlen = (uint32_t)read_byte();
|
||||||
rlen |= (uint32_t)read_byte() << 8;
|
rlen |= (uint32_t)read_byte() << 8;
|
||||||
rlen |= (uint32_t)read_byte() << 16;
|
rlen |= (uint32_t)read_byte() << 16;
|
||||||
|
|
||||||
sp_spi_op_begin();
|
sp_spi_op_begin();
|
||||||
size_t this_batch;
|
size_t this_batch;
|
||||||
|
|
||||||
// 1. write slen data bytes
|
// 1. write slen data bytes
|
||||||
// we're going to use the tx buf for all operations here
|
// we're going to use the tx buf for all operations here
|
||||||
while (slen > 0) {
|
while (slen > 0) {
|
||||||
this_batch = sizeof(tx_buf);
|
this_batch = sizeof(tx_buf);
|
||||||
if (this_batch > slen) this_batch = slen;
|
if (this_batch > slen) this_batch = slen;
|
||||||
|
|
||||||
for (size_t i = 0; i < this_batch; ++i) tx_buf[i] = read_byte();
|
for (size_t i = 0; i < this_batch; ++i) tx_buf[i] = read_byte();
|
||||||
sp_spi_op_write(this_batch, tx_buf);
|
sp_spi_op_write(this_batch, tx_buf);
|
||||||
|
|
||||||
slen -= this_batch;
|
slen -= this_batch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. write data
|
// 2. write data
|
||||||
// first, do a batch of 63, because we also need to send an ACK byte
|
// first, do a batch of 63, because we also need to send an ACK byte
|
||||||
this_batch = sizeof(tx_buf)-1;
|
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]);
|
sp_spi_op_read(this_batch, &tx_buf[1]);
|
||||||
tx_buf[0] = S_ACK;
|
tx_buf[0] = S_ACK;
|
||||||
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch+1);
|
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch+1);
|
||||||
rlen -= this_batch;
|
rlen -= this_batch;
|
||||||
|
|
||||||
// now do in batches of 64
|
// now do in batches of 64
|
||||||
while (rlen > 0) {
|
while (rlen > 0) {
|
||||||
this_batch = sizeof(tx_buf);
|
this_batch = sizeof(tx_buf);
|
||||||
if (this_batch > rlen) this_batch = rlen;
|
if (this_batch > rlen) this_batch = rlen;
|
||||||
|
|
||||||
sp_spi_op_read(this_batch, tx_buf);
|
sp_spi_op_read(this_batch, tx_buf);
|
||||||
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch);
|
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch);
|
||||||
|
|
||||||
rlen -= this_batch;
|
rlen -= this_batch;
|
||||||
}
|
}
|
||||||
tud_cdc_n_write_flush(CDC_N_SERPROG);
|
tud_cdc_n_write_flush(CDC_N_SERPROG);
|
||||||
|
|
||||||
// that's it!
|
// that's it!
|
||||||
sp_spi_op_end();
|
sp_spi_op_end();
|
||||||
nresp = 0; // we sent our own response manually
|
nresp = 0; // we sent our own response manually
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case S_CMD_S_SPI_FREQ: {
|
case S_CMD_S_SPI_FREQ: {
|
||||||
uint32_t freq;
|
uint32_t freq;
|
||||||
freq = (uint32_t)read_byte();
|
freq = (uint32_t)read_byte();
|
||||||
freq |= (uint32_t)read_byte() << 8;
|
freq |= (uint32_t)read_byte() << 8;
|
||||||
freq |= (uint32_t)read_byte() << 16;
|
freq |= (uint32_t)read_byte() << 16;
|
||||||
freq |= (uint32_t)read_byte() << 24;
|
freq |= (uint32_t)read_byte() << 24;
|
||||||
|
|
||||||
uint32_t nfreq = sp_spi_set_freq(freq);
|
uint32_t nfreq = sp_spi_set_freq(freq);
|
||||||
tx_buf[0] = S_ACK;
|
tx_buf[0] = S_ACK;
|
||||||
tx_buf[1] = nfreq & 0xff;
|
tx_buf[1] = nfreq & 0xff;
|
||||||
tx_buf[2] = (nfreq >> 8) & 0xff;
|
tx_buf[2] = (nfreq >> 8) & 0xff;
|
||||||
tx_buf[3] = (nfreq >> 16) & 0xff;
|
tx_buf[3] = (nfreq >> 16) & 0xff;
|
||||||
tx_buf[4] = (nfreq >> 24) & 0xff;
|
tx_buf[4] = (nfreq >> 24) & 0xff;
|
||||||
nresp = 5;
|
nresp = 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case S_CMD_S_PINSTATE: {
|
case S_CMD_S_PINSTATE: {
|
||||||
if (read_byte() == 0) sp_spi_cs_deselect();
|
if (read_byte() == 0) sp_spi_cs_deselect();
|
||||||
else sp_spi_cs_select();
|
else sp_spi_cs_select();
|
||||||
|
|
||||||
tx_buf[0] = S_ACK;
|
tx_buf[0] = S_ACK;
|
||||||
nresp = 1;
|
nresp = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_CMD_MAGIC_SETTINGS: {
|
case S_CMD_MAGIC_SETTINGS: {
|
||||||
uint8_t a = read_byte();
|
uint8_t a = read_byte();
|
||||||
uint8_t b = read_byte();
|
uint8_t b = read_byte();
|
||||||
|
|
||||||
tx_buf[0] = S_ACK;
|
tx_buf[0] = S_ACK;
|
||||||
tx_buf[1] = rtconf_do(a, b);
|
tx_buf[1] = rtconf_do(a, b);
|
||||||
nresp = 2;
|
nresp = 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tx_buf[0] = S_NAK;
|
tx_buf[0] = S_NAK;
|
||||||
nresp = 1;
|
nresp = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nresp > 0) {
|
if (nresp > 0) {
|
||||||
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, nresp);
|
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, nresp);
|
||||||
tud_cdc_n_write_flush(CDC_N_SERPROG);
|
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 */
|
||||||
|
|
128
src/i2ctinyusb.h
128
src/i2ctinyusb.h
|
@ -9,87 +9,87 @@
|
||||||
#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_IDLE = 0,
|
||||||
ITU_STATUS_ADDR_ACK = 1,
|
ITU_STATUS_ADDR_ACK = 1,
|
||||||
ITU_STATUS_ADDR_NAK = 2
|
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_WORD_DATA | \
|
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
|
||||||
I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
|
I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
|
||||||
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC),
|
I2C_FUNC_SMBUS_I2C_BLOCK | 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_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
|
||||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL),
|
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
|
||||||
|
@ -98,9 +98,9 @@ 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, const uint8_t* buf, size_t len);
|
uint16_t addr, 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, uint8_t* buf, size_t len);
|
uint16_t addr, uint8_t* buf, size_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
364
src/main.c
364
src/main.c
|
@ -1,182 +1,182 @@
|
||||||
/*
|
/*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "tusb_config.h"
|
#include "tusb_config.h"
|
||||||
|
|
||||||
#include "bsp/board.h" /* a tinyusb header */
|
#include "bsp/board.h" /* a tinyusb header */
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
#include "DAP_config.h" /* ARM code *assumes* this is included prior to DAP.h */
|
#include "DAP_config.h" /* ARM code *assumes* this is included prior to DAP.h */
|
||||||
#include "DAP.h"
|
#include "DAP.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "protocfg.h"
|
#include "protocfg.h"
|
||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
#include "libco.h"
|
#include "libco.h"
|
||||||
|
|
||||||
#ifdef PICO_BOARD
|
#ifdef PICO_BOARD
|
||||||
#include <pico/binary_info.h>
|
#include <pico/binary_info.h>
|
||||||
/*#include <hardware/i2c.h>
|
/*#include <hardware/i2c.h>
|
||||||
#include "pinout.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();
|
thread_yield();
|
||||||
while (1) {
|
while (1) {
|
||||||
cdc_serprog_task();
|
cdc_serprog_task();
|
||||||
thread_yield();
|
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);
|
/*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));*/
|
||||||
#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;
|
/*uint8_t val = 0x12;
|
||||||
i2c_write_timeout_us(PINOUT_I2C_DEV, 0x13, &val, 1, false, 1000*1000);*/
|
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_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);
|
//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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// USB HID
|
// USB HID
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
// 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, uint8_t* buffer, uint16_t reqlen) {
|
hid_report_type_t report_type, 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, uint8_t const* RxDataBuffer, uint16_t bufsize) {
|
hid_report_type_t report_type, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
54
src/rtconf.c
54
src/rtconf.c
|
@ -8,52 +8,52 @@
|
||||||
#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
|
#endif
|
||||||
// always true
|
// always true
|
||||||
/*#ifdef DBOARD_HAS_SERPROG
|
/*#ifdef DBOARD_HAS_SERPROG
|
||||||
| 4
|
| 4
|
||||||
#endif*/
|
#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);
|
cdc_uart_set_hwflow(b != 0);
|
||||||
return 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) return rv;
|
||||||
else if (b == 0xff) tempsense_set_active(false);
|
else if (b == 0xff) tempsense_set_active(false);
|
||||||
else tempsense_set_addr(b);
|
else tempsense_set_addr(b);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case opt_get_implmap:
|
case opt_get_implmap:
|
||||||
return implmap_val;
|
return implmap_val;
|
||||||
default:
|
default:
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
src/rtconf.h
18
src/rtconf.h
|
@ -8,19 +8,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);
|
||||||
|
|
|
@ -3,35 +3,35 @@
|
||||||
#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_ACK = 0x06,
|
||||||
S_NAK = 0x15
|
S_NAK = 0x15
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERPROG_IFACE_VERSION 0x0001
|
#define SERPROG_IFACE_VERSION 0x0001
|
||||||
|
@ -46,11 +46,11 @@ 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 write_len, const uint8_t* write_data,
|
||||||
uint32_t read_len, uint8_t* read_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
|
||||||
|
|
|
@ -14,54 +14,54 @@ 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}; do_pkt(0x05, false, 0x18, 1, pk1);
|
||||||
uint8_t pk2[2]; do_pkt(0x06, true , 0x18, 2, pk2); pbuf(2, pk2);
|
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}; do_pkt(0x05, false, 0x18, 1, pk3);
|
||||||
uint8_t pk4[2]; do_pkt(0x06, true , 0x18, 2, pk4); pbuf(2, pk4);
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
308
src/tempsensor.c
308
src/tempsensor.c
|
@ -20,204 +20,204 @@ static size_t index;
|
||||||
static bool instartstop, hasreg;
|
static bool instartstop, hasreg;
|
||||||
|
|
||||||
enum regid {
|
enum regid {
|
||||||
cap = 0,
|
cap = 0,
|
||||||
config,
|
config,
|
||||||
t_upper,
|
t_upper,
|
||||||
t_lower,
|
t_lower,
|
||||||
t_crit,
|
t_crit,
|
||||||
t_a,
|
t_a,
|
||||||
manuf_id,
|
manuf_id,
|
||||||
dev_idrev,
|
dev_idrev,
|
||||||
reso
|
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) {
|
||||||
if (fix > 4095) fix = 4095;
|
if (fix > 4095) fix = 4095;
|
||||||
if (fix < -4096) fix = -4096;
|
if (fix < -4096) fix = -4096;
|
||||||
return fix;
|
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();
|
mcp9808.t_lower = tempsense_dev_get_lower();
|
||||||
mcp9808.t_upper = tempsense_dev_get_upper();
|
mcp9808.t_upper = tempsense_dev_get_upper();
|
||||||
mcp9808.t_crit = tempsense_dev_get_crit ();
|
mcp9808.t_crit = tempsense_dev_get_crit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
buf[index] = 0;
|
||||||
break;
|
break;
|
||||||
case config:
|
case config:
|
||||||
if (index == 0) buf[0] = (mcp9808.config >> 8) & 0xff;
|
if (index == 0) buf[0] = (mcp9808.config >> 8) & 0xff;
|
||||||
else if (index == 1) buf[1] = (mcp9808.config >> 0) & 0xff;
|
else if (index == 1) buf[1] = (mcp9808.config >> 0) & 0xff;
|
||||||
else return index;
|
else return index;
|
||||||
break;
|
break;
|
||||||
case t_upper:
|
case t_upper:
|
||||||
if (index == 0) buf[0] = (mcp9808.t_upper >> 8) & 0xff;
|
if (index == 0) buf[0] = (mcp9808.t_upper >> 8) & 0xff;
|
||||||
else if (index == 1) buf[1] = (mcp9808.t_upper >> 0) & 0xff;
|
else if (index == 1) buf[1] = (mcp9808.t_upper >> 0) & 0xff;
|
||||||
else return index;
|
else return index;
|
||||||
break;
|
break;
|
||||||
case t_lower:
|
case t_lower:
|
||||||
if (index == 0) buf[0] = (mcp9808.t_lower >> 8) & 0xff;
|
if (index == 0) buf[0] = (mcp9808.t_lower >> 8) & 0xff;
|
||||||
else if (index == 1) buf[1] = (mcp9808.t_lower >> 0) & 0xff;
|
else if (index == 1) buf[1] = (mcp9808.t_lower >> 0) & 0xff;
|
||||||
else return index;
|
else return index;
|
||||||
break;
|
break;
|
||||||
case t_crit:
|
case t_crit:
|
||||||
if (index == 0) buf[0] = (mcp9808.t_crit >> 8) & 0xff;
|
if (index == 0) buf[0] = (mcp9808.t_crit >> 8) & 0xff;
|
||||||
else if (index == 1) buf[1] = (mcp9808.t_crit >> 0) & 0xff;
|
else if (index == 1) buf[1] = (mcp9808.t_crit >> 0) & 0xff;
|
||||||
else return index;
|
else return index;
|
||||||
break;
|
break;
|
||||||
case t_a: {
|
case t_a: {
|
||||||
static uint16_t temp;
|
static uint16_t temp;
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
int16_t res = tempsense_dev_get_temp();
|
int16_t res = tempsense_dev_get_temp();
|
||||||
|
|
||||||
uint32_t tup = mcp9808.t_upper & 0x1ffc;
|
uint32_t tup = mcp9808.t_upper & 0x1ffc;
|
||||||
if (tup & 0x1000) tup |= 0xffffe000; // make negative
|
if (tup & 0x1000) tup |= 0xffffe000; // make negative
|
||||||
uint32_t tlo = mcp9808.t_lower & 0x1ffc;
|
uint32_t tlo = mcp9808.t_lower & 0x1ffc;
|
||||||
if (tlo & 0x1000) tlo |= 0xffffe000; // make negative
|
if (tlo & 0x1000) tlo |= 0xffffe000; // make negative
|
||||||
uint32_t tcr = mcp9808.t_crit & 0x1ffc;
|
uint32_t tcr = mcp9808.t_crit & 0x1ffc;
|
||||||
if (tcr & 0x1000) tcr |= 0xffffe000; // make negative
|
if (tcr & 0x1000) tcr |= 0xffffe000; // make negative
|
||||||
|
|
||||||
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) buf[1] = (temp>>0) & 0xff;
|
||||||
else return index;
|
else return index;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case manuf_id:
|
case manuf_id:
|
||||||
if (index == 0) buf[0] = (MANUF_ID >> 8) & 0xff;
|
if (index == 0) buf[0] = (MANUF_ID >> 8) & 0xff;
|
||||||
else if (index == 1) buf[1] = (MANUF_ID>>0)&0xff;
|
else if (index == 1) buf[1] = (MANUF_ID>>0)&0xff;
|
||||||
else return index;
|
else return index;
|
||||||
break;
|
break;
|
||||||
case dev_idrev:
|
case dev_idrev:
|
||||||
if (index == 0) buf[0] = (DEV_IDREV >> 8) & 0xff;
|
if (index == 0) buf[0] = (DEV_IDREV >> 8) & 0xff;
|
||||||
else if (index == 1) buf[1] = (DEV_IDREV>>0)&0xff;
|
else if (index == 1) buf[1] = (DEV_IDREV>>0)&0xff;
|
||||||
else return index;
|
else return index;
|
||||||
break;
|
break;
|
||||||
case reso:
|
case reso:
|
||||||
if (index == 0) buf[0] = mcp9808.reso;
|
if (index == 0) buf[0] = mcp9808.reso;
|
||||||
else return index;
|
else return index;
|
||||||
break;
|
break;
|
||||||
default: return -1;
|
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 return index;
|
||||||
break;
|
break;
|
||||||
case t_upper:
|
case t_upper:
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
mcp9808.t_upper = (mcp9808.t_upper & 0x00ff) | ((uint16_t)buf[0] << 8);
|
mcp9808.t_upper = (mcp9808.t_upper & 0x00ff) | ((uint16_t)buf[0] << 8);
|
||||||
} else if (index == 1) {
|
} else if (index == 1) {
|
||||||
mcp9808.t_upper = (mcp9808.t_upper & 0xff00) | ((uint16_t)buf[1] << 0);
|
mcp9808.t_upper = (mcp9808.t_upper & 0xff00) | ((uint16_t)buf[1] << 0);
|
||||||
} else return index;
|
} else return index;
|
||||||
break;
|
break;
|
||||||
case t_lower:
|
case t_lower:
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
mcp9808.t_lower = (mcp9808.t_lower & 0x00ff) | ((uint16_t)buf[0] << 8);
|
mcp9808.t_lower = (mcp9808.t_lower & 0x00ff) | ((uint16_t)buf[0] << 8);
|
||||||
} else if (index == 1) {
|
} else if (index == 1) {
|
||||||
mcp9808.t_lower = (mcp9808.t_lower & 0xff00) | ((uint16_t)buf[1] << 0);
|
mcp9808.t_lower = (mcp9808.t_lower & 0xff00) | ((uint16_t)buf[1] << 0);
|
||||||
} else return index;
|
} else return index;
|
||||||
break;
|
break;
|
||||||
case t_crit:
|
case t_crit:
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
mcp9808.t_crit = (mcp9808.t_crit & 0x00ff) | ((uint16_t)buf[0] << 8);
|
mcp9808.t_crit = (mcp9808.t_crit & 0x00ff) | ((uint16_t)buf[0] << 8);
|
||||||
} else if (index == 1) {
|
} else if (index == 1) {
|
||||||
mcp9808.t_crit = (mcp9808.t_crit & 0xff00) | ((uint16_t)buf[1] << 0);
|
mcp9808.t_crit = (mcp9808.t_crit & 0xff00) | ((uint16_t)buf[1] << 0);
|
||||||
} else return index;
|
} else return index;
|
||||||
break;
|
break;
|
||||||
case reso:
|
case reso:
|
||||||
mcp9808.reso = buf[index];
|
mcp9808.reso = buf[index];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("unk reg\n");
|
printf("unk reg\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,118 +1,118 @@
|
||||||
/*
|
/*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TUSB_CONFIG_H__
|
#ifndef _TUSB_CONFIG_H__
|
||||||
#define _TUSB_CONFIG_H__
|
#define _TUSB_CONFIG_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "protocfg.h"
|
#include "protocfg.h"
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// COMMON CONFIGURATION
|
// COMMON CONFIGURATION
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
// 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_MIMXRT10XX || \
|
||||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
|
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
|
||||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
||||||
#else
|
#else
|
||||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||||
#endif
|
#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
|
||||||
// #define CFG_TUSB_DEBUG 0
|
// #define CFG_TUSB_DEBUG 0
|
||||||
|
|
||||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||||
* into those specific section.
|
* into those specific section.
|
||||||
* e.g
|
* e.g
|
||||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
||||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
||||||
*/
|
*/
|
||||||
#ifndef CFG_TUSB_MEM_SECTION
|
#ifndef CFG_TUSB_MEM_SECTION
|
||||||
#define CFG_TUSB_MEM_SECTION
|
#define CFG_TUSB_MEM_SECTION
|
||||||
#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
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// DEVICE CONFIGURATION
|
// DEVICE CONFIGURATION
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
#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_ */
|
||||||
|
|
|
@ -1,260 +1,260 @@
|
||||||
/*
|
/*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "protos.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 the first plug.
|
||||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
* 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]
|
||||||
*/
|
*/
|
||||||
#ifdef DBOARD_HAS_I2C
|
#ifdef DBOARD_HAS_I2C
|
||||||
#define USB_BCD_BASE 0x6000
|
#define USB_BCD_BASE 0x6000
|
||||||
#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 (USB_BCD_BASE | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 3) | _PID_MAP(HID, 6) | \
|
||||||
_PID_MAP(MIDI, 9) | _PID_MAP(VENDOR, 12) ) \
|
_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
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
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)
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Configuration Descriptor
|
// Configuration Descriptor
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EPNUM_CDC_UART_OUT 0x02
|
#define EPNUM_CDC_UART_OUT 0x02
|
||||||
#define EPNUM_CDC_UART_IN 0x82
|
#define EPNUM_CDC_UART_IN 0x82
|
||||||
#define EPNUM_CDC_UART_NOTIF 0x83
|
#define EPNUM_CDC_UART_NOTIF 0x83
|
||||||
#define EPNUM_HID_CMSISDAP 0x04
|
#define EPNUM_HID_CMSISDAP 0x04
|
||||||
#define EPNUM_CDC_SERPROG_OUT 0x05
|
#define EPNUM_CDC_SERPROG_OUT 0x05
|
||||||
#define EPNUM_CDC_SERPROG_IN 0x85
|
#define EPNUM_CDC_SERPROG_IN 0x85
|
||||||
#define EPNUM_CDC_SERPROG_NOTIF 0x86
|
#define EPNUM_CDC_SERPROG_NOTIF 0x86
|
||||||
#define EPNUM_CDC_STDIO_OUT 0x07
|
#define EPNUM_CDC_STDIO_OUT 0x07
|
||||||
#define EPNUM_CDC_STDIO_IN 0x87
|
#define EPNUM_CDC_STDIO_IN 0x87
|
||||||
#define EPNUM_CDC_STDIO_NOTIF 0x88
|
#define EPNUM_CDC_STDIO_NOTIF 0x88
|
||||||
|
|
||||||
// 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
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// String Descriptors
|
// String Descriptors
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
// array of pointer to string descriptors
|
// array of pointer to string descriptors
|
||||||
char const* string_desc_arr [] = {
|
char const* string_desc_arr [] = {
|
||||||
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
|
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
|
||||||
[STRID_MANUFACTURER] = INFO_MANUFACTURER, // Manufacturer
|
[STRID_MANUFACTURER] = INFO_MANUFACTURER, // Manufacturer
|
||||||
[STRID_PRODUCT] = INFO_PRODUCT(INFO_BOARDNAME), // Product
|
[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)",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#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) return '0'+(x-0);
|
||||||
else return 'A'+(x-0xa);
|
else return 'A'+(x-0xa);
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_yield(void);
|
void thread_yield(void);
|
||||||
|
|
|
@ -28,214 +28,214 @@ 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) {
|
||||||
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) {
|
||||||
TU_VERIFY(itf_desc->bInterfaceClass == 0
|
TU_VERIFY(itf_desc->bInterfaceClass == 0
|
||||||
&& itf_desc->bInterfaceSubClass == 0
|
&& itf_desc->bInterfaceSubClass == 0
|
||||||
&& itf_desc->bInterfaceProtocol == 0, 0);
|
&& itf_desc->bInterfaceProtocol == 0, 0);
|
||||||
|
|
||||||
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) {
|
||||||
/*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.len == req->wLength) {
|
&& cmd.addr == req->wIndex && 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) status = ITU_STATUS_ADDR_NAK;
|
||||||
else status = ITU_STATUS_ADDR_ACK;
|
else status = ITU_STATUS_ADDR_ACK;
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
|
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
|
||||||
} else
|
} 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.len > sizeof rxbuf ? sizeof rxbuf : cmd.len);
|
cmd.addr, rxbuf, 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
|
if (req->wLength != 2) return false; // bad length -> let's stall
|
||||||
|
|
||||||
uint8_t rv[2];
|
uint8_t rv[2];
|
||||||
rv[0] = req->wValue&0xff;
|
rv[0] = req->wValue&0xff;
|
||||||
rv[1] = (req->wValue>>8)&0xff;
|
rv[1] = (req->wValue>>8)&0xff;
|
||||||
return tud_control_xfer(rhport, req, rv, sizeof rv);
|
return tud_control_xfer(rhport, req, rv, sizeof rv);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ITU_CMD_GET_FUNC: { // flags unused, addr unused, len=4
|
case ITU_CMD_GET_FUNC: { // flags unused, addr unused, len=4
|
||||||
if (req->wLength != 4) return false;
|
if (req->wLength != 4) return false;
|
||||||
|
|
||||||
const uint32_t func = i2ctu_get_func();
|
const uint32_t func = i2ctu_get_func();
|
||||||
txbuf[0]=func&0xff;
|
txbuf[0]=func&0xff;
|
||||||
txbuf[1]=(func>>8)&0xff;
|
txbuf[1]=(func>>8)&0xff;
|
||||||
txbuf[2]=(func>>16)&0xff;
|
txbuf[2]=(func>>16)&0xff;
|
||||||
txbuf[3]=(func>>24)&0xff;
|
txbuf[3]=(func>>24)&0xff;
|
||||||
return tud_control_xfer(rhport, req, txbuf, 4);
|
return tud_control_xfer(rhport, req, txbuf, 4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ITU_CMD_SET_DELAY: { // flags=delay, addr unused, len=0
|
case ITU_CMD_SET_DELAY: { // flags=delay, addr unused, len=0
|
||||||
if (req->wLength != 0) return false;
|
if (req->wLength != 0) return false;
|
||||||
|
|
||||||
uint32_t us = req->wValue ? req->wValue : 1;
|
uint32_t us = req->wValue ? req->wValue : 1;
|
||||||
uint32_t freq = 1000*1000 / us;
|
uint32_t freq = 1000*1000 / us;
|
||||||
|
|
||||||
//printf("set freq us=%u freq=%u\n", us, freq);
|
//printf("set freq us=%u freq=%u\n", us, freq);
|
||||||
if (i2ctu_set_freq(freq, us) != 0) // returned an ok frequency
|
if (i2ctu_set_freq(freq, us) != 0) // returned an ok frequency
|
||||||
return tud_control_status(rhport, req);
|
return tud_control_status(rhport, req);
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ITU_CMD_GET_STATUS: { // flags unused, addr unused, len=1
|
case ITU_CMD_GET_STATUS: { // flags unused, addr unused, len=1
|
||||||
if (req->wLength != 1) return false;
|
if (req->wLength != 1) return false;
|
||||||
|
|
||||||
uint8_t rv = status;
|
uint8_t rv = status;
|
||||||
return tud_control_xfer(rhport, req, &rv, 1);
|
return tud_control_xfer(rhport, req, &rv, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ITU_CMD_I2C_IO: // flags: ki2c_flags
|
case ITU_CMD_I2C_IO: // flags: ki2c_flags
|
||||||
case ITU_CMD_I2C_IO_BEGIN: // addr: I2C address
|
case ITU_CMD_I2C_IO_BEGIN: // addr: I2C address
|
||||||
case ITU_CMD_I2C_IO_END: // len: transfer size
|
case ITU_CMD_I2C_IO_END: // len: transfer size
|
||||||
case ITU_CMD_I2C_IO_BEGINEND: { // (transfer dir is in flags)
|
case ITU_CMD_I2C_IO_BEGINEND: { // (transfer dir is in flags)
|
||||||
struct itu_cmd cmd;
|
struct itu_cmd cmd;
|
||||||
cmd.flags = req->wValue;
|
cmd.flags = req->wValue;
|
||||||
cmd.addr = req->wIndex;
|
cmd.addr = req->wIndex;
|
||||||
cmd.len = req->wLength;
|
cmd.len = req->wLength;
|
||||||
cmd.cmd = req->bRequest;
|
cmd.cmd = req->bRequest;
|
||||||
|
|
||||||
if (cmd.flags & I2C_M_RD) { // read from I2C device
|
if (cmd.flags & I2C_M_RD) { // read from I2C device
|
||||||
//printf("read addr=%04hx len=%04hx ", cmd.addr, cmd.len);
|
//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(cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len, txbuf);
|
||||||
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
|
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
|
||||||
else status = ITU_STATUS_ADDR_ACK;
|
else status = ITU_STATUS_ADDR_ACK;
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
|
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
|
||||||
} else
|
} 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, txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
|
cmd.addr, 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(rhport, req, txbuf,
|
||||||
cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
|
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) status = ITU_STATUS_ADDR_NAK;
|
||||||
else status = ITU_STATUS_ADDR_ACK;
|
else status = ITU_STATUS_ADDR_ACK;
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
|
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
|
||||||
} else
|
} 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 return true; // other stage...
|
} else 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(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// interfacing stuff for TinyUSB API, actually defines the driver
|
// interfacing stuff for TinyUSB API, actually defines the driver
|
||||||
|
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
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(uint8_t rhport, uint8_t ep_addr, tusb_control_request_t const* req) {
|
||||||
return iub_ctl_req(rhport, ep_addr, req);
|
return iub_ctl_req(rhport, ep_addr, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DBOARD_HAS_I2C */
|
#endif /* DBOARD_HAS_I2C */
|
||||||
|
|
Loading…
Reference in New Issue