Added RP2040 support
This commit is contained in:
parent
a720420a78
commit
83f02325ed
242
platform/rp2040/dap_config.h
Normal file
242
platform/rp2040/dap_config.h
Normal file
@ -0,0 +1,242 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _DAP_CONFIG_H_
|
||||
#define _DAP_CONFIG_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include "rp2040.h"
|
||||
#include "hal_config.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define DAP_CONFIG_ENABLE_JTAG
|
||||
|
||||
#define DAP_CONFIG_DEFAULT_PORT DAP_PORT_SWD
|
||||
#define DAP_CONFIG_DEFAULT_CLOCK 1000000 // Hz
|
||||
|
||||
#define DAP_CONFIG_PACKET_SIZE 64
|
||||
#define DAP_CONFIG_PACKET_COUNT 1
|
||||
|
||||
#define DAP_CONFIG_JTAG_DEV_COUNT 8
|
||||
|
||||
// Set the value to NULL if you want to disable a string
|
||||
// DAP_CONFIG_PRODUCT_STR must contain "CMSIS-DAP" to be compatible with the standard
|
||||
#define DAP_CONFIG_VENDOR_STR "Alex Taradov"
|
||||
#define DAP_CONFIG_PRODUCT_STR "Generic CMSIS-DAP Adapter"
|
||||
#define DAP_CONFIG_SER_NUM_STR usb_serial_number
|
||||
#define DAP_CONFIG_FW_VER_STR "v1.0"
|
||||
#define DAP_CONFIG_DEVICE_VENDOR_STR NULL
|
||||
#define DAP_CONFIG_DEVICE_NAME_STR NULL
|
||||
|
||||
//#define DAP_CONFIG_RESET_TARGET_FN target_specific_reset_function
|
||||
//#define DAP_CONFIG_VENDOR_FN vendor_command_handler_function
|
||||
|
||||
// Attribute to use for performance-critical functions
|
||||
#define DAP_CONFIG_PERFORMANCE_ATTR
|
||||
|
||||
// A value at which dap_clock_test() produces 1 kHz output on the SWCLK pin
|
||||
#define DAP_CONFIG_DELAY_CONSTANT 20000
|
||||
|
||||
// A threshold for switching to fast clock (no added delays)
|
||||
// This is the frequency produced by dap_clock_test(1) on the SWCLK pin
|
||||
#define DAP_CONFIG_FAST_CLOCK 8550000 // Hz
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
extern char usb_serial_number[16];
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWCLK_TCK_write(int value)
|
||||
{
|
||||
HAL_GPIO_SWCLK_TCK_write(value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWDIO_TMS_write(int value)
|
||||
{
|
||||
HAL_GPIO_SWDIO_TMS_write(value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_TDI_write(int value)
|
||||
{
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
HAL_GPIO_TDI_write(value);
|
||||
#else
|
||||
(void)value;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_TDO_write(int value)
|
||||
{
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
HAL_GPIO_TDO_write(value);
|
||||
#else
|
||||
(void)value;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_nTRST_write(int value)
|
||||
{
|
||||
(void)value;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_nRESET_write(int value)
|
||||
{
|
||||
HAL_GPIO_nRESET_write(value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_SWCLK_TCK_read(void)
|
||||
{
|
||||
return HAL_GPIO_SWCLK_TCK_read();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_SWDIO_TMS_read(void)
|
||||
{
|
||||
return HAL_GPIO_SWDIO_TMS_read();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_TDO_read(void)
|
||||
{
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
return HAL_GPIO_TDO_read();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_TDI_read(void)
|
||||
{
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
return HAL_GPIO_TDI_read();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_nTRST_read(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_nRESET_read(void)
|
||||
{
|
||||
return HAL_GPIO_nRESET_read();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWCLK_TCK_set(void)
|
||||
{
|
||||
HAL_GPIO_SWCLK_TCK_set();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWCLK_TCK_clr(void)
|
||||
{
|
||||
HAL_GPIO_SWCLK_TCK_clr();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWDIO_TMS_in(void)
|
||||
{
|
||||
HAL_GPIO_SWDIO_TMS_in();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWDIO_TMS_out(void)
|
||||
{
|
||||
HAL_GPIO_SWDIO_TMS_out();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SETUP(void)
|
||||
{
|
||||
HAL_GPIO_SWCLK_TCK_in();
|
||||
HAL_GPIO_SWDIO_TMS_in();
|
||||
HAL_GPIO_nRESET_in();
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
HAL_GPIO_TDO_in();
|
||||
HAL_GPIO_TDI_in();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_DISCONNECT(void)
|
||||
{
|
||||
HAL_GPIO_SWCLK_TCK_in();
|
||||
HAL_GPIO_SWDIO_TMS_in();
|
||||
HAL_GPIO_nRESET_in();
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
HAL_GPIO_TDO_in();
|
||||
HAL_GPIO_TDI_in();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_CONNECT_SWD(void)
|
||||
{
|
||||
HAL_GPIO_SWDIO_TMS_out();
|
||||
HAL_GPIO_SWDIO_TMS_set();
|
||||
|
||||
HAL_GPIO_SWCLK_TCK_out();
|
||||
HAL_GPIO_SWCLK_TCK_set();
|
||||
|
||||
HAL_GPIO_nRESET_out();
|
||||
HAL_GPIO_nRESET_set();
|
||||
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
HAL_GPIO_TDO_in();
|
||||
HAL_GPIO_TDI_in();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_CONNECT_JTAG(void)
|
||||
{
|
||||
HAL_GPIO_SWDIO_TMS_out();
|
||||
HAL_GPIO_SWDIO_TMS_set();
|
||||
|
||||
HAL_GPIO_SWCLK_TCK_out();
|
||||
HAL_GPIO_SWCLK_TCK_set();
|
||||
|
||||
HAL_GPIO_nRESET_out();
|
||||
HAL_GPIO_nRESET_set();
|
||||
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
HAL_GPIO_TDO_in();
|
||||
|
||||
HAL_GPIO_TDI_out();
|
||||
HAL_GPIO_TDI_set();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_LED(int index, int state)
|
||||
{
|
||||
(void)index;
|
||||
(void)state;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__attribute__((always_inline))
|
||||
static inline void DAP_CONFIG_DELAY(uint32_t cycles)
|
||||
{
|
||||
asm volatile (
|
||||
"1: sub %[cycles], %[cycles], #1 \n"
|
||||
" bne 1b \n"
|
||||
: [cycles] "+l"(cycles)
|
||||
);
|
||||
}
|
||||
|
||||
#endif // _DAP_CONFIG_H_
|
||||
|
||||
31
platform/rp2040/hal_config.h
Normal file
31
platform/rp2040/hal_config.h
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _HAL_CONFIG_H_
|
||||
#define _HAL_CONFIG_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include "hal_gpio.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
HAL_GPIO_PIN(SWCLK_TCK, 0, 11, sio_11)
|
||||
HAL_GPIO_PIN(SWDIO_TMS, 0, 12, sio_12)
|
||||
HAL_GPIO_PIN(TDI, 0, 13, sio_13)
|
||||
HAL_GPIO_PIN(TDO, 0, 14, sio_14)
|
||||
HAL_GPIO_PIN(nRESET, 0, 15, sio_15)
|
||||
|
||||
HAL_GPIO_PIN(VCP_STATUS, 0, 6, sio_6);
|
||||
HAL_GPIO_PIN(DAP_STATUS, 0, 7, sio_7);
|
||||
|
||||
HAL_GPIO_PIN(UART_TX, 0, 0, uart0_tx)
|
||||
HAL_GPIO_PIN(UART_RX, 0, 1, uart0_rx)
|
||||
|
||||
#define UART_PER UART0
|
||||
#define UART_RESET_MASK RESETS_RESET_uart0_Msk
|
||||
#define UART_IRQ_INDEX UART0_IRQ_IRQn
|
||||
#define UART_IRQ_HANDLER irq_handler_uart0
|
||||
#define UART_CLOCK 120000000
|
||||
|
||||
#endif // _HAL_CONFIG_H_
|
||||
|
||||
|
||||
85
platform/rp2040/hal_gpio.h
Normal file
85
platform/rp2040/hal_gpio.h
Normal file
@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2021, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _HAL_GPIO_H_
|
||||
#define _HAL_GPIO_H_
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define HAL_GPIO_PIN(name, port, pin, func) \
|
||||
static inline void HAL_GPIO_##name##_set(void) \
|
||||
{ \
|
||||
SIO->GPIO_OUT_SET = (1 << pin); \
|
||||
(void)HAL_GPIO_##name##_set; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_clr(void) \
|
||||
{ \
|
||||
SIO->GPIO_OUT_CLR = (1 << pin); \
|
||||
(void)HAL_GPIO_##name##_clr; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_toggle(void) \
|
||||
{ \
|
||||
SIO->GPIO_OUT_XOR = (1 << pin); \
|
||||
(void)HAL_GPIO_##name##_toggle; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_write(int value) \
|
||||
{ \
|
||||
if (value) \
|
||||
SIO->GPIO_OUT_SET = (1 << pin); \
|
||||
else \
|
||||
SIO->GPIO_OUT_CLR = (1 << pin); \
|
||||
(void)HAL_GPIO_##name##_write; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_in(void) \
|
||||
{ \
|
||||
SIO->GPIO_OE_CLR = (1 << pin); \
|
||||
IO_BANK##port->GPIO##pin##_CTRL = IO_BANK##port##_GPIO##pin##_CTRL_FUNCSEL_sio_##pin; \
|
||||
PADS_BANK##port##_CLR->GPIO##pin = PADS_BANK##port##_GPIO##pin##_PDE_Msk | PADS_BANK##port##_GPIO##pin##_PUE_Msk; \
|
||||
PADS_BANK##port##_SET->GPIO##pin = PADS_BANK##port##_GPIO##pin##_IE_Msk; \
|
||||
(void)HAL_GPIO_##name##_in; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_out(void) \
|
||||
{ \
|
||||
SIO->GPIO_OE_SET = (1 << pin); \
|
||||
IO_BANK##port->GPIO##pin##_CTRL = IO_BANK##port##_GPIO##pin##_CTRL_FUNCSEL_sio_##pin; \
|
||||
(void)HAL_GPIO_##name##_out; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_init(void) \
|
||||
{ \
|
||||
IO_BANK##port->GPIO##pin##_CTRL = IO_BANK##port##_GPIO##pin##_CTRL_FUNCSEL_##func; \
|
||||
(void)HAL_GPIO_##name##_init; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_pullup(void) \
|
||||
{ \
|
||||
PADS_BANK##port##_SET->GPIO##pin = PADS_BANK##port##_GPIO##pin##_PUE_Msk; \
|
||||
PADS_BANK##port##_CLR->GPIO##pin = PADS_BANK##port##_GPIO##pin##_PDE_Msk; \
|
||||
(void)HAL_GPIO_##name##_pullup; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_pulldown(void) \
|
||||
{ \
|
||||
PADS_BANK##port##_SET->GPIO##pin = PADS_BANK##port##_GPIO##pin##_PDE_Msk; \
|
||||
PADS_BANK##port##_CLR->GPIO##pin = PADS_BANK##port##_GPIO##pin##_PUE_Msk; \
|
||||
(void)HAL_GPIO_##name##_pulldown; \
|
||||
} \
|
||||
\
|
||||
static inline int HAL_GPIO_##name##_read(void) \
|
||||
{ \
|
||||
return (SIO->GPIO_IN & (1 << pin)) != 0; \
|
||||
(void)HAL_GPIO_##name##_read; \
|
||||
} \
|
||||
\
|
||||
static inline void HAL_GPIO_##name##_funcsel(int fn) \
|
||||
{ \
|
||||
IO_BANK##port->GPIO##pin##_CTRL_b.FUNCSEL = fn; \
|
||||
(void)HAL_GPIO_##name##_funcsel; \
|
||||
} \
|
||||
|
||||
#endif // _HAL_GPIO_H_
|
||||
|
||||
283
platform/rp2040/include/cmsis_compiler.h
Normal file
283
platform/rp2040/include/cmsis_compiler.h
Normal file
@ -0,0 +1,283 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_compiler.h
|
||||
* @brief CMSIS compiler generic header file
|
||||
* @version V5.1.0
|
||||
* @date 09. October 2018
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __CMSIS_COMPILER_H
|
||||
#define __CMSIS_COMPILER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Arm Compiler 4/5
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
|
||||
/*
|
||||
* Arm Compiler 6.6 LTM (armclang)
|
||||
*/
|
||||
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
|
||||
#include "cmsis_armclang_ltm.h"
|
||||
|
||||
/*
|
||||
* Arm Compiler above 6.10.1 (armclang)
|
||||
*/
|
||||
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
|
||||
#include "cmsis_armclang.h"
|
||||
|
||||
|
||||
/*
|
||||
* GNU Compiler
|
||||
*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
|
||||
/*
|
||||
* IAR Compiler
|
||||
*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iccarm.h>
|
||||
|
||||
|
||||
/*
|
||||
* TI Arm Compiler
|
||||
*/
|
||||
#elif defined ( __TI_ARM__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
#define __NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT struct __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION union __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#define __RESTRICT __restrict
|
||||
#endif
|
||||
#ifndef __COMPILER_BARRIER
|
||||
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||
#define __COMPILER_BARRIER() (void)0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* TASKING Compiler
|
||||
*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
#define __NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __packed__
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT struct __packed__
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION union __packed__
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
struct __packed__ T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __align(x)
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||
#define __RESTRICT
|
||||
#endif
|
||||
#ifndef __COMPILER_BARRIER
|
||||
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||
#define __COMPILER_BARRIER() (void)0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* COSMIC Compiler
|
||||
*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM _asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
// NO RETURN is automatically detected hence no warning here
|
||||
#define __NO_RETURN
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#warning No compiler specific solution for __USED. __USED is ignored.
|
||||
#define __USED
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __weak
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED @packed
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT @packed struct
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION @packed union
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
@packed struct T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
|
||||
#define __ALIGNED(x)
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||
#define __RESTRICT
|
||||
#endif
|
||||
#ifndef __COMPILER_BARRIER
|
||||
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||
#define __COMPILER_BARRIER() (void)0
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
#error Unknown compiler.
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __CMSIS_COMPILER_H */
|
||||
|
||||
2211
platform/rp2040/include/cmsis_gcc.h
Normal file
2211
platform/rp2040/include/cmsis_gcc.h
Normal file
File diff suppressed because it is too large
Load Diff
39
platform/rp2040/include/cmsis_version.h
Normal file
39
platform/rp2040/include/cmsis_version.h
Normal file
@ -0,0 +1,39 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_version.h
|
||||
* @brief CMSIS Core(M) Version definitions
|
||||
* @version V5.0.4
|
||||
* @date 23. July 2019
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2009-2019 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined (__clang__)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CMSIS_VERSION_H
|
||||
#define __CMSIS_VERSION_H
|
||||
|
||||
/* CMSIS Version definitions */
|
||||
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
|
||||
#define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */
|
||||
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
|
||||
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
|
||||
#endif
|
||||
1087
platform/rp2040/include/core_cm0plus.h
Normal file
1087
platform/rp2040/include/core_cm0plus.h
Normal file
File diff suppressed because it is too large
Load Diff
275
platform/rp2040/include/mpu_armv7.h
Normal file
275
platform/rp2040/include/mpu_armv7.h
Normal file
@ -0,0 +1,275 @@
|
||||
/******************************************************************************
|
||||
* @file mpu_armv7.h
|
||||
* @brief CMSIS MPU API for Armv7-M MPU
|
||||
* @version V5.1.2
|
||||
* @date 25. May 2020
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2017-2020 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined (__clang__)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef ARM_MPU_ARMV7_H
|
||||
#define ARM_MPU_ARMV7_H
|
||||
|
||||
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
|
||||
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
|
||||
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
|
||||
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
|
||||
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
|
||||
|
||||
#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
|
||||
#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
|
||||
#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
|
||||
#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
|
||||
#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
|
||||
#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
|
||||
|
||||
/** MPU Region Base Address Register Value
|
||||
*
|
||||
* \param Region The region to be configured, number 0 to 15.
|
||||
* \param BaseAddress The base address for the region.
|
||||
*/
|
||||
#define ARM_MPU_RBAR(Region, BaseAddress) \
|
||||
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
|
||||
((Region) & MPU_RBAR_REGION_Msk) | \
|
||||
(MPU_RBAR_VALID_Msk))
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attributes
|
||||
*
|
||||
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
|
||||
* \param IsShareable Region is shareable between multiple bus masters.
|
||||
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
|
||||
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
|
||||
((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
|
||||
(((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
|
||||
(((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
|
||||
(((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
|
||||
|
||||
/**
|
||||
* MPU Region Attribute and Size Register Value
|
||||
*
|
||||
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
|
||||
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
|
||||
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
|
||||
* \param SubRegionDisable Sub-region disable field.
|
||||
* \param Size Region size of the region to be configured, for example 4K, 8K.
|
||||
*/
|
||||
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
|
||||
((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
|
||||
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
|
||||
(((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
|
||||
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
|
||||
(((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
|
||||
(((MPU_RASR_ENABLE_Msk))))
|
||||
|
||||
/**
|
||||
* MPU Region Attribute and Size Register Value
|
||||
*
|
||||
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
|
||||
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
|
||||
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
|
||||
* \param IsShareable Region is shareable between multiple bus masters.
|
||||
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
|
||||
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
|
||||
* \param SubRegionDisable Sub-region disable field.
|
||||
* \param Size Region size of the region to be configured, for example 4K, 8K.
|
||||
*/
|
||||
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
|
||||
ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute for strongly ordered memory.
|
||||
* - TEX: 000b
|
||||
* - Shareable
|
||||
* - Non-cacheable
|
||||
* - Non-bufferable
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute for device memory.
|
||||
* - TEX: 000b (if shareable) or 010b (if non-shareable)
|
||||
* - Shareable or non-shareable
|
||||
* - Non-cacheable
|
||||
* - Bufferable (if shareable) or non-bufferable (if non-shareable)
|
||||
*
|
||||
* \param IsShareable Configures the device memory as shareable or non-shareable.
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute for normal memory.
|
||||
* - TEX: 1BBb (reflecting outer cacheability rules)
|
||||
* - Shareable or non-shareable
|
||||
* - Cacheable or non-cacheable (reflecting inner cacheability rules)
|
||||
* - Bufferable or non-bufferable (reflecting inner cacheability rules)
|
||||
*
|
||||
* \param OuterCp Configures the outer cache policy.
|
||||
* \param InnerCp Configures the inner cache policy.
|
||||
* \param IsShareable Configures the memory as shareable or non-shareable.
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U))
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute non-cacheable policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_NOCACHE 0U
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute write-back, write and read allocate policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_WB_WRA 1U
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute write-through, no write allocate policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_WT_NWA 2U
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute write-back, no write allocate policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_WB_NWA 3U
|
||||
|
||||
|
||||
/**
|
||||
* Struct for a single MPU Region
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t RBAR; //!< The region base address register value (RBAR)
|
||||
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
|
||||
} ARM_MPU_Region_t;
|
||||
|
||||
/** Enable the MPU.
|
||||
* \param MPU_Control Default access permissions for unconfigured regions.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
|
||||
{
|
||||
__DMB();
|
||||
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
|
||||
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
|
||||
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
|
||||
#endif
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/** Disable the MPU.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_Disable(void)
|
||||
{
|
||||
__DMB();
|
||||
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
|
||||
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
|
||||
#endif
|
||||
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/** Clear and disable the given MPU region.
|
||||
* \param rnr Region number to be cleared.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
|
||||
{
|
||||
MPU->RNR = rnr;
|
||||
MPU->RASR = 0U;
|
||||
}
|
||||
|
||||
/** Configure an MPU region.
|
||||
* \param rbar Value for RBAR register.
|
||||
* \param rasr Value for RASR register.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
|
||||
{
|
||||
MPU->RBAR = rbar;
|
||||
MPU->RASR = rasr;
|
||||
}
|
||||
|
||||
/** Configure the given MPU region.
|
||||
* \param rnr Region number to be configured.
|
||||
* \param rbar Value for RBAR register.
|
||||
* \param rasr Value for RASR register.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
|
||||
{
|
||||
MPU->RNR = rnr;
|
||||
MPU->RBAR = rbar;
|
||||
MPU->RASR = rasr;
|
||||
}
|
||||
|
||||
/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_Load().
|
||||
* \param dst Destination data is copied to.
|
||||
* \param src Source data is copied from.
|
||||
* \param len Amount of data words to be copied.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0U; i < len; ++i)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/** Load the given number of MPU regions from a table.
|
||||
* \param table Pointer to the MPU configuration table.
|
||||
* \param cnt Amount of regions to be configured.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
|
||||
{
|
||||
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
|
||||
while (cnt > MPU_TYPE_RALIASES) {
|
||||
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
|
||||
table += MPU_TYPE_RALIASES;
|
||||
cnt -= MPU_TYPE_RALIASES;
|
||||
}
|
||||
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
28233
platform/rp2040/include/rp2040.h
Normal file
28233
platform/rp2040/include/rp2040.h
Normal file
File diff suppressed because it is too large
Load Diff
59
platform/rp2040/linker/rp2040.ld
Normal file
59
platform/rp2040/linker/rp2040.ld
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
Copyright (c) 2021, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
boot (rx) : ORIGIN = 0x10000000, LENGTH = 256
|
||||
flash (rx) : ORIGIN = 0x10000100, LENGTH = 2048K - 256
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
||||
}
|
||||
|
||||
ENTRY(boot_entry)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.boot : ALIGN(4)
|
||||
{
|
||||
KEEP(*(.boot.entry))
|
||||
*(.boot*)
|
||||
. = 256-4;
|
||||
LONG(0xcccccccc) /* CRC */
|
||||
} > boot
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
_text = .;
|
||||
KEEP(*(.vectors))
|
||||
*(.text*)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
} > ram AT > flash
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
_data = .;
|
||||
*(.ramfunc .ramfunc.*);
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} > ram AT > flash
|
||||
|
||||
.bss : ALIGN(4)
|
||||
{
|
||||
_bss = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} > ram
|
||||
|
||||
PROVIDE(_end = .);
|
||||
PROVIDE(_text_start = ORIGIN(flash));
|
||||
PROVIDE(_stack_top = ORIGIN(ram) + LENGTH(ram));
|
||||
}
|
||||
|
||||
371
platform/rp2040/main.c
Normal file
371
platform/rp2040/main.c
Normal file
@ -0,0 +1,371 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "rp2040.h"
|
||||
#include "hal_gpio.h"
|
||||
#include "usb.h"
|
||||
#include "uart.h"
|
||||
#include "dap.h"
|
||||
#include "dap_config.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define USB_BUFFER_SIZE 64
|
||||
#define UART_WAIT_TIMEOUT 10 // ms
|
||||
#define STATUS_TIMEOUT 250 // ms
|
||||
|
||||
#define F_REF 12000000
|
||||
#define F_CPU 120000000
|
||||
#define F_PER 120000000
|
||||
#define F_RTC (F_REF / 256)
|
||||
#define F_TICK 1000000
|
||||
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
static uint8_t app_request_buffer[DAP_CONFIG_PACKET_SIZE];
|
||||
static uint8_t app_response_buffer[DAP_CONFIG_PACKET_SIZE];
|
||||
static uint8_t app_recv_buffer[USB_BUFFER_SIZE];
|
||||
static uint8_t app_send_buffer[USB_BUFFER_SIZE];
|
||||
static int app_recv_buffer_size = 0;
|
||||
static int app_recv_buffer_ptr = 0;
|
||||
static int app_send_buffer_ptr = 0;
|
||||
static bool app_send_buffer_free = true;
|
||||
static bool app_send_zlp = false;
|
||||
static uint64_t app_system_time = 0;
|
||||
static uint64_t app_uart_timeout = 0;
|
||||
static uint64_t app_status_timeout = 0;
|
||||
static uint64_t app_break_timeout = 0;
|
||||
static bool app_dap_event = false;
|
||||
static bool app_vcp_event = false;
|
||||
static bool app_vcp_open = false;
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void sys_init(void)
|
||||
{
|
||||
// Enable XOSC
|
||||
XOSC->CTRL = (XOSC_CTRL_FREQ_RANGE_1_15MHZ << XOSC_CTRL_FREQ_RANGE_Pos);
|
||||
XOSC->STARTUP = 47; // ~1 ms @ 12 MHz
|
||||
XOSC_SET->CTRL = (XOSC_CTRL_ENABLE_ENABLE << XOSC_CTRL_ENABLE_Pos);
|
||||
while (0 == (XOSC->STATUS & XOSC_STATUS_STABLE_Msk));
|
||||
|
||||
// Setup SYS PLL for 12 MHz * 40 / 4 / 1 = 120 MHz
|
||||
RESETS_CLR->RESET = RESETS_RESET_pll_sys_Msk;
|
||||
while (0 == RESETS->RESET_DONE_b.pll_sys);
|
||||
|
||||
PLL_SYS->CS = (1 << PLL_SYS_CS_REFDIV_Pos);
|
||||
PLL_SYS->FBDIV_INT = 40;
|
||||
PLL_SYS->PRIM = (4 << PLL_SYS_PRIM_POSTDIV1_Pos) | (1 << PLL_SYS_PRIM_POSTDIV2_Pos);
|
||||
|
||||
PLL_SYS_CLR->PWR = PLL_SYS_PWR_VCOPD_Msk | PLL_SYS_PWR_PD_Msk;
|
||||
while (0 == PLL_SYS->CS_b.LOCK);
|
||||
|
||||
PLL_SYS_CLR->PWR = PLL_SYS_PWR_POSTDIVPD_Msk;
|
||||
|
||||
// Setup USB PLL for 12 MHz * 36 / 3 / 3 = 48 MHz
|
||||
RESETS_CLR->RESET = RESETS_RESET_pll_usb_Msk;
|
||||
while (0 == RESETS->RESET_DONE_b.pll_usb);
|
||||
|
||||
PLL_USB->CS = (1 << PLL_SYS_CS_REFDIV_Pos);
|
||||
PLL_USB->FBDIV_INT = 36;
|
||||
PLL_USB->PRIM = (3 << PLL_SYS_PRIM_POSTDIV1_Pos) | (3 << PLL_SYS_PRIM_POSTDIV2_Pos);
|
||||
|
||||
PLL_USB_CLR->PWR = PLL_SYS_PWR_VCOPD_Msk | PLL_SYS_PWR_PD_Msk;
|
||||
while (0 == PLL_USB->CS_b.LOCK);
|
||||
|
||||
PLL_USB_CLR->PWR = PLL_SYS_PWR_POSTDIVPD_Msk;
|
||||
|
||||
// Switch clocks to their final socurces
|
||||
CLOCKS->CLK_REF_CTRL = (CLOCKS_CLK_REF_CTRL_SRC_xosc_clksrc << CLOCKS_CLK_REF_CTRL_SRC_Pos);
|
||||
|
||||
CLOCKS->CLK_SYS_CTRL = (CLOCKS_CLK_SYS_CTRL_AUXSRC_clksrc_pll_sys << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos);
|
||||
CLOCKS_SET->CLK_SYS_CTRL = (CLOCKS_CLK_SYS_CTRL_SRC_clksrc_clk_sys_aux << CLOCKS_CLK_SYS_CTRL_SRC_Pos);
|
||||
|
||||
CLOCKS->CLK_PERI_CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE_Msk |
|
||||
(CLOCKS_CLK_PERI_CTRL_AUXSRC_clk_sys << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos);
|
||||
|
||||
CLOCKS->CLK_USB_CTRL = CLOCKS_CLK_USB_CTRL_ENABLE_Msk |
|
||||
(CLOCKS_CLK_USB_CTRL_AUXSRC_clksrc_pll_usb << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos);
|
||||
|
||||
CLOCKS->CLK_ADC_CTRL = CLOCKS_CLK_ADC_CTRL_ENABLE_Msk |
|
||||
(CLOCKS_CLK_ADC_CTRL_AUXSRC_clksrc_pll_usb << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos);
|
||||
|
||||
CLOCKS->CLK_RTC_DIV = (256 << CLOCKS_CLK_RTC_DIV_INT_Pos); // 12MHz / 256 = 46875 Hz
|
||||
CLOCKS->CLK_RTC_CTRL = CLOCKS_CLK_RTC_CTRL_ENABLE_Msk |
|
||||
(CLOCKS_CLK_RTC_CTRL_AUXSRC_xosc_clksrc << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos);
|
||||
|
||||
// Configure 1 us tick for watchdog and timer
|
||||
WATCHDOG->TICK = ((F_REF/F_TICK) << WATCHDOG_TICK_CYCLES_Pos) | WATCHDOG_TICK_ENABLE_Msk;
|
||||
|
||||
// Enable GPIOs
|
||||
RESETS_CLR->RESET = RESETS_RESET_io_bank0_Msk | RESETS_RESET_pads_bank0_Msk;
|
||||
while (0 == RESETS->RESET_DONE_b.io_bank0 || 0 == RESETS->RESET_DONE_b.pads_bank0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void serial_number_init(void)
|
||||
{
|
||||
volatile uint8_t *uid = (volatile uint8_t *)0x20041f01;
|
||||
uint32_t sn = 5381;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
sn = ((sn << 5) + sn) ^ uid[i];
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
usb_serial_number[i] = "0123456789ABCDEF"[(sn >> (i * 4)) & 0xf];
|
||||
|
||||
usb_serial_number[8] = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void sys_time_init(void)
|
||||
{
|
||||
SysTick->VAL = 0;
|
||||
SysTick->LOAD = 1000; // 1 ms
|
||||
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
|
||||
app_system_time = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void sys_time_task(void)
|
||||
{
|
||||
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)
|
||||
app_system_time++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void tx_task(void)
|
||||
{
|
||||
while (app_recv_buffer_size)
|
||||
{
|
||||
if (!uart_write_byte(app_recv_buffer[app_recv_buffer_ptr]))
|
||||
break;
|
||||
|
||||
app_recv_buffer_ptr++;
|
||||
app_recv_buffer_size--;
|
||||
app_vcp_event = true;
|
||||
|
||||
if (0 == app_recv_buffer_size)
|
||||
usb_cdc_recv(app_recv_buffer, sizeof(app_recv_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void send_buffer(void)
|
||||
{
|
||||
app_send_buffer_free = false;
|
||||
app_send_zlp = (USB_BUFFER_SIZE == app_send_buffer_ptr);
|
||||
|
||||
usb_cdc_send(app_send_buffer, app_send_buffer_ptr);
|
||||
|
||||
app_send_buffer_ptr = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void rx_task(void)
|
||||
{
|
||||
int byte;
|
||||
|
||||
if (!app_send_buffer_free)
|
||||
return;
|
||||
|
||||
while (uart_read_byte(&byte))
|
||||
{
|
||||
int state = (byte >> 8) & 0xff;
|
||||
|
||||
app_uart_timeout = app_system_time + UART_WAIT_TIMEOUT;
|
||||
app_vcp_event = true;
|
||||
|
||||
if (state)
|
||||
{
|
||||
usb_cdc_set_state(state);
|
||||
}
|
||||
else
|
||||
{
|
||||
app_send_buffer[app_send_buffer_ptr++] = byte;
|
||||
|
||||
if (USB_BUFFER_SIZE == app_send_buffer_ptr)
|
||||
{
|
||||
send_buffer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void break_task(void)
|
||||
{
|
||||
if (app_break_timeout && app_system_time > app_break_timeout)
|
||||
{
|
||||
uart_set_break(false);
|
||||
app_break_timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void uart_timer_task(void)
|
||||
{
|
||||
if (app_uart_timeout && app_system_time > app_uart_timeout)
|
||||
{
|
||||
if (app_send_zlp || app_send_buffer_ptr)
|
||||
send_buffer();
|
||||
|
||||
app_uart_timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_line_coding_updated(usb_cdc_line_coding_t *line_coding)
|
||||
{
|
||||
uart_init(line_coding);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_control_line_state_update(int line_state)
|
||||
{
|
||||
bool status = line_state & USB_CDC_CTRL_SIGNAL_DTE_PRESENT;
|
||||
|
||||
app_vcp_open = status;
|
||||
app_send_buffer_ptr = 0;
|
||||
app_uart_timeout = 0;
|
||||
app_break_timeout = 0;
|
||||
|
||||
if (app_vcp_open)
|
||||
uart_init(usb_cdc_get_line_coding());
|
||||
else
|
||||
uart_close();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_send_break(int duration)
|
||||
{
|
||||
if (USB_CDC_BREAK_DURATION_DISABLE == duration)
|
||||
{
|
||||
app_break_timeout = 0;
|
||||
uart_set_break(false);
|
||||
}
|
||||
else if (USB_CDC_BREAK_DURATION_INFINITE == duration)
|
||||
{
|
||||
app_break_timeout = 0;
|
||||
uart_set_break(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
app_break_timeout = app_system_time + duration;
|
||||
uart_set_break(true);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_send_callback(void)
|
||||
{
|
||||
app_send_buffer_free = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_recv_callback(int size)
|
||||
{
|
||||
app_recv_buffer_ptr = 0;
|
||||
app_recv_buffer_size = size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_hid_send_callback(void)
|
||||
{
|
||||
usb_hid_recv(app_request_buffer, DAP_CONFIG_PACKET_SIZE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_hid_recv_callback(int size)
|
||||
{
|
||||
app_dap_event = true;
|
||||
dap_process_request(app_request_buffer, sizeof(app_request_buffer),
|
||||
app_response_buffer, sizeof(app_response_buffer));
|
||||
usb_hid_send(app_response_buffer, sizeof(app_response_buffer));
|
||||
(void)size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool usb_class_handle_request(usb_request_t *request)
|
||||
{
|
||||
if (usb_cdc_handle_request(request))
|
||||
return true;
|
||||
else if (usb_hid_handle_request(request))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_configuration_callback(int config)
|
||||
{
|
||||
usb_cdc_recv(app_recv_buffer, sizeof(app_recv_buffer));
|
||||
usb_hid_recv(app_request_buffer, sizeof(app_request_buffer));
|
||||
|
||||
app_send_buffer_free = true;
|
||||
app_send_buffer_ptr = 0;
|
||||
|
||||
(void)config;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void status_timer_task(void)
|
||||
{
|
||||
if (app_system_time < app_status_timeout)
|
||||
return;
|
||||
|
||||
app_status_timeout = app_system_time + STATUS_TIMEOUT;
|
||||
|
||||
if (app_dap_event)
|
||||
HAL_GPIO_DAP_STATUS_toggle();
|
||||
else
|
||||
HAL_GPIO_DAP_STATUS_set();
|
||||
|
||||
if (app_vcp_event)
|
||||
HAL_GPIO_VCP_STATUS_toggle();
|
||||
else
|
||||
HAL_GPIO_VCP_STATUS_write(app_vcp_open);
|
||||
|
||||
app_dap_event = false;
|
||||
app_vcp_event = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
sys_init();
|
||||
sys_time_init();
|
||||
dap_init();
|
||||
usb_init();
|
||||
usb_cdc_init();
|
||||
usb_hid_init();
|
||||
serial_number_init();
|
||||
|
||||
app_status_timeout = STATUS_TIMEOUT;
|
||||
|
||||
HAL_GPIO_VCP_STATUS_out();
|
||||
HAL_GPIO_VCP_STATUS_clr();
|
||||
|
||||
HAL_GPIO_DAP_STATUS_out();
|
||||
HAL_GPIO_DAP_STATUS_set();
|
||||
|
||||
while (1)
|
||||
{
|
||||
sys_time_task();
|
||||
usb_task();
|
||||
tx_task();
|
||||
rx_task();
|
||||
break_task();
|
||||
uart_timer_task();
|
||||
status_timer_task();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
1
platform/rp2040/make/.gitignore
vendored
Normal file
1
platform/rp2040/make/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
build/
|
||||
87
platform/rp2040/make/Makefile
Normal file
87
platform/rp2040/make/Makefile
Normal file
@ -0,0 +1,87 @@
|
||||
##############################################################################
|
||||
BUILD = build
|
||||
BIN = free_dap_rp2040
|
||||
|
||||
##############################################################################
|
||||
.PHONY: all directory clean size
|
||||
|
||||
CC = arm-none-eabi-gcc
|
||||
OBJCOPY = arm-none-eabi-objcopy
|
||||
SIZE = arm-none-eabi-size
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
MKDIR = gmkdir
|
||||
else
|
||||
MKDIR = mkdir
|
||||
endif
|
||||
|
||||
CFLAGS += -W -Wall --std=gnu11 -Os
|
||||
CFLAGS += -ffreestanding
|
||||
CFLAGS += -fno-diagnostics-show-caret
|
||||
CFLAGS += -fdata-sections -ffunction-sections
|
||||
CFLAGS += -funsigned-char -funsigned-bitfields
|
||||
CFLAGS += -mcpu=cortex-m0plus -mthumb
|
||||
CFLAGS += -MD -MP -MT $(BUILD)/$(*F).o -MF $(BUILD)/$(@F).d
|
||||
|
||||
LDFLAGS += -mcpu=cortex-m0plus -mthumb
|
||||
LDFLAGS += -nostartfiles
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
LDFLAGS += -Wl,--script=../linker/rp2040.ld
|
||||
|
||||
INCLUDES += \
|
||||
-I../include \
|
||||
-I../../.. \
|
||||
-I..
|
||||
|
||||
SRCS += \
|
||||
../main.c \
|
||||
../uart.c \
|
||||
../usb.c \
|
||||
../usb_std.c \
|
||||
../usb_cdc.c \
|
||||
../usb_hid.c \
|
||||
../usb_descriptors.c \
|
||||
../startup_rp2040.c \
|
||||
../../../dap.c \
|
||||
|
||||
DEFINES += \
|
||||
|
||||
CFLAGS += $(INCLUDES) $(DEFINES)
|
||||
|
||||
OBJS = $(addprefix $(BUILD)/, $(notdir %/$(subst .c,.o, $(SRCS))))
|
||||
|
||||
all: directory $(BUILD)/$(BIN).elf $(BUILD)/$(BIN).hex $(BUILD)/$(BIN).bin $(BUILD)/$(BIN).uf2 size
|
||||
|
||||
$(BUILD)/$(BIN).elf: $(OBJS)
|
||||
@echo LD $@
|
||||
@$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
|
||||
$(BUILD)/$(BIN).hex: $(BUILD)/$(BIN).elf
|
||||
@echo OBJCOPY $@
|
||||
@$(OBJCOPY) -O ihex $^ $@
|
||||
|
||||
$(BUILD)/$(BIN).bin: $(BUILD)/$(BIN).elf
|
||||
@echo OBJCOPY $@
|
||||
@$(OBJCOPY) -O binary $^ $@
|
||||
|
||||
$(BUILD)/$(BIN).uf2: $(BUILD)/$(BIN).bin
|
||||
@echo BIN2UF2 $@
|
||||
@bin2uf2 -i $^ -o $@
|
||||
|
||||
%.o:
|
||||
@echo CC $@
|
||||
@$(CC) $(CFLAGS) $(filter %/$(subst .o,.c,$(notdir $@)), $(SRCS)) -c -o $@
|
||||
|
||||
directory:
|
||||
@$(MKDIR) -p $(BUILD)
|
||||
|
||||
size: $(BUILD)/$(BIN).elf
|
||||
@echo size:
|
||||
@$(SIZE) -t $^
|
||||
|
||||
clean:
|
||||
@echo clean
|
||||
@-rm -rf $(BUILD)
|
||||
|
||||
-include $(wildcard $(BUILD)/*.d)
|
||||
|
||||
197
platform/rp2040/startup_rp2040.c
Normal file
197
platform/rp2040/startup_rp2040.c
Normal file
@ -0,0 +1,197 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2021, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <stdint.h>
|
||||
#include "rp2040.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#define DUMMY __attribute__ ((weak, alias ("irq_handler_dummy")))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
DUMMY void irq_handler_nmi(void);
|
||||
DUMMY void irq_handler_hard_fault(void);
|
||||
DUMMY void irq_handler_sv_call(void);
|
||||
DUMMY void irq_handler_pend_sv(void);
|
||||
DUMMY void irq_handler_sys_tick(void);
|
||||
|
||||
DUMMY void irq_handler_timer_0(void);
|
||||
DUMMY void irq_handler_timer_1(void);
|
||||
DUMMY void irq_handler_timer_2(void);
|
||||
DUMMY void irq_handler_timer_3(void);
|
||||
DUMMY void irq_handler_pwm(void);
|
||||
DUMMY void irq_handler_usbctrl(void);
|
||||
DUMMY void irq_handler_xip(void);
|
||||
DUMMY void irq_handler_pio0_0(void);
|
||||
DUMMY void irq_handler_pio0_1(void);
|
||||
DUMMY void irq_handler_pio1_0(void);
|
||||
DUMMY void irq_handler_pio1_1(void);
|
||||
DUMMY void irq_handler_dma_0(void);
|
||||
DUMMY void irq_handler_dma_1(void);
|
||||
DUMMY void irq_handler_io_bank0(void);
|
||||
DUMMY void irq_handler_io_qspi(void);
|
||||
DUMMY void irq_handler_sio_proc0(void);
|
||||
DUMMY void irq_handler_sio_proc1(void);
|
||||
DUMMY void irq_handler_clocks(void);
|
||||
DUMMY void irq_handler_spi0(void);
|
||||
DUMMY void irq_handler_spi1(void);
|
||||
DUMMY void irq_handler_uart0(void);
|
||||
DUMMY void irq_handler_uart1(void);
|
||||
DUMMY void irq_handler_adc_fifo(void);
|
||||
DUMMY void irq_handler_i2c0(void);
|
||||
DUMMY void irq_handler_i2c1(void);
|
||||
DUMMY void irq_handler_rtc(void);
|
||||
|
||||
extern int main(void);
|
||||
|
||||
extern uint32_t _text_start;
|
||||
extern uint32_t _stack_top;
|
||||
extern uint32_t _text;
|
||||
extern uint32_t _etext;
|
||||
extern uint32_t _data;
|
||||
extern uint32_t _edata;
|
||||
extern uint32_t _bss;
|
||||
extern uint32_t _ebss;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Note: Vector table does not need to be placed in a separate section on this MCU,
|
||||
// but we do so anyway to ensure alignment at 128 byte boundary without
|
||||
// potentially wasting space with automatic alignment.
|
||||
__attribute__ ((used, section(".vectors")))
|
||||
void (* const vectors[])(void) =
|
||||
{
|
||||
0, // 0 - Initial Stack Pointer Value (unused)
|
||||
|
||||
// Cortex-M0+ handlers
|
||||
0, // 1 - Reset (unused)
|
||||
irq_handler_nmi, // 2 - NMI
|
||||
irq_handler_hard_fault, // 3 - Hard Fault
|
||||
0, // 4 - Reserved
|
||||
0, // 5 - Reserved
|
||||
0, // 6 - Reserved
|
||||
0, // 7 - Reserved
|
||||
0, // 8 - Reserved
|
||||
0, // 9 - Reserved
|
||||
0, // 10 - Reserved
|
||||
irq_handler_sv_call, // 11 - SVCall
|
||||
0, // 12 - Reserved
|
||||
0, // 13 - Reserved
|
||||
irq_handler_pend_sv, // 14 - PendSV
|
||||
irq_handler_sys_tick, // 15 - SysTick
|
||||
|
||||
// Peripheral handlers
|
||||
irq_handler_timer_0, // 0 - timer_irq_0
|
||||
irq_handler_timer_1, // 1 - timer_irq_1
|
||||
irq_handler_timer_2, // 2 - timer_irq_2
|
||||
irq_handler_timer_3, // 3 - timer_irq_3
|
||||
irq_handler_pwm, // 4 - pwm_irq_wrap
|
||||
irq_handler_usbctrl, // 5 - usbctrl_irq
|
||||
irq_handler_xip, // 6 - xip_irq
|
||||
irq_handler_pio0_0, // 7 - pio0_irq_0
|
||||
irq_handler_pio0_1, // 8 - pio0_irq_1
|
||||
irq_handler_pio1_0, // 9 - pio1_irq_0
|
||||
irq_handler_pio1_1, // 10 - pio1_irq_1
|
||||
irq_handler_dma_0, // 11 - dma_irq_0
|
||||
irq_handler_dma_1, // 12 - dma_irq_1
|
||||
irq_handler_io_bank0, // 13 - io_irq_bank0
|
||||
irq_handler_io_qspi, // 14 - io_irq_qspi
|
||||
irq_handler_sio_proc0, // 15 - sio_irq_proc0
|
||||
irq_handler_sio_proc1, // 16 - sio_irq_proc1
|
||||
irq_handler_clocks, // 17 - clocks_irq
|
||||
irq_handler_spi0, // 18 - spi0_irq
|
||||
irq_handler_spi1, // 19 - spi1_irq
|
||||
irq_handler_uart0, // 20 - uart0_irq
|
||||
irq_handler_uart1, // 21 - uart1_irq
|
||||
irq_handler_adc_fifo, // 22 - adc_irq_fifo
|
||||
irq_handler_i2c0, // 23 - i2c0_irq
|
||||
irq_handler_i2c1, // 24 - i2c1_irq
|
||||
irq_handler_rtc, // 25 - rtc_irq
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void irq_handler_dummy(void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__attribute__((naked, used, noreturn, section(".boot.entry"))) void boot_entry(void)
|
||||
{
|
||||
// Note: This code must be position independent, it is linked at 0x10000000, but
|
||||
// loaded at 0x20041f00.
|
||||
XIP_SSI->SSIENR = 0;
|
||||
|
||||
XIP_SSI->BAUDR = 2; // Must be even
|
||||
|
||||
// Read unique ID
|
||||
XIP_SSI->RX_SAMPLE_DLY = (1 << XIP_SSI_RX_SAMPLE_DLY_RSD_Pos);
|
||||
|
||||
XIP_SSI->CTRLR0 = (XIP_SSI_CTRLR0_SPI_FRF_STD << XIP_SSI_CTRLR0_SPI_FRF_Pos) |
|
||||
(XIP_SSI_CTRLR0_TMOD_TX_AND_RX << XIP_SSI_CTRLR0_TMOD_Pos) |
|
||||
((32-1) << XIP_SSI_CTRLR0_DFS_32_Pos);
|
||||
|
||||
XIP_SSI->SSIENR = XIP_SSI_SSIENR_SSI_EN_Msk;
|
||||
|
||||
XIP_SSI->DR0 = 0x4b000000/*RUID*/;
|
||||
XIP_SSI->DR0 = 0;
|
||||
XIP_SSI->DR0 = 0;
|
||||
XIP_SSI->DR0 = 0;
|
||||
XIP_SSI->DR0 = 0;
|
||||
XIP_SSI->DR0 = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int sr = XIP_SSI->SR;
|
||||
if ((sr & XIP_SSI_SR_TFE_Msk) && (0 == (sr & XIP_SSI_SR_BUSY_Msk)))
|
||||
break;
|
||||
}
|
||||
|
||||
(void)XIP_SSI->DR0;
|
||||
|
||||
// UID is placed at the same address as this boot sector
|
||||
volatile uint32_t *uid = (volatile uint32_t *)0x20041f00;
|
||||
uid[0] = XIP_SSI->DR0;
|
||||
uid[1] = XIP_SSI->DR0;
|
||||
uid[2] = XIP_SSI->DR0;
|
||||
uid[3] = XIP_SSI->DR0;
|
||||
uid[4] = XIP_SSI->DR0;
|
||||
|
||||
XIP_SSI->SSIENR = 0;
|
||||
|
||||
// Setup for XIP
|
||||
XIP_SSI->CTRLR0 = (XIP_SSI_CTRLR0_SPI_FRF_STD << XIP_SSI_CTRLR0_SPI_FRF_Pos) |
|
||||
(XIP_SSI_CTRLR0_TMOD_EEPROM_READ << XIP_SSI_CTRLR0_TMOD_Pos) |
|
||||
((32-1) << XIP_SSI_CTRLR0_DFS_32_Pos);
|
||||
|
||||
XIP_SSI->CTRLR1 = (0 << XIP_SSI_CTRLR1_NDF_Pos);
|
||||
|
||||
XIP_SSI->SPI_CTRLR0 = (0x03/*READ_DATA*/ << XIP_SSI_SPI_CTRLR0_XIP_CMD_Pos) |
|
||||
((24 / 4) << XIP_SSI_SPI_CTRLR0_ADDR_L_Pos) |
|
||||
(XIP_SSI_SPI_CTRLR0_INST_L_8B << XIP_SSI_SPI_CTRLR0_INST_L_Pos) |
|
||||
(XIP_SSI_SPI_CTRLR0_TRANS_TYPE_1C1A << XIP_SSI_SPI_CTRLR0_TRANS_TYPE_Pos);
|
||||
|
||||
XIP_SSI->SSIENR = XIP_SSI_SSIENR_SSI_EN_Msk;
|
||||
|
||||
uint32_t *src = &_text_start;
|
||||
uint32_t *dst = &_text;
|
||||
|
||||
while (dst < &_edata)
|
||||
*dst++ = *src++;
|
||||
|
||||
dst = &_bss;
|
||||
while (dst < &_ebss)
|
||||
*dst++ = 0;
|
||||
|
||||
SCB->VTOR = (uint32_t)vectors;
|
||||
|
||||
asm (R"asm(
|
||||
msr msp, %[sp]
|
||||
bx %[reset]
|
||||
)asm"
|
||||
:: [sp] "r" (&_stack_top), [reset] "r" (main)
|
||||
);
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
|
||||
3
platform/rp2040/tools/.gitignore
vendored
Normal file
3
platform/rp2040/tools/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
bin2uf2
|
||||
bin2uf2.exe
|
||||
|
||||
6
platform/rp2040/tools/Makefile
Normal file
6
platform/rp2040/tools/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
all: bin2uf2.c
|
||||
gcc -W -Wall -Wextra -O3 -std=gnu11 bin2uf2.c -o bin2uf2
|
||||
|
||||
clean:
|
||||
rm -rf bin2uf2 bin2uf2.exe
|
||||
|
||||
245
platform/rp2040/tools/bin2uf2.c
Normal file
245
platform/rp2040/tools/bin2uf2.c
Normal file
@ -0,0 +1,245 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2021, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#define MAX_FILE_SIZE (16*1024*1024)
|
||||
|
||||
#define UF2_MAGIC_START_0 0x0a324655
|
||||
#define UF2_MAGIC_START_1 0x9e5d5157
|
||||
#define UF2_MAGIC_END 0x0ab16f30
|
||||
#define UF2_FLAG_FAMILY_ID 0x00002000
|
||||
#define UF2_FAMILY_ID_RP2040 0xe48bff56
|
||||
#define UF2_BLOCK_SIZE 256
|
||||
|
||||
#define FLASH_START 0x10000000
|
||||
#define BL2_SIZE 256
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t magic_start_0;
|
||||
uint32_t magic_start_1;
|
||||
uint32_t flags;
|
||||
uint32_t target_addr;
|
||||
uint32_t payload_size;
|
||||
uint32_t block_no;
|
||||
uint32_t num_blocks;
|
||||
uint32_t family_id;
|
||||
uint8_t data[476];
|
||||
uint32_t magic_end;
|
||||
} UF2Block;
|
||||
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
static const struct option long_options[] =
|
||||
{
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "update", no_argument, 0, 'u' },
|
||||
{ "input", required_argument, 0, 'i' },
|
||||
{ "output", required_argument, 0, 'o' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const char *short_options = "hui:o:";
|
||||
|
||||
static bool g_update = false;
|
||||
static char *g_input = NULL;
|
||||
static char *g_output = NULL;
|
||||
|
||||
static uint32_t crc32_tab[256];
|
||||
|
||||
static uint8_t g_data[MAX_FILE_SIZE];
|
||||
static int g_size = 0;
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void crc32_tab_gen(void)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t value = i << 24;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (value & (1 << 31))
|
||||
value = (value << 1) ^ 0x4c11db7ul;
|
||||
else
|
||||
value = value << 1;
|
||||
}
|
||||
|
||||
crc32_tab[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static uint32_t crc32(uint8_t *data, int size)
|
||||
{
|
||||
uint32_t crc = 0xffffffff;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
crc = crc32_tab[((crc >> 24) & 0xff) ^ data[i]] ^ (crc << 8);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void check(bool cond, char *fmt, ...)
|
||||
{
|
||||
if (!cond)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "Error: ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(args);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void perror_exit(char *text)
|
||||
{
|
||||
perror(text);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void print_help(char *name)
|
||||
{
|
||||
printf("Usage: %s [options]\n", name);
|
||||
printf("Options:\n");
|
||||
printf(" -h, --help print this help message and exit\n");
|
||||
printf(" -u, --update generate raw binary file with an updated CRC\n");
|
||||
printf(" -i, --input <name> input file name\n");
|
||||
printf(" -o, --output <name> output file name\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void parse_command_line(int argc, char **argv)
|
||||
{
|
||||
int option_index = 0;
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'h': print_help(argv[0]); break;
|
||||
case 'u': g_update = true; break;
|
||||
case 'i': g_input = optarg; break;
|
||||
case 'o': g_output = optarg; break;
|
||||
default: exit(1); break;
|
||||
}
|
||||
}
|
||||
|
||||
check(optind >= argc, "malformed command line, use '-h' for more information");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
uint32_t crc;
|
||||
|
||||
crc32_tab_gen();
|
||||
|
||||
parse_command_line(argc, argv);
|
||||
|
||||
check(NULL != g_input, "input file name is not specified");
|
||||
check(NULL != g_output, "output file name is not specified");
|
||||
|
||||
memset(g_data, 0xff, sizeof(g_data));
|
||||
|
||||
fd = open(g_input, O_RDONLY | O_BINARY);
|
||||
|
||||
if (fd < 0)
|
||||
perror_exit("open()");
|
||||
|
||||
g_size = read(fd, g_data, sizeof(g_data));
|
||||
|
||||
if (g_size < 0)
|
||||
perror_exit("read()");
|
||||
|
||||
check(g_size < (int)sizeof(g_data), "input file is too big");
|
||||
|
||||
close(fd);
|
||||
|
||||
while ((g_size % UF2_BLOCK_SIZE) != 0)
|
||||
g_size++;
|
||||
|
||||
crc = crc32(g_data, BL2_SIZE-4);
|
||||
|
||||
g_data[BL2_SIZE-4] = (crc >> 0);
|
||||
g_data[BL2_SIZE-3] = (crc >> 8);
|
||||
g_data[BL2_SIZE-2] = (crc >> 16);
|
||||
g_data[BL2_SIZE-1] = (crc >> 24);
|
||||
|
||||
fd = open(g_output, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0644);
|
||||
|
||||
if (fd < 0)
|
||||
perror_exit("open()");
|
||||
|
||||
if (g_update)
|
||||
{
|
||||
if (write(fd, g_data, g_size) < 0)
|
||||
perror_exit("write()");
|
||||
}
|
||||
else
|
||||
{
|
||||
UF2Block block;
|
||||
uint32_t offs = 0;
|
||||
uint32_t addr = FLASH_START;
|
||||
int n_blocks = g_size / UF2_BLOCK_SIZE;
|
||||
|
||||
block.magic_start_0 = UF2_MAGIC_START_0;
|
||||
block.magic_start_1 = UF2_MAGIC_START_1;
|
||||
block.flags = UF2_FLAG_FAMILY_ID;
|
||||
block.payload_size = UF2_BLOCK_SIZE;
|
||||
block.num_blocks = n_blocks;
|
||||
block.family_id = UF2_FAMILY_ID_RP2040;
|
||||
block.magic_end = UF2_MAGIC_END;
|
||||
|
||||
memset(block.data, 0, sizeof(block.data));
|
||||
|
||||
for (int i = 0; i < n_blocks; i++)
|
||||
{
|
||||
block.target_addr = addr;
|
||||
block.block_no = i;
|
||||
|
||||
memcpy(block.data, &g_data[offs], UF2_BLOCK_SIZE);
|
||||
|
||||
if (write(fd, &block, sizeof(UF2Block)) < 0)
|
||||
perror_exit("write()");
|
||||
|
||||
addr += UF2_BLOCK_SIZE;
|
||||
offs += UF2_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
224
platform/rp2040/uart.c
Normal file
224
platform/rp2040/uart.c
Normal file
@ -0,0 +1,224 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "rp2040.h"
|
||||
#include "hal_config.h"
|
||||
#include "uart.h"
|
||||
#include "usb_cdc.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define UART_BUF_SIZE 256
|
||||
|
||||
/*- Types ------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
int wr;
|
||||
int rd;
|
||||
uint16_t data[UART_BUF_SIZE];
|
||||
} fifo_buffer_t;
|
||||
|
||||
/*- Variables --------------------------------------------------------------*/
|
||||
static volatile fifo_buffer_t uart_rx_fifo;
|
||||
static volatile fifo_buffer_t uart_tx_fifo;
|
||||
static volatile bool uart_fifo_overflow = false;
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void uart_init(usb_cdc_line_coding_t *line_coding)
|
||||
{
|
||||
int wlen, parity, stop, baud;
|
||||
|
||||
RESETS_SET->RESET = UART_RESET_MASK;
|
||||
RESETS_CLR->RESET = UART_RESET_MASK;
|
||||
while (0 == (RESETS->RESET_DONE & UART_RESET_MASK));
|
||||
|
||||
uart_tx_fifo.wr = 0;
|
||||
uart_tx_fifo.rd = 0;
|
||||
|
||||
uart_rx_fifo.wr = 0;
|
||||
uart_rx_fifo.rd = 0;
|
||||
|
||||
uart_fifo_overflow = false;
|
||||
|
||||
if (USB_CDC_5_DATA_BITS == line_coding->bDataBits)
|
||||
wlen = 0;
|
||||
else if (USB_CDC_6_DATA_BITS == line_coding->bDataBits)
|
||||
wlen = 1;
|
||||
else if (USB_CDC_7_DATA_BITS == line_coding->bDataBits)
|
||||
wlen = 2;
|
||||
else if (USB_CDC_8_DATA_BITS == line_coding->bDataBits)
|
||||
wlen = 3;
|
||||
else
|
||||
wlen = 3;
|
||||
|
||||
if (USB_CDC_NO_PARITY == line_coding->bParityType)
|
||||
parity = 0;
|
||||
else if (USB_CDC_ODD_PARITY == line_coding->bParityType)
|
||||
parity = UART0_UARTLCR_H_PEN_Msk;
|
||||
else if (USB_CDC_EVEN_PARITY == line_coding->bParityType)
|
||||
parity = UART0_UARTLCR_H_PEN_Msk | UART0_UARTLCR_H_EPS_Msk;
|
||||
else if (USB_CDC_MARK_PARITY == line_coding->bParityType)
|
||||
parity = UART0_UARTLCR_H_PEN_Msk | UART0_UARTLCR_H_SPS_Msk;
|
||||
else if (USB_CDC_SPACE_PARITY == line_coding->bParityType)
|
||||
parity = UART0_UARTLCR_H_PEN_Msk | UART0_UARTLCR_H_SPS_Msk | UART0_UARTLCR_H_EPS_Msk;
|
||||
else
|
||||
parity = 0;
|
||||
|
||||
if (USB_CDC_1_STOP_BIT == line_coding->bCharFormat)
|
||||
stop = 0;
|
||||
else
|
||||
stop = UART0_UARTLCR_H_STP2_Msk;
|
||||
|
||||
baud = (UART_CLOCK * 4) / line_coding->dwDTERate;
|
||||
|
||||
UART_PER->UARTIFLS = (3 << UART0_UARTIFLS_RXIFLSEL_Pos) | (0 << UART0_UARTIFLS_TXIFLSEL_Pos);
|
||||
|
||||
UART_PER->UARTIBRD = baud / 64;
|
||||
UART_PER->UARTFBRD = baud % 64;
|
||||
|
||||
UART_PER->UARTLCR_H = (wlen << UART0_UARTLCR_H_WLEN_Pos) | parity | stop | UART0_UARTLCR_H_FEN_Msk;
|
||||
|
||||
UART_PER->UARTIMSC = UART0_UARTIMSC_RXIM_Msk | UART0_UARTIMSC_RTIM_Msk | UART0_UARTIMSC_TXIM_Msk;
|
||||
|
||||
HAL_GPIO_UART_TX_init();
|
||||
HAL_GPIO_UART_TX_pullup();
|
||||
|
||||
HAL_GPIO_UART_RX_init();
|
||||
HAL_GPIO_UART_RX_pullup();
|
||||
|
||||
UART_PER->UARTCR = UART0_UARTCR_UARTEN_Msk | UART0_UARTCR_RXE_Msk | UART0_UARTCR_TXE_Msk;
|
||||
|
||||
NVIC_EnableIRQ(UART_IRQ_INDEX);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void uart_close(void)
|
||||
{
|
||||
RESETS_SET->RESET = UART_RESET_MASK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool uart_write_byte(int byte)
|
||||
{
|
||||
int wr = (uart_tx_fifo.wr + 1) % UART_BUF_SIZE;
|
||||
bool res = false;
|
||||
|
||||
NVIC_DisableIRQ(UART_IRQ_INDEX);
|
||||
|
||||
if (uart_tx_fifo.rd == uart_tx_fifo.wr && !UART_PER->UARTFR_b.TXFF)
|
||||
{
|
||||
UART_PER->UARTDR = byte;
|
||||
res = true;
|
||||
}
|
||||
else if (wr != uart_tx_fifo.rd)
|
||||
{
|
||||
uart_tx_fifo.data[uart_tx_fifo.wr] = byte;
|
||||
uart_tx_fifo.wr = wr;
|
||||
res = true;
|
||||
}
|
||||
|
||||
NVIC_EnableIRQ(UART_IRQ_INDEX);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool uart_read_byte(int *byte)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
NVIC_DisableIRQ(UART_IRQ_INDEX);
|
||||
|
||||
if (uart_fifo_overflow)
|
||||
{
|
||||
*byte = (USB_CDC_SERIAL_STATE_OVERRUN << 8);
|
||||
uart_fifo_overflow = false;
|
||||
res = true;
|
||||
}
|
||||
else if (uart_rx_fifo.rd != uart_rx_fifo.wr)
|
||||
{
|
||||
*byte = uart_rx_fifo.data[uart_rx_fifo.rd];
|
||||
uart_rx_fifo.rd = (uart_rx_fifo.rd + 1) % UART_BUF_SIZE;
|
||||
res = true;
|
||||
}
|
||||
|
||||
NVIC_EnableIRQ(UART_IRQ_INDEX);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void uart_set_break(bool brk)
|
||||
{
|
||||
if (brk)
|
||||
UART_PER->UARTLCR_H |= UART0_UARTLCR_H_BRK_Msk;
|
||||
else
|
||||
UART_PER->UARTLCR_H &= ~UART0_UARTLCR_H_BRK_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UART_IRQ_HANDLER(void)
|
||||
{
|
||||
int flags = UART_PER->UARTMIS;
|
||||
|
||||
if (flags & (UART0_UARTIMSC_RXIM_Msk | UART0_UARTIMSC_RTIM_Msk))
|
||||
{
|
||||
while (!UART_PER->UARTFR_b.RXFE)
|
||||
{
|
||||
int byte = UART_PER->UARTDR;
|
||||
int wr = (uart_rx_fifo.wr + 1) % UART_BUF_SIZE;
|
||||
int state = 0;
|
||||
|
||||
if (byte & UART0_UARTDR_BE_Msk)
|
||||
{
|
||||
state |= USB_CDC_SERIAL_STATE_BREAK;
|
||||
byte &= ~(UART0_UARTDR_PE_Msk | UART0_UARTDR_FE_Msk);
|
||||
}
|
||||
|
||||
if (byte & UART0_UARTDR_PE_Msk)
|
||||
state |= USB_CDC_SERIAL_STATE_PARITY;
|
||||
|
||||
if (byte & UART0_UARTDR_FE_Msk)
|
||||
state |= USB_CDC_SERIAL_STATE_FRAMING;
|
||||
|
||||
if (byte & UART0_UARTDR_OE_Msk)
|
||||
state |= USB_CDC_SERIAL_STATE_OVERRUN;
|
||||
|
||||
byte = (state << 8) | (byte & UART0_UARTDR_DATA_Msk);
|
||||
|
||||
if (wr == uart_rx_fifo.rd)
|
||||
{
|
||||
uart_fifo_overflow = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_rx_fifo.data[uart_rx_fifo.wr] = byte;
|
||||
uart_rx_fifo.wr = wr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & UART0_UARTIMSC_TXIM_Msk)
|
||||
{
|
||||
UART_PER->UARTICR = UART0_UARTICR_TXIC_Msk;
|
||||
|
||||
while (!UART_PER->UARTFR_b.TXFF)
|
||||
{
|
||||
if (uart_tx_fifo.rd == uart_tx_fifo.wr)
|
||||
break;
|
||||
|
||||
UART_PER->UARTDR = uart_tx_fifo.data[uart_tx_fifo.rd];
|
||||
uart_tx_fifo.rd = (uart_tx_fifo.rd + 1) % UART_BUF_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
platform/rp2040/uart.h
Normal file
20
platform/rp2040/uart.h
Normal file
@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb_cdc.h"
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
void uart_init(usb_cdc_line_coding_t *line_coding);
|
||||
void uart_close(void);
|
||||
bool uart_write_byte(int byte);
|
||||
bool uart_read_byte(int *byte);
|
||||
void uart_set_break(bool brk);
|
||||
|
||||
#endif // _UART_H_
|
||||
|
||||
368
platform/rp2040/usb.c
Normal file
368
platform/rp2040/usb.c
Normal file
@ -0,0 +1,368 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdalign.h>
|
||||
#include "rp2040.h"
|
||||
#include "utils.h"
|
||||
#include "usb.h"
|
||||
#include "usb_std.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define USB_DPRAM_SIZE 4096
|
||||
#define USB_DPRAM ((usb_dpram_t *)USBCTRL_DPRAM_BASE)
|
||||
#define USB_DPRAM_FIXED_SIZE 0x100
|
||||
#define USB_DPRAM_BUF_OFFSET (USB_DPRAM_FIXED_SIZE + USB_CTRL_EP_SIZE*2)
|
||||
|
||||
/*- Types -------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
__IOM uint8_t SETUP[8];
|
||||
|
||||
struct // Starts with EP1
|
||||
{
|
||||
__IOM uint32_t IN;
|
||||
__IOM uint32_t OUT;
|
||||
} EP_CTRL[USB_EP_NUM-1];
|
||||
|
||||
struct // Starts with EP0
|
||||
{
|
||||
__IOM uint32_t IN;
|
||||
__IOM uint32_t OUT;
|
||||
} EP_BUF_CTRL[USB_EP_NUM];
|
||||
|
||||
__IOM uint8_t EP0_BUF[USB_CTRL_EP_SIZE];
|
||||
__IOM uint8_t DUMMY[USB_CTRL_EP_SIZE];
|
||||
} usb_dpram_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int in_pid;
|
||||
volatile uint8_t *in_buf;
|
||||
int out_pid;
|
||||
volatile uint8_t *out_buf;
|
||||
uint8_t *out_data;
|
||||
} usb_ep_t;
|
||||
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
static int usb_ep_buf_ptr = 0;
|
||||
static usb_ep_t usb_ep[USB_EP_NUM];
|
||||
static void (*usb_control_recv_callback)(uint8_t *data, int size);
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
static void usb_reset_endpoints(void);
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_hw_init(void)
|
||||
{
|
||||
RESETS_CLR->RESET = RESETS_RESET_usbctrl_Msk;
|
||||
while (0 == RESETS->RESET_DONE_b.usbctrl);
|
||||
|
||||
memset(USBCTRL_DPRAM, 0, USB_DPRAM_SIZE);
|
||||
|
||||
USBCTRL_REGS->USB_MUXING = USBCTRL_REGS_USB_MUXING_TO_PHY_Msk |
|
||||
USBCTRL_REGS_USB_MUXING_SOFTCON_Msk;
|
||||
|
||||
USBCTRL_REGS->USB_PWR = USBCTRL_REGS_USB_PWR_VBUS_DETECT_Msk |
|
||||
USBCTRL_REGS_USB_PWR_VBUS_DETECT_OVERRIDE_EN_Msk;
|
||||
|
||||
USBCTRL_REGS->MAIN_CTRL = USBCTRL_REGS_MAIN_CTRL_CONTROLLER_EN_Msk;
|
||||
|
||||
USBCTRL_REGS->SIE_CTRL = USBCTRL_REGS_SIE_CTRL_EP0_INT_1BUF_Msk;
|
||||
|
||||
USBCTRL_REGS->ADDR_ENDP = 0;
|
||||
|
||||
USBCTRL_REGS->INTE = USBCTRL_REGS_INTE_BUFF_STATUS_Msk |
|
||||
USBCTRL_REGS_INTE_SETUP_REQ_Msk | USBCTRL_REGS_INTE_BUS_RESET_Msk;
|
||||
|
||||
usb_reset_endpoints();
|
||||
|
||||
usb_attach();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_attach(void)
|
||||
{
|
||||
USBCTRL_REGS_SET->SIE_CTRL = USBCTRL_REGS_SIE_CTRL_PULLUP_EN_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_detach(void)
|
||||
{
|
||||
USBCTRL_REGS_CLR->SIE_CTRL = USBCTRL_REGS_SIE_CTRL_PULLUP_EN_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_reset_endpoints(void)
|
||||
{
|
||||
for (int i = 0; i < USB_EP_NUM-1; i++)
|
||||
{
|
||||
USB_DPRAM->EP_CTRL[i].IN = 0;
|
||||
USB_DPRAM->EP_CTRL[i].OUT = 0;
|
||||
}
|
||||
|
||||
memset(&usb_ep, 0, sizeof(usb_ep));
|
||||
|
||||
usb_ep_buf_ptr = USB_DPRAM_BUF_OFFSET;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_configure_endpoint(usb_endpoint_descriptor_t *desc)
|
||||
{
|
||||
int ep, dir, type, size;
|
||||
|
||||
ep = desc->bEndpointAddress & USB_INDEX_MASK;
|
||||
dir = desc->bEndpointAddress & USB_DIRECTION_MASK;
|
||||
type = desc->bmAttributes & 0x03;
|
||||
size = desc->wMaxPacketSize & 0x3ff;
|
||||
|
||||
if (size <= 64)
|
||||
size = 64;
|
||||
else if (size <= 128)
|
||||
size = 128;
|
||||
else if (size <= 256)
|
||||
size = 256;
|
||||
else if (size <= 512)
|
||||
size = 512;
|
||||
else
|
||||
size = 1024;
|
||||
|
||||
if (USB_IN_ENDPOINT == dir)
|
||||
{
|
||||
usb_ep[ep].in_buf = (volatile uint8_t *)(USBCTRL_DPRAM_BASE + usb_ep_buf_ptr);
|
||||
|
||||
USB_DPRAM->EP_CTRL[ep-1].IN = USBCTRL_DPRAM_EP1_IN_CONTROL_ENABLE_Msk |
|
||||
USBCTRL_DPRAM_EP1_IN_CONTROL_INTERRUPT_PER_BUFF_Msk |
|
||||
(type << USBCTRL_DPRAM_EP1_IN_CONTROL_ENDPOINT_TYPE_Pos) |
|
||||
(usb_ep_buf_ptr << USBCTRL_DPRAM_EP1_IN_CONTROL_BUFFER_ADDRESS_Pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_ep[ep].out_buf = (volatile uint8_t *)(USBCTRL_DPRAM_BASE + usb_ep_buf_ptr);
|
||||
|
||||
USB_DPRAM->EP_CTRL[ep-1].OUT = USBCTRL_DPRAM_EP1_OUT_CONTROL_ENABLE_Msk |
|
||||
USBCTRL_DPRAM_EP1_OUT_CONTROL_INTERRUPT_PER_BUFF_Msk |
|
||||
(type << USBCTRL_DPRAM_EP1_OUT_CONTROL_ENDPOINT_TYPE_Pos) |
|
||||
(usb_ep_buf_ptr << USBCTRL_DPRAM_EP1_OUT_CONTROL_BUFFER_ADDRESS_Pos);
|
||||
}
|
||||
|
||||
usb_ep_buf_ptr += size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool usb_endpoint_configured(int ep, int dir)
|
||||
{
|
||||
if (USB_IN_ENDPOINT == dir)
|
||||
return (USB_DPRAM->EP_CTRL[ep-1].IN & USBCTRL_DPRAM_EP1_IN_CONTROL_ENABLE_Msk) != 0;
|
||||
else
|
||||
return (USB_DPRAM->EP_CTRL[ep-1].OUT & USBCTRL_DPRAM_EP1_OUT_CONTROL_ENABLE_Msk) != 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int usb_endpoint_get_status(int ep, int dir)
|
||||
{
|
||||
if (USB_IN_ENDPOINT == dir)
|
||||
return (USB_DPRAM->EP_BUF_CTRL[ep].IN & USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_STALL_Msk) != 0;
|
||||
else
|
||||
return (USB_DPRAM->EP_BUF_CTRL[ep].OUT & USBCTRL_DPRAM_EP0_OUT_BUFFER_CONTROL_STALL_Msk) != 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_endpoint_set_feature(int ep, int dir)
|
||||
{
|
||||
if (USB_IN_ENDPOINT == dir)
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].IN = USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_STALL_Msk;
|
||||
else
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].OUT = USBCTRL_DPRAM_EP0_OUT_BUFFER_CONTROL_STALL_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_endpoint_clear_feature(int ep, int dir)
|
||||
{
|
||||
if (USB_IN_ENDPOINT == dir)
|
||||
{
|
||||
usb_ep[ep].in_pid = 0;
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].IN &= ~USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_STALL_Msk;
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_ep[0].out_pid = 0;
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].OUT &= ~USBCTRL_DPRAM_EP0_OUT_BUFFER_CONTROL_STALL_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_set_address(int address)
|
||||
{
|
||||
USBCTRL_REGS->ADDR_ENDP = address;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_start_in_transfer(int ep, int size)
|
||||
{
|
||||
uint32_t v = size | USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_FULL_0_Msk |
|
||||
(usb_ep[ep].in_pid ? USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_PID_0_Msk : 0);
|
||||
usb_ep[ep].in_pid ^= 1;
|
||||
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].IN = v;
|
||||
asm("nop");
|
||||
asm("nop");
|
||||
asm("nop");
|
||||
asm("nop");
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].IN = v | USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_AVAILABLE_0_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_start_out_transfer(int ep, int size)
|
||||
{
|
||||
uint32_t v = size | (usb_ep[ep].out_pid ? USBCTRL_DPRAM_EP0_OUT_BUFFER_CONTROL_PID_0_Msk : 0);
|
||||
usb_ep[ep].out_pid ^= 1;
|
||||
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].OUT = v;
|
||||
asm("nop");
|
||||
asm("nop");
|
||||
asm("nop");
|
||||
asm("nop");
|
||||
USB_DPRAM->EP_BUF_CTRL[ep].OUT = v | USBCTRL_DPRAM_EP0_OUT_BUFFER_CONTROL_AVAILABLE_0_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_send(int ep, uint8_t *data, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
usb_ep[ep].in_buf[i] = data[i];
|
||||
|
||||
usb_start_in_transfer(ep, size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_recv(int ep, uint8_t *data, int size)
|
||||
{
|
||||
usb_ep[ep].out_data = data;
|
||||
usb_start_out_transfer(ep, size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_control_send_zlp(void)
|
||||
{
|
||||
usb_start_in_transfer(0, 0);
|
||||
|
||||
while (0 == (USBCTRL_REGS->BUFF_STATUS & USBCTRL_REGS_BUFF_STATUS_EP0_IN_Msk));
|
||||
USBCTRL_REGS->BUFF_STATUS = USBCTRL_REGS_BUFF_STATUS_EP0_IN_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_control_stall(void)
|
||||
{
|
||||
USBCTRL_REGS->EP_STALL_ARM = USBCTRL_REGS_EP_STALL_ARM_EP0_IN_Msk;
|
||||
USB_DPRAM->EP_BUF_CTRL[0].IN = USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_STALL_Msk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_control_send(uint8_t *data, int size)
|
||||
{
|
||||
while (size)
|
||||
{
|
||||
int transfer_size = LIMIT(size, usb_device_descriptor.bMaxPacketSize0);
|
||||
|
||||
for (int i = 0; i < transfer_size; i++)
|
||||
usb_ep[0].in_buf[i] = data[i];
|
||||
|
||||
usb_start_in_transfer(0, transfer_size);
|
||||
|
||||
while (0 == (USBCTRL_REGS->BUFF_STATUS & USBCTRL_REGS_BUFF_STATUS_EP0_IN_Msk));
|
||||
USBCTRL_REGS->BUFF_STATUS = USBCTRL_REGS_BUFF_STATUS_EP0_IN_Msk;
|
||||
|
||||
size -= transfer_size;
|
||||
data += transfer_size;
|
||||
}
|
||||
|
||||
usb_start_out_transfer(0, USB_CTRL_EP_SIZE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_control_recv(void (*callback)(uint8_t *data, int size))
|
||||
{
|
||||
usb_control_recv_callback = callback;
|
||||
|
||||
usb_start_out_transfer(0, USB_CTRL_EP_SIZE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_task(void)
|
||||
{
|
||||
uint32_t status = USBCTRL_REGS->INTS;
|
||||
uint32_t flags;
|
||||
|
||||
if (status & USBCTRL_REGS_INTS_BUS_RESET_Msk)
|
||||
{
|
||||
USBCTRL_REGS_CLR->SIE_STATUS = USBCTRL_REGS_SIE_STATUS_BUS_RESET_Msk;
|
||||
USBCTRL_REGS->ADDR_ENDP = 0;
|
||||
|
||||
usb_reset_endpoints();
|
||||
|
||||
usb_ep[0].in_buf = (volatile uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_FIXED_SIZE);
|
||||
usb_ep[0].out_buf = (volatile uint8_t *)(USBCTRL_DPRAM_BASE + USB_DPRAM_FIXED_SIZE);
|
||||
}
|
||||
|
||||
if (status & USBCTRL_REGS_INTS_SETUP_REQ_Msk)
|
||||
{
|
||||
usb_request_t *request = (usb_request_t *)USBCTRL_DPRAM;
|
||||
|
||||
usb_ep[0].in_pid = 1;
|
||||
usb_ep[0].out_pid = 1;
|
||||
|
||||
USBCTRL_REGS_CLR->SIE_STATUS = USBCTRL_REGS_SIE_STATUS_SETUP_REC_Msk;
|
||||
|
||||
if (!usb_handle_standard_request(request))
|
||||
usb_control_stall();
|
||||
}
|
||||
|
||||
if (status & USBCTRL_REGS_INTS_BUFF_STATUS_Msk)
|
||||
{
|
||||
status = USBCTRL_REGS->BUFF_STATUS;
|
||||
|
||||
if (status & USBCTRL_REGS_BUFF_STATUS_EP0_OUT_Msk)
|
||||
{
|
||||
int size = USB_DPRAM->EP_BUF_CTRL[0].OUT & USBCTRL_DPRAM_EP0_OUT_BUFFER_CONTROL_LENGTH_0_Msk;
|
||||
|
||||
if (usb_control_recv_callback)
|
||||
{
|
||||
usb_control_recv_callback((uint8_t *)usb_ep[0].out_buf, size);
|
||||
usb_control_recv_callback = NULL;
|
||||
usb_control_send_zlp();
|
||||
}
|
||||
}
|
||||
|
||||
flags = status >> 2;
|
||||
|
||||
for (int ep = 1; ep < USB_EP_NUM && flags > 0; ep++)
|
||||
{
|
||||
if (flags & 1) // IN
|
||||
{
|
||||
usb_send_callback(ep);
|
||||
}
|
||||
|
||||
if (flags & 2) // OUT
|
||||
{
|
||||
int size = USB_DPRAM->EP_BUF_CTRL[ep].OUT & USBCTRL_DPRAM_EP0_OUT_BUFFER_CONTROL_LENGTH_0_Msk;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
usb_ep[ep].out_data[i] = usb_ep[ep].out_buf[i];
|
||||
|
||||
usb_recv_callback(ep, size);
|
||||
}
|
||||
|
||||
flags >>= 2;
|
||||
}
|
||||
|
||||
USBCTRL_REGS->BUFF_STATUS = status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
36
platform/rp2040/usb.h
Normal file
36
platform/rp2040/usb.h
Normal file
@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2016-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _USB_H_
|
||||
#define _USB_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define USB_EP_NUM 16
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
void usb_hw_init(void);
|
||||
void usb_attach(void);
|
||||
void usb_detach(void);
|
||||
void usb_configure_endpoint(usb_endpoint_descriptor_t *ep_desc);
|
||||
bool usb_endpoint_configured(int ep, int dir);
|
||||
int usb_endpoint_get_status(int ep, int dir);
|
||||
void usb_endpoint_set_feature(int ep, int dir);
|
||||
void usb_endpoint_clear_feature(int ep, int dir);
|
||||
void usb_set_address(int address);
|
||||
void usb_send(int ep, uint8_t *data, int size);
|
||||
void usb_recv(int ep, uint8_t *data, int size);
|
||||
void usb_control_send_zlp(void);
|
||||
void usb_control_stall(void);
|
||||
void usb_control_send(uint8_t *data, int size);
|
||||
void usb_control_recv(void (*callback)(uint8_t *data, int size));
|
||||
void usb_task(void);
|
||||
|
||||
void usb_configuration_callback(int config);
|
||||
|
||||
#endif // _USB_H_
|
||||
|
||||
198
platform/rp2040/usb_cdc.c
Normal file
198
platform/rp2040/usb_cdc.c
Normal file
@ -0,0 +1,198 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2017-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdbool.h>
|
||||
#include <stdalign.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
#include "usb.h"
|
||||
#include "usb_std.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define ONE_SHOT_STATES (USB_CDC_SERIAL_STATE_BREAK | USB_CDC_SERIAL_STATE_RING | \
|
||||
USB_CDC_SERIAL_STATE_FRAMING | USB_CDC_SERIAL_STATE_PARITY | USB_CDC_SERIAL_STATE_OVERRUN)
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
static void usb_cdc_send_state_notify(void);
|
||||
static void usb_cdc_ep_comm_callback(int size);
|
||||
static void usb_cdc_ep_send_callback(int size);
|
||||
static void usb_cdc_ep_recv_callback(int size);
|
||||
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
static usb_cdc_line_coding_t usb_cdc_line_coding =
|
||||
{
|
||||
.dwDTERate = 115200,
|
||||
.bCharFormat = USB_CDC_1_STOP_BIT,
|
||||
.bParityType = USB_CDC_NO_PARITY,
|
||||
.bDataBits = USB_CDC_8_DATA_BITS,
|
||||
};
|
||||
|
||||
static alignas(4) usb_cdc_notify_serial_state_t usb_cdc_notify_message;
|
||||
static int usb_cdc_serial_state;
|
||||
static bool usb_cdc_comm_busy;
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_init(void)
|
||||
{
|
||||
usb_set_callback(USB_CDC_EP_COMM, usb_cdc_ep_comm_callback);
|
||||
usb_set_callback(USB_CDC_EP_SEND, usb_cdc_ep_send_callback);
|
||||
usb_set_callback(USB_CDC_EP_RECV, usb_cdc_ep_recv_callback);
|
||||
|
||||
usb_cdc_notify_message.request.bmRequestType = USB_IN_TRANSFER |
|
||||
USB_INTERFACE_RECIPIENT | USB_CLASS_REQUEST;
|
||||
usb_cdc_notify_message.request.bRequest = USB_CDC_NOTIFY_SERIAL_STATE;
|
||||
usb_cdc_notify_message.request.wValue = 0;
|
||||
usb_cdc_notify_message.request.wIndex = 0;
|
||||
usb_cdc_notify_message.request.wLength = sizeof(uint16_t);
|
||||
usb_cdc_notify_message.value = 0;
|
||||
|
||||
usb_cdc_serial_state = 0;
|
||||
usb_cdc_comm_busy = false;
|
||||
|
||||
usb_cdc_line_coding_updated(&usb_cdc_line_coding);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_send(uint8_t *data, int size)
|
||||
{
|
||||
usb_send(USB_CDC_EP_SEND, data, size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_recv(uint8_t *data, int size)
|
||||
{
|
||||
usb_recv(USB_CDC_EP_RECV, data, size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_set_state(int mask)
|
||||
{
|
||||
usb_cdc_serial_state |= mask;
|
||||
|
||||
usb_cdc_send_state_notify();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_cdc_clear_state(int mask)
|
||||
{
|
||||
usb_cdc_serial_state &= ~mask;
|
||||
|
||||
usb_cdc_send_state_notify();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
usb_cdc_line_coding_t *usb_cdc_get_line_coding(void)
|
||||
{
|
||||
return &usb_cdc_line_coding;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_cdc_send_state_notify(void)
|
||||
{
|
||||
if (usb_cdc_comm_busy)
|
||||
return;
|
||||
|
||||
if (usb_cdc_serial_state != usb_cdc_notify_message.value)
|
||||
{
|
||||
usb_cdc_comm_busy = true;
|
||||
usb_cdc_notify_message.value = usb_cdc_serial_state;
|
||||
usb_cdc_serial_state &= ~ONE_SHOT_STATES;
|
||||
usb_send(USB_CDC_EP_COMM, (uint8_t *)&usb_cdc_notify_message, sizeof(usb_cdc_notify_serial_state_t));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_cdc_ep_comm_callback(int size)
|
||||
{
|
||||
usb_cdc_comm_busy = false;
|
||||
usb_cdc_notify_message.value &= ~ONE_SHOT_STATES;
|
||||
usb_cdc_send_state_notify();
|
||||
(void)size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_cdc_ep_send_callback(int size)
|
||||
{
|
||||
usb_cdc_send_callback();
|
||||
(void)size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_cdc_ep_recv_callback(int size)
|
||||
{
|
||||
usb_cdc_recv_callback(size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_cdc_set_line_coding_handler(uint8_t *data, int size)
|
||||
{
|
||||
usb_cdc_line_coding_t *line_coding = (usb_cdc_line_coding_t *)data;
|
||||
|
||||
if (sizeof(usb_cdc_line_coding_t) != size)
|
||||
return;
|
||||
|
||||
usb_cdc_line_coding = *line_coding;
|
||||
|
||||
usb_cdc_line_coding_updated(&usb_cdc_line_coding);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool usb_cdc_handle_request(usb_request_t *request)
|
||||
{
|
||||
int length = request->wLength;
|
||||
|
||||
switch ((request->bRequest << 8) | request->bmRequestType)
|
||||
{
|
||||
case USB_CMD(OUT, INTERFACE, CLASS, CDC_SET_LINE_CODING):
|
||||
{
|
||||
length = LIMIT(length, sizeof(usb_cdc_line_coding_t));
|
||||
|
||||
usb_control_recv(usb_cdc_set_line_coding_handler);
|
||||
} break;
|
||||
|
||||
case USB_CMD(IN, INTERFACE, CLASS, CDC_GET_LINE_CODING):
|
||||
{
|
||||
length = LIMIT(length, sizeof(usb_cdc_line_coding_t));
|
||||
|
||||
usb_control_send((uint8_t *)&usb_cdc_line_coding, length);
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, INTERFACE, CLASS, CDC_SET_CONTROL_LINE_STATE):
|
||||
{
|
||||
usb_cdc_control_line_state_update(request->wValue);
|
||||
|
||||
usb_control_send_zlp();
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, INTERFACE, CLASS, CDC_SEND_BREAK):
|
||||
{
|
||||
usb_cdc_send_break(request->wValue);
|
||||
|
||||
usb_control_send_zlp();
|
||||
} break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
WEAK void usb_cdc_control_line_state_update(int line_state)
|
||||
{
|
||||
(void)line_state;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
WEAK void usb_cdc_send_break(int duration)
|
||||
{
|
||||
(void)duration;
|
||||
}
|
||||
|
||||
|
||||
211
platform/rp2040/usb_cdc.h
Normal file
211
platform/rp2040/usb_cdc.h
Normal file
@ -0,0 +1,211 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2017-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _USB_CDC_H_
|
||||
#define _USB_CDC_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "utils.h"
|
||||
#include "usb_std.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
USB_CDC_SEND_ENCAPSULATED_COMMAND = 0x00,
|
||||
USB_CDC_GET_ENCAPSULATED_RESPONSE = 0x01,
|
||||
USB_CDC_SET_COMM_FEATURE = 0x02,
|
||||
USB_CDC_GET_COMM_FEATURE = 0x03,
|
||||
USB_CDC_CLEAR_COMM_FEATURE = 0x04,
|
||||
USB_CDC_SET_AUX_LINE_STATE = 0x10,
|
||||
USB_CDC_SET_HOOK_STATE = 0x11,
|
||||
USB_CDC_PULSE_SETUP = 0x12,
|
||||
USB_CDC_SEND_PULSE = 0x13,
|
||||
USB_CDC_SET_PULSE_TIME = 0x14,
|
||||
USB_CDC_RING_AUX_JACK = 0x15,
|
||||
USB_CDC_SET_LINE_CODING = 0x20,
|
||||
USB_CDC_GET_LINE_CODING = 0x21,
|
||||
USB_CDC_SET_CONTROL_LINE_STATE = 0x22,
|
||||
USB_CDC_SEND_BREAK = 0x23,
|
||||
USB_CDC_SET_RINGER_PARMS = 0x30,
|
||||
USB_CDC_GET_RINGER_PARMS = 0x31,
|
||||
USB_CDC_SET_OPERATION_PARMS = 0x32,
|
||||
USB_CDC_GET_OPERATION_PARMS = 0x33,
|
||||
USB_CDC_SET_LINE_PARMS = 0x34,
|
||||
USB_CDC_GET_LINE_PARMS = 0x35,
|
||||
USB_CDC_DIAL_DIGITS = 0x36,
|
||||
USB_CDC_SET_UNIT_PARAMETER = 0x37,
|
||||
USB_CDC_GET_UNIT_PARAMETER = 0x38,
|
||||
USB_CDC_CLEAR_UNIT_PARAMETER = 0x39,
|
||||
USB_CDC_GET_PROFILE = 0x3a,
|
||||
|
||||
USB_CDC_NOTIFY_RING_DETECT = 0x09,
|
||||
USB_CDC_NOTIFY_SERIAL_STATE = 0x20,
|
||||
USB_CDC_NOTIFY_CALL_STATE_CHANGE = 0x28,
|
||||
USB_CDC_NOTIFY_LINE_STATE_CHANGE = 0x29,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_1_STOP_BIT = 0,
|
||||
USB_CDC_1_5_STOP_BITS = 1,
|
||||
USB_CDC_2_STOP_BITS = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_NO_PARITY = 0,
|
||||
USB_CDC_ODD_PARITY = 1,
|
||||
USB_CDC_EVEN_PARITY = 2,
|
||||
USB_CDC_MARK_PARITY = 3,
|
||||
USB_CDC_SPACE_PARITY = 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_5_DATA_BITS = 5,
|
||||
USB_CDC_6_DATA_BITS = 6,
|
||||
USB_CDC_7_DATA_BITS = 7,
|
||||
USB_CDC_8_DATA_BITS = 8,
|
||||
USB_CDC_16_DATA_BITS = 16,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_DEVICE_CLASS = 2, // USB Communication Device Class
|
||||
USB_CDC_COMM_CLASS = 2, // CDC Communication Class Interface
|
||||
USB_CDC_DATA_CLASS = 10, // CDC Data Class Interface
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_NO_SUBCLASS = 0,
|
||||
USB_CDC_DLCM_SUBCLASS = 1, // Direct Line Control Model
|
||||
USB_CDC_ACM_SUBCLASS = 2, // Abstract Control Model
|
||||
USB_CDC_TCM_SUBCLASS = 3, // Telephone Control Model
|
||||
USB_CDC_MCCM_SUBCLASS = 4, // Multi-Channel Control Model
|
||||
USB_CDC_CCM_SUBCLASS = 5, // CAPI Control Model
|
||||
USB_CDC_ETH_SUBCLASS = 6, // Ethernet Networking Control Model
|
||||
USB_CDC_ATM_SUBCLASS = 7, // ATM Networking Control Model
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_HEADER_SUBTYPE = 0, // Header Functional Descriptor
|
||||
USB_CDC_CALL_MGMT_SUBTYPE = 1, // Call Management
|
||||
USB_CDC_ACM_SUBTYPE = 2, // Abstract Control Management
|
||||
USB_CDC_UNION_SUBTYPE = 6, // Union Functional Descriptor
|
||||
};
|
||||
|
||||
// USB CDC Call Management Capabilities
|
||||
enum
|
||||
{
|
||||
USB_CDC_CALL_MGMT_SUPPORTED = (1 << 0),
|
||||
USB_CDC_CALL_MGMT_OVER_DCI = (1 << 1),
|
||||
};
|
||||
|
||||
// USB CDC ACM Capabilities
|
||||
enum
|
||||
{
|
||||
// Device supports the request combination of Set_Comm_Feature,
|
||||
// Clear_Comm_Feature, and Get_Comm_Feature.
|
||||
USB_CDC_ACM_SUPPORT_FEATURE_REQUESTS = (1 << 0),
|
||||
|
||||
// Device supports the request combination of Set_Line_Coding, Set_Control_Line_State,
|
||||
// Get_Line_Coding, and the notification Serial_State.
|
||||
USB_CDC_ACM_SUPPORT_LINE_REQUESTS = (1 << 1),
|
||||
|
||||
// Device supports the request Send_Break.
|
||||
USB_CDC_ACM_SUPPORT_SENDBREAK_REQUESTS = (1 << 2),
|
||||
|
||||
// Device supports the notification Network_Connection.
|
||||
USB_CDC_ACM_SUPPORT_NOTIFY_REQUESTS = (1 << 3),
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_CTRL_SIGNAL_DTE_PRESENT = (1 << 0), // DTR
|
||||
USB_CDC_CTRL_SIGNAL_ACTIVATE_CARRIER = (1 << 1), // RTS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CDC_SERIAL_STATE_DCD = (1 << 0),
|
||||
USB_CDC_SERIAL_STATE_DSR = (1 << 1),
|
||||
USB_CDC_SERIAL_STATE_BREAK = (1 << 2),
|
||||
USB_CDC_SERIAL_STATE_RING = (1 << 3),
|
||||
USB_CDC_SERIAL_STATE_FRAMING = (1 << 4),
|
||||
USB_CDC_SERIAL_STATE_PARITY = (1 << 5),
|
||||
USB_CDC_SERIAL_STATE_OVERRUN = (1 << 6),
|
||||
};
|
||||
|
||||
#define USB_CDC_BREAK_DURATION_DISABLE 0
|
||||
#define USB_CDC_BREAK_DURATION_INFINITE 0xffff
|
||||
|
||||
/*- Types -------------------------------------------------------------------*/
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bFunctionalLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint16_t bcdCDC;
|
||||
} usb_cdc_header_functional_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bFunctionalLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bmCapabilities;
|
||||
} usb_cdc_abstract_control_managment_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bFunctionalLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bmCapabilities;
|
||||
uint8_t bDataInterface;
|
||||
} usb_cdc_call_managment_functional_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bFunctionalLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bMasterInterface;
|
||||
uint8_t bSlaveInterface0;
|
||||
} usb_cdc_union_functional_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint32_t dwDTERate;
|
||||
uint8_t bCharFormat;
|
||||
uint8_t bParityType;
|
||||
uint8_t bDataBits;
|
||||
} usb_cdc_line_coding_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
usb_request_t request;
|
||||
uint16_t value;
|
||||
} usb_cdc_notify_serial_state_t;
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
void usb_cdc_init(void);
|
||||
bool usb_cdc_handle_request(usb_request_t *request);
|
||||
void usb_cdc_send(uint8_t *data, int size);
|
||||
void usb_cdc_recv(uint8_t *data, int size);
|
||||
void usb_cdc_set_state(int mask);
|
||||
void usb_cdc_clear_state(int mask);
|
||||
usb_cdc_line_coding_t *usb_cdc_get_line_coding(void);
|
||||
|
||||
void usb_cdc_send_callback(void);
|
||||
void usb_cdc_recv_callback(int size);
|
||||
void usb_cdc_line_coding_updated(usb_cdc_line_coding_t *line_coding);
|
||||
void usb_cdc_control_line_state_update(int line_state);
|
||||
void usb_cdc_send_break(int duration);
|
||||
|
||||
#endif // _USB_CDC_H_
|
||||
|
||||
225
platform/rp2040/usb_descriptors.c
Normal file
225
platform/rp2040/usb_descriptors.c
Normal file
@ -0,0 +1,225 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2017-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdalign.h>
|
||||
#include "usb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
const alignas(4) usb_device_descriptor_t usb_device_descriptor =
|
||||
{
|
||||
.bLength = sizeof(usb_device_descriptor_t),
|
||||
.bDescriptorType = USB_DEVICE_DESCRIPTOR,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = USB_DEVICE_CLASS_MISCELLANEOUS,
|
||||
.bDeviceSubClass = USB_DEVICE_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = USB_DEVICE_PROTOCOL_INTERFACE_ASSOCIATION,
|
||||
.bMaxPacketSize0 = USB_CTRL_EP_SIZE,
|
||||
.idVendor = 0x6666,
|
||||
.idProduct = 0x6600,
|
||||
.bcdDevice = 0x0101,
|
||||
.iManufacturer = USB_STR_MANUFACTURER,
|
||||
.iProduct = USB_STR_PRODUCT,
|
||||
.iSerialNumber = USB_STR_SERIAL_NUMBER,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
|
||||
{
|
||||
.configuration =
|
||||
{
|
||||
.bLength = sizeof(usb_configuration_descriptor_t),
|
||||
.bDescriptorType = USB_CONFIGURATION_DESCRIPTOR,
|
||||
.wTotalLength = sizeof(usb_configuration_hierarchy_t),
|
||||
.bNumInterfaces = 3,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 250, // 500 mA
|
||||
},
|
||||
|
||||
.hid_interface =
|
||||
{
|
||||
.bLength = sizeof(usb_interface_descriptor_t),
|
||||
.bDescriptorType = USB_INTERFACE_DESCRIPTOR,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_HID_DEVICE_CLASS,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = USB_STR_CMSIS_DAP,
|
||||
},
|
||||
|
||||
.hid =
|
||||
{
|
||||
.bLength = sizeof(usb_hid_descriptor_t),
|
||||
.bDescriptorType = USB_HID_DESCRIPTOR,
|
||||
.bcdHID = 0x0111,
|
||||
.bCountryCode = 0,
|
||||
.bNumDescriptors = 1,
|
||||
.bDescriptorType1 = USB_HID_REPORT_DESCRIPTOR,
|
||||
.wDescriptorLength = sizeof(usb_hid_report_descriptor),
|
||||
},
|
||||
|
||||
.hid_ep_in =
|
||||
{
|
||||
.bLength = sizeof(usb_endpoint_descriptor_t),
|
||||
.bDescriptorType = USB_ENDPOINT_DESCRIPTOR,
|
||||
.bEndpointAddress = USB_IN_ENDPOINT | USB_HID_EP_SEND,
|
||||
.bmAttributes = USB_INTERRUPT_ENDPOINT,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
},
|
||||
|
||||
.hid_ep_out =
|
||||
{
|
||||
.bLength = sizeof(usb_endpoint_descriptor_t),
|
||||
.bDescriptorType = USB_ENDPOINT_DESCRIPTOR,
|
||||
.bEndpointAddress = USB_OUT_ENDPOINT | USB_HID_EP_RECV,
|
||||
.bmAttributes = USB_INTERRUPT_ENDPOINT,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
},
|
||||
|
||||
.iad =
|
||||
{
|
||||
.bLength = sizeof(usb_interface_association_descriptor_t),
|
||||
.bDescriptorType = USB_INTERFACE_ASSOCIATION_DESCRIPTOR,
|
||||
.bFirstInterface = 1,
|
||||
.bInterfaceCount = 2,
|
||||
.bFunctionClass = USB_CDC_COMM_CLASS,
|
||||
.bFunctionSubClass = USB_CDC_ACM_SUBCLASS,
|
||||
.bFunctionProtocol = 0,
|
||||
.iFunction = USB_STR_COM_PORT,
|
||||
},
|
||||
|
||||
.interface_comm =
|
||||
{
|
||||
.bLength = sizeof(usb_interface_descriptor_t),
|
||||
.bDescriptorType = USB_INTERFACE_DESCRIPTOR,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CDC_COMM_CLASS,
|
||||
.bInterfaceSubClass = USB_CDC_ACM_SUBCLASS,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = 0,
|
||||
},
|
||||
|
||||
.cdc_header =
|
||||
{
|
||||
.bFunctionalLength = sizeof(usb_cdc_header_functional_descriptor_t),
|
||||
.bDescriptorType = USB_CS_INTERFACE_DESCRIPTOR,
|
||||
.bDescriptorSubtype = USB_CDC_HEADER_SUBTYPE,
|
||||
.bcdCDC = 0x0110,
|
||||
},
|
||||
|
||||
.cdc_acm =
|
||||
{
|
||||
.bFunctionalLength = sizeof(usb_cdc_abstract_control_managment_descriptor_t),
|
||||
.bDescriptorType = USB_CS_INTERFACE_DESCRIPTOR,
|
||||
.bDescriptorSubtype = USB_CDC_ACM_SUBTYPE,
|
||||
.bmCapabilities = USB_CDC_ACM_SUPPORT_LINE_REQUESTS | USB_CDC_ACM_SUPPORT_SENDBREAK_REQUESTS,
|
||||
},
|
||||
|
||||
.cdc_call_mgmt =
|
||||
{
|
||||
.bFunctionalLength = sizeof(usb_cdc_call_managment_functional_descriptor_t),
|
||||
.bDescriptorType = USB_CS_INTERFACE_DESCRIPTOR,
|
||||
.bDescriptorSubtype = USB_CDC_CALL_MGMT_SUBTYPE,
|
||||
.bmCapabilities = USB_CDC_CALL_MGMT_OVER_DCI,
|
||||
.bDataInterface = 2,
|
||||
},
|
||||
|
||||
.cdc_union =
|
||||
{
|
||||
.bFunctionalLength = sizeof(usb_cdc_union_functional_descriptor_t),
|
||||
.bDescriptorType = USB_CS_INTERFACE_DESCRIPTOR,
|
||||
.bDescriptorSubtype = USB_CDC_UNION_SUBTYPE,
|
||||
.bMasterInterface = 1,
|
||||
.bSlaveInterface0 = 2,
|
||||
},
|
||||
|
||||
.ep_comm =
|
||||
{
|
||||
.bLength = sizeof(usb_endpoint_descriptor_t),
|
||||
.bDescriptorType = USB_ENDPOINT_DESCRIPTOR,
|
||||
.bEndpointAddress = USB_IN_ENDPOINT | USB_CDC_EP_COMM,
|
||||
.bmAttributes = USB_INTERRUPT_ENDPOINT,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
},
|
||||
|
||||
.interface_data =
|
||||
{
|
||||
.bLength = sizeof(usb_interface_descriptor_t),
|
||||
.bDescriptorType = USB_INTERFACE_DESCRIPTOR,
|
||||
.bInterfaceNumber = 2,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CDC_DATA_CLASS,
|
||||
.bInterfaceSubClass = USB_CDC_NO_SUBCLASS,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = 0,
|
||||
},
|
||||
|
||||
.ep_in =
|
||||
{
|
||||
.bLength = sizeof(usb_endpoint_descriptor_t),
|
||||
.bDescriptorType = USB_ENDPOINT_DESCRIPTOR,
|
||||
.bEndpointAddress = USB_IN_ENDPOINT | USB_CDC_EP_SEND,
|
||||
.bmAttributes = USB_BULK_ENDPOINT,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 0,
|
||||
},
|
||||
|
||||
.ep_out =
|
||||
{
|
||||
.bLength = sizeof(usb_endpoint_descriptor_t),
|
||||
.bDescriptorType = USB_ENDPOINT_DESCRIPTOR,
|
||||
.bEndpointAddress = USB_OUT_ENDPOINT | USB_CDC_EP_RECV,
|
||||
.bmAttributes = USB_BULK_ENDPOINT,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 0,
|
||||
},
|
||||
};
|
||||
|
||||
const alignas(4) uint8_t usb_hid_report_descriptor[28] =
|
||||
{
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x00, // Usage (Undefined)
|
||||
0xa1, 0x01, // Collection (Application)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xff, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x40, // Report Count (64)
|
||||
0x09, 0x00, // Usage (Undefined)
|
||||
0x81, 0x82, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x40, // Report Count (64)
|
||||
0x09, 0x00, // Usage (Undefined)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0xc0, // End Collection
|
||||
};
|
||||
|
||||
const alignas(4) usb_string_descriptor_zero_t usb_string_descriptor_zero =
|
||||
{
|
||||
.bLength = sizeof(usb_string_descriptor_zero_t),
|
||||
.bDescriptorType = USB_STRING_DESCRIPTOR,
|
||||
.wLANGID = 0x0409, // English (United States)
|
||||
};
|
||||
|
||||
char usb_serial_number[16];
|
||||
|
||||
const char *usb_strings[] =
|
||||
{
|
||||
[USB_STR_MANUFACTURER] = "Alex Taradov",
|
||||
[USB_STR_PRODUCT] = "Combined VCP and CMSIS-DAP Adapter",
|
||||
[USB_STR_COM_PORT] = "Virtual COM-Port",
|
||||
[USB_STR_CMSIS_DAP] = "CMSIS-DAP Adapter",
|
||||
[USB_STR_SERIAL_NUMBER] = usb_serial_number,
|
||||
};
|
||||
|
||||
|
||||
64
platform/rp2040/usb_descriptors.h
Normal file
64
platform/rp2040/usb_descriptors.h
Normal file
@ -0,0 +1,64 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2019-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _USB_DESCRIPTORS_H_
|
||||
#define _USB_DESCRIPTORS_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include "usb.h"
|
||||
#include "usb_std.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "usb_hid.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
USB_STR_ZERO,
|
||||
USB_STR_MANUFACTURER,
|
||||
USB_STR_PRODUCT,
|
||||
USB_STR_COM_PORT,
|
||||
USB_STR_CMSIS_DAP,
|
||||
USB_STR_SERIAL_NUMBER,
|
||||
USB_STR_COUNT,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_HID_EP_SEND = 1,
|
||||
USB_HID_EP_RECV = 2,
|
||||
USB_CDC_EP_COMM = 3,
|
||||
USB_CDC_EP_SEND = 4,
|
||||
USB_CDC_EP_RECV = 5,
|
||||
};
|
||||
|
||||
/*- Types -------------------------------------------------------------------*/
|
||||
typedef struct PACK
|
||||
{
|
||||
usb_configuration_descriptor_t configuration;
|
||||
usb_interface_descriptor_t hid_interface;
|
||||
usb_hid_descriptor_t hid;
|
||||
usb_endpoint_descriptor_t hid_ep_in;
|
||||
usb_endpoint_descriptor_t hid_ep_out;
|
||||
usb_interface_association_descriptor_t iad;
|
||||
usb_interface_descriptor_t interface_comm;
|
||||
usb_cdc_header_functional_descriptor_t cdc_header;
|
||||
usb_cdc_abstract_control_managment_descriptor_t cdc_acm;
|
||||
usb_cdc_call_managment_functional_descriptor_t cdc_call_mgmt;
|
||||
usb_cdc_union_functional_descriptor_t cdc_union;
|
||||
usb_endpoint_descriptor_t ep_comm;
|
||||
usb_interface_descriptor_t interface_data;
|
||||
usb_endpoint_descriptor_t ep_in;
|
||||
usb_endpoint_descriptor_t ep_out;
|
||||
} usb_configuration_hierarchy_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
extern const usb_device_descriptor_t usb_device_descriptor;
|
||||
extern const usb_configuration_hierarchy_t usb_configuration_hierarchy;
|
||||
extern const uint8_t usb_hid_report_descriptor[28];
|
||||
extern const usb_string_descriptor_zero_t usb_string_descriptor_zero;
|
||||
extern const char *usb_strings[];
|
||||
extern char usb_serial_number[16];
|
||||
|
||||
#endif // _USB_DESCRIPTORS_H_
|
||||
|
||||
|
||||
72
platform/rp2040/usb_hid.c
Normal file
72
platform/rp2040/usb_hid.c
Normal file
@ -0,0 +1,72 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2019-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdbool.h>
|
||||
#include <stdalign.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
#include "usb.h"
|
||||
#include "usb_std.h"
|
||||
#include "usb_hid.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
static void usb_hid_ep_send_callback(int size);
|
||||
static void usb_hid_ep_recv_callback(int size);
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_hid_init(void)
|
||||
{
|
||||
usb_set_callback(USB_HID_EP_SEND, usb_hid_ep_send_callback);
|
||||
usb_set_callback(USB_HID_EP_RECV, usb_hid_ep_recv_callback);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_hid_send(uint8_t *data, int size)
|
||||
{
|
||||
usb_send(USB_HID_EP_SEND, data, size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_hid_recv(uint8_t *data, int size)
|
||||
{
|
||||
usb_recv(USB_HID_EP_RECV, data, size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_hid_ep_send_callback(int size)
|
||||
{
|
||||
usb_hid_send_callback();
|
||||
(void)size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void usb_hid_ep_recv_callback(int size)
|
||||
{
|
||||
usb_hid_recv_callback(size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool usb_hid_handle_request(usb_request_t *request)
|
||||
{
|
||||
int length = request->wLength;
|
||||
|
||||
switch ((request->bRequest << 8) | request->bmRequestType)
|
||||
{
|
||||
case USB_CMD(IN, INTERFACE, STANDARD, GET_DESCRIPTOR):
|
||||
{
|
||||
length = LIMIT(length, sizeof(usb_hid_report_descriptor));
|
||||
|
||||
usb_control_send((uint8_t *)usb_hid_report_descriptor, length);
|
||||
} break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
48
platform/rp2040/usb_hid.h
Normal file
48
platform/rp2040/usb_hid.h
Normal file
@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2019-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _USB_HID_H_
|
||||
#define _USB_HID_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "utils.h"
|
||||
#include "usb_std.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
USB_HID_DESCRIPTOR = 0x21,
|
||||
USB_HID_REPORT_DESCRIPTOR = 0x22,
|
||||
USB_HID_PHYSICAL_DESCRIPTOR = 0x23,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_HID_DEVICE_CLASS = 3, // USB Human Interface Device Class
|
||||
};
|
||||
|
||||
/*- Types -------------------------------------------------------------------*/
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bDescriptorType1;
|
||||
uint16_t wDescriptorLength;
|
||||
} usb_hid_descriptor_t;
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
void usb_hid_init(void);
|
||||
bool usb_hid_handle_request(usb_request_t *request);
|
||||
void usb_hid_send(uint8_t *data, int size);
|
||||
void usb_hid_recv(uint8_t *data, int size);
|
||||
|
||||
void usb_hid_send_callback(void);
|
||||
void usb_hid_recv_callback(int size);
|
||||
|
||||
#endif // _USB_HID_H_
|
||||
|
||||
242
platform/rp2040/usb_std.c
Normal file
242
platform/rp2040/usb_std.c
Normal file
@ -0,0 +1,242 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2016-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdbool.h>
|
||||
#include <stdalign.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
#include "usb.h"
|
||||
#include "usb_std.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/*- Types -------------------------------------------------------------------*/
|
||||
typedef void (*usb_ep_callback_t)(int size);
|
||||
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
static usb_ep_callback_t usb_ep_callbacks[USB_EP_NUM];
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_init(void)
|
||||
{
|
||||
for (int i = 0; i < USB_EP_NUM; i++)
|
||||
usb_ep_callbacks[i] = NULL;
|
||||
|
||||
usb_hw_init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_set_callback(int ep, void (*callback)(int size))
|
||||
{
|
||||
usb_ep_callbacks[ep] = callback;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
WEAK bool usb_class_handle_request(usb_request_t *request)
|
||||
{
|
||||
(void)request;
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool usb_handle_standard_request(usb_request_t *request)
|
||||
{
|
||||
static int usb_config = 0;
|
||||
|
||||
switch ((request->bRequest << 8) | request->bmRequestType)
|
||||
{
|
||||
case USB_CMD(IN, DEVICE, STANDARD, GET_DESCRIPTOR):
|
||||
{
|
||||
int type = request->wValue >> 8;
|
||||
int index = request->wValue & 0xff;
|
||||
int length = request->wLength;
|
||||
|
||||
if (USB_DEVICE_DESCRIPTOR == type)
|
||||
{
|
||||
length = LIMIT(length, usb_device_descriptor.bLength);
|
||||
|
||||
usb_control_send((uint8_t *)&usb_device_descriptor, length);
|
||||
}
|
||||
else if (USB_CONFIGURATION_DESCRIPTOR == type)
|
||||
{
|
||||
length = LIMIT(length, usb_configuration_hierarchy.configuration.wTotalLength);
|
||||
|
||||
usb_control_send((uint8_t *)&usb_configuration_hierarchy, length);
|
||||
}
|
||||
else if (USB_STRING_DESCRIPTOR == type)
|
||||
{
|
||||
if (0 == index)
|
||||
{
|
||||
length = LIMIT(length, usb_string_descriptor_zero.bLength);
|
||||
|
||||
usb_control_send((uint8_t *)&usb_string_descriptor_zero, length);
|
||||
}
|
||||
else if (index < USB_STR_COUNT)
|
||||
{
|
||||
const char *str = usb_strings[index];
|
||||
int len = strlen(str);
|
||||
int size = len*2 + 2;
|
||||
alignas(4) uint8_t buf[size];
|
||||
|
||||
buf[0] = size;
|
||||
buf[1] = USB_STRING_DESCRIPTOR;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
buf[2 + i*2] = str[i];
|
||||
buf[3 + i*2] = 0;
|
||||
}
|
||||
|
||||
length = LIMIT(length, size);
|
||||
|
||||
usb_control_send(buf, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, DEVICE, STANDARD, SET_ADDRESS):
|
||||
{
|
||||
usb_control_send_zlp();
|
||||
usb_set_address(request->wValue);
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, DEVICE, STANDARD, SET_CONFIGURATION):
|
||||
{
|
||||
usb_config = request->wValue;
|
||||
|
||||
usb_control_send_zlp();
|
||||
|
||||
if (usb_config)
|
||||
{
|
||||
int size = usb_configuration_hierarchy.configuration.wTotalLength;
|
||||
usb_descriptor_header_t *desc = (usb_descriptor_header_t *)&usb_configuration_hierarchy;
|
||||
|
||||
while (size)
|
||||
{
|
||||
if (USB_ENDPOINT_DESCRIPTOR == desc->bDescriptorType)
|
||||
usb_configure_endpoint((usb_endpoint_descriptor_t *)desc);
|
||||
|
||||
size -= desc->bLength;
|
||||
desc = (usb_descriptor_header_t *)((uint8_t *)desc + desc->bLength);
|
||||
}
|
||||
|
||||
usb_configuration_callback(usb_config);
|
||||
}
|
||||
} break;
|
||||
|
||||
case USB_CMD(IN, DEVICE, STANDARD, GET_CONFIGURATION):
|
||||
{
|
||||
uint8_t config = usb_config;
|
||||
usb_control_send(&config, sizeof(config));
|
||||
} break;
|
||||
|
||||
case USB_CMD(IN, DEVICE, STANDARD, GET_STATUS):
|
||||
case USB_CMD(IN, INTERFACE, STANDARD, GET_STATUS):
|
||||
{
|
||||
uint16_t status = 0;
|
||||
usb_control_send((uint8_t *)&status, sizeof(status));
|
||||
} break;
|
||||
|
||||
case USB_CMD(IN, ENDPOINT, STANDARD, GET_STATUS):
|
||||
{
|
||||
int ep = request->wIndex & USB_INDEX_MASK;
|
||||
int dir = request->wIndex & USB_DIRECTION_MASK;
|
||||
uint16_t status = 0;
|
||||
|
||||
if (usb_endpoint_configured(ep, dir))
|
||||
{
|
||||
status = usb_endpoint_get_status(ep, dir);
|
||||
usb_control_send((uint8_t *)&status, sizeof(status));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, DEVICE, STANDARD, SET_FEATURE):
|
||||
{
|
||||
return false;
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, INTERFACE, STANDARD, SET_FEATURE):
|
||||
{
|
||||
usb_control_send_zlp();
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, ENDPOINT, STANDARD, SET_FEATURE):
|
||||
{
|
||||
int ep = request->wIndex & USB_INDEX_MASK;
|
||||
int dir = request->wIndex & USB_DIRECTION_MASK;
|
||||
|
||||
if (0 == request->wValue && ep && usb_endpoint_configured(ep, dir))
|
||||
{
|
||||
usb_endpoint_set_feature(ep, dir);
|
||||
usb_control_send_zlp();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, DEVICE, STANDARD, CLEAR_FEATURE):
|
||||
{
|
||||
return false;
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, INTERFACE, STANDARD, CLEAR_FEATURE):
|
||||
{
|
||||
usb_control_send_zlp();
|
||||
} break;
|
||||
|
||||
case USB_CMD(OUT, ENDPOINT, STANDARD, CLEAR_FEATURE):
|
||||
{
|
||||
int ep = request->wIndex & USB_INDEX_MASK;
|
||||
int dir = request->wIndex & USB_DIRECTION_MASK;
|
||||
|
||||
if (0 == request->wValue && ep && usb_endpoint_configured(ep, dir))
|
||||
{
|
||||
usb_endpoint_clear_feature(ep, dir);
|
||||
usb_control_send_zlp();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
if (!usb_class_handle_request(request))
|
||||
return false;
|
||||
} break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_send_callback(int ep)
|
||||
{
|
||||
if (usb_ep_callbacks[ep])
|
||||
usb_ep_callbacks[ep](0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void usb_recv_callback(int ep, int size)
|
||||
{
|
||||
if (usb_ep_callbacks[ep])
|
||||
usb_ep_callbacks[ep](size);
|
||||
}
|
||||
|
||||
216
platform/rp2040/usb_std.h
Normal file
216
platform/rp2040/usb_std.h
Normal file
@ -0,0 +1,216 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2016-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _USB_STD_H_
|
||||
#define _USB_STD_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "utils.h"
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
USB_GET_STATUS = 0,
|
||||
USB_CLEAR_FEATURE = 1,
|
||||
USB_SET_FEATURE = 3,
|
||||
USB_SET_ADDRESS = 5,
|
||||
USB_GET_DESCRIPTOR = 6,
|
||||
USB_SET_DESCRIPTOR = 7,
|
||||
USB_GET_CONFIGURATION = 8,
|
||||
USB_SET_CONFIGURATION = 9,
|
||||
USB_GET_INTERFACE = 10,
|
||||
USB_SET_INTERFACE = 11,
|
||||
USB_SYNCH_FRAME = 12,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_DEVICE_DESCRIPTOR = 1,
|
||||
USB_CONFIGURATION_DESCRIPTOR = 2,
|
||||
USB_STRING_DESCRIPTOR = 3,
|
||||
USB_INTERFACE_DESCRIPTOR = 4,
|
||||
USB_ENDPOINT_DESCRIPTOR = 5,
|
||||
USB_DEVICE_QUALIFIER_DESCRIPTOR = 6,
|
||||
USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR = 7,
|
||||
USB_INTERFACE_POWER_DESCRIPTOR = 8,
|
||||
USB_OTG_DESCRIPTOR = 9,
|
||||
USB_DEBUG_DESCRIPTOR = 10,
|
||||
USB_INTERFACE_ASSOCIATION_DESCRIPTOR = 11,
|
||||
USB_BINARY_OBJECT_STORE_DESCRIPTOR = 15,
|
||||
USB_DEVICE_CAPABILITY_DESCRIPTOR = 16,
|
||||
USB_CS_INTERFACE_DESCRIPTOR = 36,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_DEVICE_RECIPIENT = 0,
|
||||
USB_INTERFACE_RECIPIENT = 1,
|
||||
USB_ENDPOINT_RECIPIENT = 2,
|
||||
USB_OTHER_RECIPIENT = 3,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_STANDARD_REQUEST = 0,
|
||||
USB_CLASS_REQUEST = 1,
|
||||
USB_VENDOR_REQUEST = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_OUT_TRANSFER = 0,
|
||||
USB_IN_TRANSFER = 1,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_IN_ENDPOINT = 0x80,
|
||||
USB_OUT_ENDPOINT = 0x00,
|
||||
USB_INDEX_MASK = 0x7f,
|
||||
USB_DIRECTION_MASK = 0x80,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_CONTROL_ENDPOINT = 0 << 0,
|
||||
USB_ISOCHRONOUS_ENDPOINT = 1 << 0,
|
||||
USB_BULK_ENDPOINT = 2 << 0,
|
||||
USB_INTERRUPT_ENDPOINT = 3 << 0,
|
||||
|
||||
USB_NO_SYNCHRONIZATION = 0 << 2,
|
||||
USB_ASYNCHRONOUS = 1 << 2,
|
||||
USB_ADAPTIVE = 2 << 2,
|
||||
USB_SYNCHRONOUS = 3 << 2,
|
||||
|
||||
USB_DATA_ENDPOINT = 0 << 4,
|
||||
USB_FEEDBACK_ENDPOINT = 1 << 4,
|
||||
USB_IMP_FB_DATA_ENDPOINT = 2 << 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_DEVICE_CLASS_MISCELLANEOUS = 0xef,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_DEVICE_SUBCLASS_COMMON = 0x02,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_DEVICE_PROTOCOL_INTERFACE_ASSOCIATION = 0x01,
|
||||
};
|
||||
|
||||
#define USB_CTRL_EP_SIZE 64
|
||||
|
||||
#define USB_CMD(dir, rcpt, type, cmd) \
|
||||
((USB_##cmd << 8) | (USB_##dir##_TRANSFER << 7) | \
|
||||
(USB_##type##_REQUEST << 5) | (USB_##rcpt##_RECIPIENT << 0))
|
||||
|
||||
/*- Types -------------------------------------------------------------------*/
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} usb_request_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
} usb_descriptor_header_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} usb_device_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wTotalLength;
|
||||
uint8_t bNumInterfaces;
|
||||
uint8_t bConfigurationValue;
|
||||
uint8_t iConfiguration;
|
||||
uint8_t bmAttributes;
|
||||
uint8_t bMaxPower;
|
||||
} usb_configuration_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bAlternateSetting;
|
||||
uint8_t bNumEndpoints;
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
uint8_t iInterface;
|
||||
} usb_interface_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmAttributes;
|
||||
uint16_t wMaxPacketSize;
|
||||
uint8_t bInterval;
|
||||
} usb_endpoint_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wLANGID;
|
||||
} usb_string_descriptor_zero_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bString;
|
||||
} usb_string_descriptor_t;
|
||||
|
||||
typedef struct PACK
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bFirstInterface;
|
||||
uint8_t bInterfaceCount;
|
||||
uint8_t bFunctionClass;
|
||||
uint8_t bFunctionSubClass;
|
||||
uint8_t bFunctionProtocol;
|
||||
uint8_t iFunction;
|
||||
} usb_interface_association_descriptor_t;
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
void usb_init(void);
|
||||
void usb_set_callback(int ep, void (*callback)(int size));
|
||||
bool usb_handle_standard_request(usb_request_t *request);
|
||||
void usb_send_callback(int ep);
|
||||
void usb_recv_callback(int ep, int size);
|
||||
|
||||
#endif // _USB_STD_H_
|
||||
|
||||
14
platform/rp2040/utils.h
Normal file
14
platform/rp2040/utils.h
Normal file
@ -0,0 +1,14 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2016-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define PACK __attribute__((packed))
|
||||
#define WEAK __attribute__((weak))
|
||||
#define INLINE static inline __attribute__((always_inline))
|
||||
#define LIMIT(a, b) (((int)(a) > (int)(b)) ? (int)(b) : (int)(a))
|
||||
|
||||
#endif // _UTILS_H_
|
||||
|
||||
Loading…
Reference in New Issue
Block a user