mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
Merge branch 'master' of github.com:hathach/tinyusb into kkitayam-impl_close_all_for_khci
This commit is contained in:
commit
f39656b6d7
@ -316,6 +316,7 @@ ST STM32
|
||||
- `STM32 F411ce Black Pill <https://www.adafruit.com/product/4877>`__
|
||||
- `STM32 F411ve Discovery <https://www.st.com/en/evaluation-tools/32f411ediscovery.html>`__
|
||||
- `STM32 F412zg Discovery <https://www.st.com/en/evaluation-tools/32f412gdiscovery.html>`__
|
||||
- `STM32 F412zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f412zg.html>`__
|
||||
- `STM32 F723e Discovery <https://www.st.com/en/evaluation-tools/32f723ediscovery.html>`__
|
||||
- `STM32 F746zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f746zg.html>`__
|
||||
- `STM32 F746g Discovery <https://www.st.com/en/evaluation-tools/32f746gdiscovery.html>`__
|
||||
|
@ -35,6 +35,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -42,7 +45,7 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
@ -51,7 +54,7 @@ tusb_desc_device_t const desc_device =
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -128,6 +131,8 @@ uint8_t const desc_fs_configuration[] =
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
@ -139,7 +144,44 @@ uint8_t const desc_hs_configuration[] =
|
||||
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512),
|
||||
};
|
||||
#endif
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
|
@ -35,32 +35,35 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
@ -82,8 +85,6 @@ enum
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
|
||||
@ -126,6 +127,9 @@ enum
|
||||
|
||||
#endif
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
// full speed configuration
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
@ -139,6 +143,9 @@ uint8_t const desc_fs_configuration[] =
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// high speed configuration
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
@ -150,7 +157,54 @@ uint8_t const desc_hs_configuration[] =
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
};
|
||||
#endif
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
// Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
|
||||
memcpy(desc_other_speed_config,
|
||||
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
|
||||
CONFIG_TOTAL_LEN);
|
||||
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
|
@ -35,6 +35,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -42,7 +45,7 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
@ -52,7 +55,7 @@ tusb_desc_device_t const desc_device =
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -82,8 +85,6 @@ enum
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
|
||||
@ -114,6 +115,8 @@ enum
|
||||
|
||||
#endif
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
@ -127,6 +130,9 @@ uint8_t const desc_fs_configuration[] =
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// high speed configuration
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
@ -138,7 +144,54 @@ uint8_t const desc_hs_configuration[] =
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
};
|
||||
#endif
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
// Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
|
||||
memcpy(desc_other_speed_config,
|
||||
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
|
||||
CONFIG_TOTAL_LEN);
|
||||
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
|
@ -36,6 +36,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -43,13 +46,13 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -111,12 +114,62 @@ uint8_t const desc_configuration[] =
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5)
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// other speed config is basically configuration with type = OHER_SPEED_CONFIG
|
||||
memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN);
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
// this example use the same configuration for both high and full speed mode
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// This example use the same configuration for both high and full speed mode
|
||||
return desc_configuration;
|
||||
}
|
||||
|
||||
|
@ -67,8 +67,9 @@
|
||||
// This examples use FreeRTOS
|
||||
#define CFG_TUSB_OS OPT_OS_FREERTOS
|
||||
|
||||
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
|
||||
// #define CFG_TUSB_DEBUG 0
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
|
@ -36,6 +36,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -43,13 +46,13 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -111,6 +114,54 @@ uint8_t const desc_configuration[] =
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5)
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// other speed config is basically configuration with type = OHER_SPEED_CONFIG
|
||||
memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN);
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
// this example use the same configuration for both high and full speed mode
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
|
169
hw/bsp/stm32f4/boards/stm32f412nucleo/STM32F412ZGTx_FLASH.ld
Normal file
169
hw/bsp/stm32f4/boards/stm32f412nucleo/STM32F412ZGTx_FLASH.ld
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
**
|
||||
|
||||
** File : LinkerScript.ld
|
||||
**
|
||||
** Abstract : Linker script for STM32F412ZGTx Device with
|
||||
** 1024KByte FLASH, 256KByte RAM
|
||||
**
|
||||
** Set heap size, stack size and stack location according
|
||||
** to application requirements.
|
||||
**
|
||||
** Set memory bank area and size if external memory is used.
|
||||
**
|
||||
** Target : STMicroelectronics STM32
|
||||
**
|
||||
**
|
||||
** Distribution: The file is distributed as is, without any warranty
|
||||
** of any kind.
|
||||
**
|
||||
** (c)Copyright Ac6.
|
||||
** You may use this file as-is or modify it according to the needs of your
|
||||
** project. Distribution of this file (unmodified or modified) is not
|
||||
** permitted. Ac6 permit registered System Workbench for MCU users the
|
||||
** rights to distribute the assembled, compiled & linked contents of this
|
||||
** file as part of an application binary file, provided that it is built
|
||||
** using the System Workbench for MCU toolchain.
|
||||
**
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = 0x20040000; /* end of RAM */
|
||||
/* Generate a link error if heap and stack don't fit into RAM */
|
||||
_Min_Heap_Size = 0x200; /* required amount of heap */
|
||||
_Min_Stack_Size = 0x400; /* required amount of stack */
|
||||
|
||||
/* Specify the memory areas */
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
|
||||
}
|
||||
|
||||
/* Define output sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code goes first into FLASH */
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* The program code and other data goes into FLASH */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} >FLASH
|
||||
|
||||
/* Constant data goes into FLASH */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
|
||||
.ARM : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} >FLASH
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >FLASH
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >FLASH
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >FLASH
|
||||
|
||||
/* used by the startup to initialize data */
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
/* Initialized data sections goes into RAM, load LMA copy after code */
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
} >RAM AT> FLASH
|
||||
|
||||
|
||||
/* Uninitialized data section */
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
/* This is used by the startup in order to initialize the .bss secion */
|
||||
_sbss = .; /* define a global symbol at bss start */
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
_ebss = .; /* define a global symbol at bss end */
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
/* User_heap_stack section, used to check that there is enough RAM left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(8);
|
||||
} >RAM
|
||||
|
||||
|
||||
|
||||
/* Remove information from the standard libraries */
|
||||
/DISCARD/ :
|
||||
{
|
||||
libc.a ( * )
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
|
||||
|
119
hw/bsp/stm32f4/boards/stm32f412nucleo/board.h
Normal file
119
hw/bsp/stm32f4/boards/stm32f412nucleo/board.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H_
|
||||
#define BOARD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// LED
|
||||
#define LED_PORT GPIOB
|
||||
#define LED_PIN GPIO_PIN_14
|
||||
#define LED_STATE_ON 0
|
||||
|
||||
// Button
|
||||
#define BUTTON_PORT GPIOC
|
||||
#define BUTTON_PIN GPIO_PIN_13
|
||||
#define BUTTON_STATE_ACTIVE 1
|
||||
|
||||
// UART Enable for STLink VCOM
|
||||
#define UART_DEV USART3
|
||||
#define UART_GPIO_PORT GPIOD
|
||||
#define UART_GPIO_AF GPIO_AF7_USART3
|
||||
#define UART_TX_PIN GPIO_PIN_8
|
||||
#define UART_RX_PIN GPIO_PIN_9
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// RCC Clock
|
||||
//--------------------------------------------------------------------+
|
||||
static inline void board_clock_init(void)
|
||||
{
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
||||
|
||||
/* Enable Power Control clock */
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
|
||||
/* The voltage scaling allows optimizing the power consumption when the
|
||||
* device is clocked below the maximum system frequency, to update the
|
||||
* voltage scaling value regarding system frequency refer to product
|
||||
* datasheet. */
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
|
||||
/* Enable HSE Oscillator and activate PLL with HSE as source */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = HSE_VALUE/1000000;
|
||||
RCC_OscInitStruct.PLL.PLLN = 200;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 7;
|
||||
RCC_OscInitStruct.PLL.PLLR = 2;
|
||||
HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||||
|
||||
/* Select PLLSAI output as USB clock source */
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SM = 8;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SQ = 4;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CK48;
|
||||
PeriphClkInitStruct.Clk48ClockSelection = RCC_CK48CLKSOURCE_PLLI2SQ;
|
||||
PeriphClkInitStruct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SR = 7;
|
||||
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
|
||||
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
|
||||
* clocks dividers */
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
|
||||
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
|
||||
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
|
||||
|
||||
// Enable clocks for LED, Button, Uart
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_USART3_CLK_ENABLE();
|
||||
}
|
||||
|
||||
static inline void board_vbus_sense_init(void)
|
||||
{
|
||||
// Enable VBUS sense (B device) via pin PA9
|
||||
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BOARD_H_ */
|
11
hw/bsp/stm32f4/boards/stm32f412nucleo/board.mk
Normal file
11
hw/bsp/stm32f4/boards/stm32f412nucleo/board.mk
Normal file
@ -0,0 +1,11 @@
|
||||
CFLAGS += -DSTM32F412Zx
|
||||
|
||||
LD_FILE = $(BOARD_PATH)/STM32F412ZGTx_FLASH.ld
|
||||
|
||||
SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f412zx.s
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = stm32f412zg
|
||||
|
||||
# flash target using on-board stlink
|
||||
flash: flash-stlink
|
493
hw/bsp/stm32f4/boards/stm32f412nucleo/stm32f4xx_hal_conf.h
Normal file
493
hw/bsp/stm32f4/boards/stm32f412nucleo/stm32f4xx_hal_conf.h
Normal file
@ -0,0 +1,493 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx_hal_conf_template.h
|
||||
* @author MCD Application Team
|
||||
* @brief HAL configuration file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F4xx_HAL_CONF_H
|
||||
#define __STM32F4xx_HAL_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* ########################## Module Selection ############################## */
|
||||
/**
|
||||
* @brief This is the list of modules to be used in the HAL driver
|
||||
*/
|
||||
#define HAL_MODULE_ENABLED
|
||||
/* #define HAL_ADC_MODULE_ENABLED */
|
||||
/* #define HAL_CAN_MODULE_ENABLED */
|
||||
/* #define HAL_CAN_LEGACY_MODULE_ENABLED */
|
||||
/* #define HAL_CRC_MODULE_ENABLED */
|
||||
/* #define HAL_CEC_MODULE_ENABLED */
|
||||
/* #define HAL_CRYP_MODULE_ENABLED */
|
||||
/* #define HAL_DAC_MODULE_ENABLED */
|
||||
/* #define HAL_DCMI_MODULE_ENABLED */
|
||||
#define HAL_DMA_MODULE_ENABLED
|
||||
/* #define HAL_DMA2D_MODULE_ENABLED */
|
||||
/* #define HAL_ETH_MODULE_ENABLED */
|
||||
#define HAL_FLASH_MODULE_ENABLED
|
||||
/* #define HAL_NAND_MODULE_ENABLED */
|
||||
/* #define HAL_NOR_MODULE_ENABLED */
|
||||
/* #define HAL_PCCARD_MODULE_ENABLED */
|
||||
/* #define HAL_SRAM_MODULE_ENABLED */
|
||||
/* #define HAL_SDRAM_MODULE_ENABLED */
|
||||
/* #define HAL_HASH_MODULE_ENABLED */
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
/* #define HAL_EXTI_MODULE_ENABLED */
|
||||
/* #define HAL_I2C_MODULE_ENABLED */
|
||||
/* #define HAL_SMBUS_MODULE_ENABLED */
|
||||
/* #define HAL_I2S_MODULE_ENABLED */
|
||||
/* #define HAL_IWDG_MODULE_ENABLED */
|
||||
/* #define HAL_LTDC_MODULE_ENABLED */
|
||||
/* #define HAL_DSI_MODULE_ENABLED */
|
||||
#define HAL_PWR_MODULE_ENABLED
|
||||
/* #define HAL_QSPI_MODULE_ENABLED */
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
/* #define HAL_RNG_MODULE_ENABLED */
|
||||
/* #define HAL_RTC_MODULE_ENABLED */
|
||||
/* #define HAL_SAI_MODULE_ENABLED */
|
||||
/* #define HAL_SD_MODULE_ENABLED */
|
||||
// #define HAL_SPI_MODULE_ENABLED
|
||||
/* #define HAL_TIM_MODULE_ENABLED */
|
||||
#define HAL_UART_MODULE_ENABLED
|
||||
/* #define HAL_USART_MODULE_ENABLED */
|
||||
/* #define HAL_IRDA_MODULE_ENABLED */
|
||||
/* #define HAL_SMARTCARD_MODULE_ENABLED */
|
||||
/* #define HAL_WWDG_MODULE_ENABLED */
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
/* #define HAL_PCD_MODULE_ENABLED */
|
||||
/* #define HAL_HCD_MODULE_ENABLED */
|
||||
/* #define HAL_FMPI2C_MODULE_ENABLED */
|
||||
/* #define HAL_SPDIFRX_MODULE_ENABLED */
|
||||
/* #define HAL_DFSDM_MODULE_ENABLED */
|
||||
/* #define HAL_LPTIM_MODULE_ENABLED */
|
||||
/* #define HAL_MMC_MODULE_ENABLED */
|
||||
|
||||
/* ########################## HSE/HSI Values adaptation ##################### */
|
||||
/**
|
||||
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
* (when HSE is used as system clock source, directly or through the PLL).
|
||||
*/
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE (8000000U) /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSE_STARTUP_TIMEOUT)
|
||||
#define HSE_STARTUP_TIMEOUT (100U) /*!< Time out for HSE start up, in ms */
|
||||
#endif /* HSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal High Speed oscillator (HSI) value.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
* (when HSI is used as system clock source, directly or through the PLL).
|
||||
*/
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE (16000000U) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Internal Low Speed oscillator (LSI) value.
|
||||
*/
|
||||
#if !defined (LSI_VALUE)
|
||||
#define LSI_VALUE (32000U)
|
||||
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
|
||||
The real value may vary depending on the variations
|
||||
in voltage and temperature. */
|
||||
/**
|
||||
* @brief External Low Speed oscillator (LSE) value.
|
||||
*/
|
||||
#if !defined (LSE_VALUE)
|
||||
#define LSE_VALUE (32768U) /*!< Value of the External Low Speed oscillator in Hz */
|
||||
#endif /* LSE_VALUE */
|
||||
|
||||
#if !defined (LSE_STARTUP_TIMEOUT)
|
||||
#define LSE_STARTUP_TIMEOUT (5000U) /*!< Time out for LSE start up, in ms */
|
||||
#endif /* LSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief External clock source for I2S peripheral
|
||||
* This value is used by the I2S HAL module to compute the I2S clock source
|
||||
* frequency, this source is inserted directly through I2S_CKIN pad.
|
||||
*/
|
||||
#if !defined (EXTERNAL_CLOCK_VALUE)
|
||||
#define EXTERNAL_CLOCK_VALUE (12288000U) /*!< Value of the External oscillator in Hz*/
|
||||
#endif /* EXTERNAL_CLOCK_VALUE */
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to use different HSE,
|
||||
=== you can define the HSE value in your toolchain compiler preprocessor. */
|
||||
|
||||
/* ########################### System Configuration ######################### */
|
||||
/**
|
||||
* @brief This is the HAL system configuration section
|
||||
*/
|
||||
#define VDD_VALUE (3300U) /*!< Value of VDD in mv */
|
||||
#define TICK_INT_PRIORITY (0x0FU) /*!< tick interrupt priority */
|
||||
#define USE_RTOS 0U
|
||||
#define PREFETCH_ENABLE 1U
|
||||
#define INSTRUCTION_CACHE_ENABLE 1U
|
||||
#define DATA_CACHE_ENABLE 1U
|
||||
|
||||
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
|
||||
#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */
|
||||
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
|
||||
#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */
|
||||
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
|
||||
#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */
|
||||
#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */
|
||||
#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */
|
||||
#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */
|
||||
#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
|
||||
#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */
|
||||
#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */
|
||||
#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */
|
||||
#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */
|
||||
#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */
|
||||
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */
|
||||
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */
|
||||
#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */
|
||||
#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */
|
||||
#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */
|
||||
#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */
|
||||
#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */
|
||||
#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */
|
||||
#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */
|
||||
#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */
|
||||
#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */
|
||||
#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */
|
||||
#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */
|
||||
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */
|
||||
#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */
|
||||
#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */
|
||||
#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */
|
||||
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */
|
||||
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */
|
||||
#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */
|
||||
#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */
|
||||
#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */
|
||||
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */
|
||||
|
||||
/* ########################## Assert Selection ############################## */
|
||||
/**
|
||||
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||
* HAL drivers code
|
||||
*/
|
||||
/* #define USE_FULL_ASSERT 1U */
|
||||
|
||||
/* ################## Ethernet peripheral configuration ##################### */
|
||||
|
||||
/* Section 1 : Ethernet peripheral configuration */
|
||||
|
||||
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
|
||||
#define MAC_ADDR0 2U
|
||||
#define MAC_ADDR1 0U
|
||||
#define MAC_ADDR2 0U
|
||||
#define MAC_ADDR3 0U
|
||||
#define MAC_ADDR4 0U
|
||||
#define MAC_ADDR5 0U
|
||||
|
||||
/* Definition of the Ethernet driver buffers size and count */
|
||||
#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
|
||||
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
|
||||
#define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
|
||||
#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
|
||||
|
||||
/* Section 2: PHY configuration section */
|
||||
|
||||
/* DP83848 PHY Address*/
|
||||
#define DP83848_PHY_ADDRESS 0x01U
|
||||
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
|
||||
#define PHY_RESET_DELAY 0x000000FFU
|
||||
/* PHY Configuration delay */
|
||||
#define PHY_CONFIG_DELAY 0x00000FFFU
|
||||
|
||||
#define PHY_READ_TO 0x0000FFFFU
|
||||
#define PHY_WRITE_TO 0x0000FFFFU
|
||||
|
||||
/* Section 3: Common PHY Registers */
|
||||
|
||||
#define PHY_BCR ((uint16_t)0x0000) /*!< Transceiver Basic Control Register */
|
||||
#define PHY_BSR ((uint16_t)0x0001) /*!< Transceiver Basic Status Register */
|
||||
|
||||
#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */
|
||||
#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */
|
||||
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */
|
||||
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */
|
||||
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */
|
||||
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */
|
||||
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */
|
||||
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */
|
||||
#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */
|
||||
#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */
|
||||
|
||||
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */
|
||||
#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */
|
||||
#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */
|
||||
|
||||
/* Section 4: Extended PHY Registers */
|
||||
|
||||
#define PHY_SR ((uint16_t)0x0010) /*!< PHY status register Offset */
|
||||
#define PHY_MICR ((uint16_t)0x0011) /*!< MII Interrupt Control Register */
|
||||
#define PHY_MISR ((uint16_t)0x0012) /*!< MII Interrupt Status and Misc. Control Register */
|
||||
|
||||
#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */
|
||||
#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */
|
||||
#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */
|
||||
|
||||
#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */
|
||||
#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */
|
||||
|
||||
#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */
|
||||
#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */
|
||||
|
||||
/* ################## SPI peripheral configuration ########################## */
|
||||
|
||||
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
|
||||
* Activated: CRC code is present inside driver
|
||||
* Deactivated: CRC code cleaned from driver
|
||||
*/
|
||||
|
||||
#define USE_SPI_CRC 1U
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Include module's header file
|
||||
*/
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_dma.h"
|
||||
#endif /* HAL_DMA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_cortex.h"
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_adc.h"
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CAN_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_can.h"
|
||||
#endif /* HAL_CAN_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CAN_LEGACY_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_can_legacy.h"
|
||||
#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_crc.h"
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRYP_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_cryp.h"
|
||||
#endif /* HAL_CRYP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA2D_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_dma2d.h"
|
||||
#endif /* HAL_DMA2D_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_dac.h"
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DCMI_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_dcmi.h"
|
||||
#endif /* HAL_DCMI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ETH_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_eth.h"
|
||||
#endif /* HAL_ETH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_flash.h"
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SRAM_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_sram.h"
|
||||
#endif /* HAL_SRAM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NOR_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_nor.h"
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NAND_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_nand.h"
|
||||
#endif /* HAL_NAND_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PCCARD_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_pccard.h"
|
||||
#endif /* HAL_PCCARD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SDRAM_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_sdram.h"
|
||||
#endif /* HAL_SDRAM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HASH_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_hash.h"
|
||||
#endif /* HAL_HASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_i2c.h"
|
||||
#endif /* HAL_I2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMBUS_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_smbus.h"
|
||||
#endif /* HAL_SMBUS_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2S_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_i2s.h"
|
||||
#endif /* HAL_I2S_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_iwdg.h"
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LTDC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_ltdc.h"
|
||||
#endif /* HAL_LTDC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_pwr.h"
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RNG_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_rng.h"
|
||||
#endif /* HAL_RNG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_rtc.h"
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SAI_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_sai.h"
|
||||
#endif /* HAL_SAI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SD_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_sd.h"
|
||||
#endif /* HAL_SD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_spi.h"
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_tim.h"
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_uart.h"
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_usart.h"
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IRDA_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_irda.h"
|
||||
#endif /* HAL_IRDA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMARTCARD_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_smartcard.h"
|
||||
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_wwdg.h"
|
||||
#endif /* HAL_WWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_pcd.h"
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HCD_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_hcd.h"
|
||||
#endif /* HAL_HCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DSI_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_dsi.h"
|
||||
#endif /* HAL_DSI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_QSPI_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_qspi.h"
|
||||
#endif /* HAL_QSPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CEC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_cec.h"
|
||||
#endif /* HAL_CEC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FMPI2C_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_fmpi2c.h"
|
||||
#endif /* HAL_FMPI2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPDIFRX_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_spdifrx.h"
|
||||
#endif /* HAL_SPDIFRX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DFSDM_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_dfsdm.h"
|
||||
#endif /* HAL_DFSDM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LPTIM_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_lptim.h"
|
||||
#endif /* HAL_LPTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_MMC_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_mmc.h"
|
||||
#endif /* HAL_MMC_MODULE_ENABLED */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief The assert_param macro is used for function's parameters check.
|
||||
* @param expr If expr is false, it calls assert_failed function
|
||||
* which reports the name of the source file and the source
|
||||
* line number of the call that failed.
|
||||
* If expr is true, it returns no value.
|
||||
* @retval None
|
||||
*/
|
||||
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void assert_failed(uint8_t* file, uint32_t line);
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F4xx_HAL_CONF_H */
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -214,14 +214,14 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c
|
||||
}
|
||||
else return false;
|
||||
|
||||
return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength);
|
||||
return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd));
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_DATA )
|
||||
{
|
||||
// Handle class request only
|
||||
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
|
||||
if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength);
|
||||
if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -372,7 +372,7 @@ typedef struct
|
||||
|
||||
static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key)
|
||||
{
|
||||
static char not_found[10];
|
||||
static char not_found[11];
|
||||
|
||||
for(uint16_t i=0; i<p_table->count; i++)
|
||||
{
|
||||
@ -380,7 +380,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
|
||||
}
|
||||
|
||||
// not found return the key value in hex
|
||||
sprintf(not_found, "0x%08lX", key);
|
||||
sprintf(not_found, "0x%08lX", (unsigned long) key);
|
||||
|
||||
return not_found;
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ typedef struct TU_ATTR_PACKED
|
||||
|
||||
uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration
|
||||
uint8_t bConfigurationValue ; ///< Value to use to select configuration
|
||||
uint8_t IConfiguration ; ///< Index of string descriptor
|
||||
uint8_t iConfiguration ; ///< Index of string descriptor
|
||||
uint8_t bmAttributes ; ///< Same as Configuration descriptor
|
||||
uint8_t bMaxPower ; ///< Same as Configuration descriptor
|
||||
} tusb_desc_other_speed_t;
|
||||
@ -387,11 +387,14 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t bDeviceClass ; ///< Class Code
|
||||
uint8_t bDeviceSubClass ; ///< SubClass Code
|
||||
uint8_t bDeviceProtocol ; ///< Protocol Code
|
||||
|
||||
uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed
|
||||
uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations
|
||||
uint8_t bReserved ; ///< Reserved for future use, must be zero
|
||||
} tusb_desc_device_qualifier_t;
|
||||
|
||||
TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct");
|
||||
|
||||
/// USB Interface Association Descriptor (IAD ECN)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
|
@ -1002,10 +1002,22 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
|
||||
break;
|
||||
|
||||
case TUSB_DESC_CONFIGURATION:
|
||||
case TUSB_DESC_OTHER_SPEED_CONFIG:
|
||||
{
|
||||
TU_LOG2(" Configuration[%u]\r\n", desc_index);
|
||||
tusb_desc_configuration_t const* desc_config;
|
||||
|
||||
if ( desc_type == TUSB_DESC_CONFIGURATION )
|
||||
{
|
||||
TU_LOG2(" Configuration[%u]\r\n", desc_index);
|
||||
desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index);
|
||||
}else
|
||||
{
|
||||
// Host only request this after getting Device Qualifier descriptor
|
||||
TU_LOG2(" Other Speed Configuration\r\n");
|
||||
TU_VERIFY( tud_descriptor_other_speed_configuration_cb );
|
||||
desc_config = (tusb_desc_configuration_t const*) tud_descriptor_other_speed_configuration_cb(desc_index);
|
||||
}
|
||||
|
||||
tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index);
|
||||
TU_ASSERT(desc_config);
|
||||
|
||||
// Use offsetof to avoid pointer to the odd/misaligned address
|
||||
@ -1029,29 +1041,17 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
|
||||
break;
|
||||
|
||||
case TUSB_DESC_DEVICE_QUALIFIER:
|
||||
{
|
||||
TU_LOG2(" Device Qualifier\r\n");
|
||||
|
||||
// Host sends this request to ask why our device with USB BCD from 2.0
|
||||
// but is running at Full/Low Speed. If not highspeed capable stall this request,
|
||||
// otherwise return the descriptor that could work in highspeed mode
|
||||
if ( tud_descriptor_device_qualifier_cb )
|
||||
{
|
||||
uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb();
|
||||
TU_ASSERT(desc_qualifier);
|
||||
TU_VERIFY( tud_descriptor_device_qualifier_cb );
|
||||
|
||||
// first byte of descriptor is its size
|
||||
return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]);
|
||||
}else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb();
|
||||
TU_VERIFY(desc_qualifier);
|
||||
|
||||
case TUSB_DESC_OTHER_SPEED_CONFIG:
|
||||
TU_LOG2(" Other Speed Configuration\r\n");
|
||||
|
||||
// After Device Qualifier descriptor is received host will ask for this descriptor
|
||||
return false; // not supported
|
||||
// first byte of descriptor is its size
|
||||
return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
default: return false;
|
||||
@ -1066,15 +1066,11 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
|
||||
switch (event->event_id)
|
||||
{
|
||||
case DCD_EVENT_UNPLUGGED:
|
||||
// UNPLUGGED event can be bouncing, only processing if we are currently connected
|
||||
if ( _usbd_dev.connected )
|
||||
{
|
||||
_usbd_dev.connected = 0;
|
||||
_usbd_dev.addressed = 0;
|
||||
_usbd_dev.cfg_num = 0;
|
||||
_usbd_dev.suspended = 0;
|
||||
osal_queue_send(_usbd_q, event, in_isr);
|
||||
}
|
||||
_usbd_dev.connected = 0;
|
||||
_usbd_dev.addressed = 0;
|
||||
_usbd_dev.cfg_num = 0;
|
||||
_usbd_dev.suspended = 0;
|
||||
osal_queue_send(_usbd_q, event, in_isr);
|
||||
break;
|
||||
|
||||
case DCD_EVENT_SUSPEND:
|
||||
@ -1383,7 +1379,13 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr)
|
||||
TU_ASSERT(dcd_edpt_close, /**/);
|
||||
TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr);
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
dcd_edpt_close(rhport, ep_addr);
|
||||
_usbd_dev.ep_status[epnum][dir].stalled = false;
|
||||
_usbd_dev.ep_status[epnum][dir].busy = false;
|
||||
_usbd_dev.ep_status[epnum][dir].claimed = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -113,9 +113,16 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid);
|
||||
TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void);
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void);
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index);
|
||||
|
||||
// Invoked when device is mounted (configured)
|
||||
TU_ATTR_WEAK void tud_mount_cb(void);
|
||||
|
||||
|
@ -42,10 +42,6 @@
|
||||
|
||||
#include "device/dcd.h"
|
||||
|
||||
// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
|
||||
// We disable SOF for now until needed later on
|
||||
#define USE_SOF 0
|
||||
|
||||
// Max number of bi-directional endpoints including EP0
|
||||
// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0
|
||||
// We should probably prohibit enabling Endpoint IN > 4 (not done yet)
|
||||
@ -92,11 +88,12 @@ static void bus_reset(void)
|
||||
USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK
|
||||
}
|
||||
|
||||
USB0.dcfg &= ~USB_DEVADDR_M; // reset address
|
||||
// clear device address
|
||||
USB0.dcfg &= ~USB_DEVADDR_M;
|
||||
|
||||
USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M;
|
||||
USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK;
|
||||
USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/;
|
||||
USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M;
|
||||
USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK;
|
||||
USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/;
|
||||
|
||||
// "USB Data FIFOs" section in reference manual
|
||||
// Peripheral FIFO architecture
|
||||
@ -193,9 +190,6 @@ void dcd_init(uint8_t rhport)
|
||||
USB0.gintsts = ~0U; //clear pending ints
|
||||
USB0.gintmsk = USB_OTGINTMSK_M |
|
||||
USB_MODEMISMSK_M |
|
||||
#if USE_SOF
|
||||
USB_SOFMSK_M |
|
||||
#endif
|
||||
USB_RXFLVIMSK_M |
|
||||
USB_ERLYSUSPMSK_M |
|
||||
USB_USBSUSPMSK_M |
|
||||
@ -220,8 +214,17 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
// TODO must manually clear this bit after 1-15 ms
|
||||
// USB0.DCTL |= USB_RMTWKUPSIG_M;
|
||||
// set remote wakeup
|
||||
USB0.dctl |= USB_RMTWKUPSIG_M;
|
||||
|
||||
// enable SOF to detect bus resume
|
||||
USB0.gintsts = USB_SOF_M;
|
||||
USB0.gintmsk |= USB_SOFMSK_M;
|
||||
|
||||
// Per specs: remote wakeup signal bit must be clear within 1-15ms
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
|
||||
USB0.dctl &= ~USB_RMTWKUPSIG_M;
|
||||
}
|
||||
|
||||
// connect by enabling internal pull-up resistor on D+/D-
|
||||
@ -260,9 +263,10 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
|
||||
xfer->max_size = desc_edpt->wMaxPacketSize.size;
|
||||
|
||||
if (dir == TUSB_DIR_OUT) {
|
||||
out_ep[epnum].doepctl |= USB_USBACTEP0_M |
|
||||
desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S |
|
||||
desc_edpt->wMaxPacketSize.size << USB_MPS0_S;
|
||||
out_ep[epnum].doepctl |= USB_USBACTEP1_M |
|
||||
desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S |
|
||||
(desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) |
|
||||
desc_edpt->wMaxPacketSize.size << USB_MPS1_S;
|
||||
USB0.daintmsk |= (1 << (16 + epnum));
|
||||
} else {
|
||||
// "USB Data FIFOs" section in reference manual
|
||||
@ -315,7 +319,25 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
|
||||
void dcd_edpt_close_all(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
// TODO implement dcd_edpt_close_all()
|
||||
|
||||
usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]);
|
||||
usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]);
|
||||
|
||||
// Disable non-control interrupt
|
||||
USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M;
|
||||
|
||||
for(uint8_t n = 1; n < EP_MAX; n++)
|
||||
{
|
||||
// disable OUT endpoint
|
||||
out_ep[n].doepctl = 0;
|
||||
xfer_status[n][TUSB_DIR_OUT].max_size = 0;
|
||||
|
||||
// disable IN endpoint
|
||||
in_ep[n].diepctl = 0;
|
||||
xfer_status[n][TUSB_DIR_IN].max_size = 0;
|
||||
}
|
||||
|
||||
_allocated_fifos = 1;
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
|
||||
@ -367,49 +389,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
|
||||
bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
// USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
|
||||
TU_ASSERT(ff->item_size == 1);
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
|
||||
xfer->buffer = NULL;
|
||||
xfer->ff = ff;
|
||||
xfer->total_len = total_bytes;
|
||||
xfer->queued_len = 0;
|
||||
xfer->short_packet = false;
|
||||
|
||||
uint16_t num_packets = (total_bytes / xfer->max_size);
|
||||
uint8_t short_packet_size = total_bytes % xfer->max_size;
|
||||
|
||||
// Zero-size packet is special case.
|
||||
if (short_packet_size > 0 || (total_bytes == 0)) {
|
||||
num_packets++;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i",
|
||||
epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"),
|
||||
num_packets, total_bytes);
|
||||
|
||||
// IN and OUT endpoint xfers are interrupt-driven, we just schedule them
|
||||
// here.
|
||||
if (dir == TUSB_DIR_IN) {
|
||||
// A full IN transfer (multiple packets, possibly) triggers XFRC.
|
||||
USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes;
|
||||
USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK
|
||||
|
||||
// Enable fifo empty interrupt only if there are something to put in the fifo.
|
||||
if(total_bytes != 0) {
|
||||
USB0.dtknqr4_fifoemptymsk |= (1 << epnum);
|
||||
}
|
||||
} else {
|
||||
// Each complete packet for OUT xfers triggers XFRC.
|
||||
USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S);
|
||||
USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -754,8 +733,8 @@ static void _dcd_int_handler(void* arg)
|
||||
(void) arg;
|
||||
uint8_t const rhport = 0;
|
||||
|
||||
const uint32_t int_status = USB0.gintsts;
|
||||
//const uint32_t int_msk = USB0.gintmsk;
|
||||
const uint32_t int_msk = USB0.gintmsk;
|
||||
const uint32_t int_status = USB0.gintsts & int_msk;
|
||||
|
||||
if (int_status & USB_USBRST_M) {
|
||||
// start of reset
|
||||
@ -808,12 +787,15 @@ static void _dcd_int_handler(void* arg)
|
||||
USB0.gotgint = otg_int;
|
||||
}
|
||||
|
||||
#if USE_SOF
|
||||
if (int_status & USB_SOF_M) {
|
||||
USB0.gintsts = USB_SOF_M;
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // do nothing actually
|
||||
|
||||
// Disable SOF interrupt since currently only used for remote wakeup detection
|
||||
USB0.gintmsk &= ~USB_SOFMSK_M;
|
||||
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (int_status & USB_RXFLVI_M) {
|
||||
// RXFLVL bit is read-only
|
||||
|
@ -200,11 +200,10 @@ static void bus_reset(void)
|
||||
}
|
||||
|
||||
/* centralized location for USBD interrupt enable bit mask */
|
||||
#if USE_SOF
|
||||
static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk | USBD_INTSTS_SOFIF_Msk;
|
||||
#else
|
||||
static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk;
|
||||
#endif
|
||||
enum {
|
||||
ENABLED_IRQS = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk |
|
||||
USBD_INTSTS_USBIF_Msk | (USE_SOF ? USBD_INTSTS_SOFIF_Msk : 0)
|
||||
};
|
||||
|
||||
/*
|
||||
NUC121/NUC125/NUC126 TinyUSB API driver implementation
|
||||
@ -226,8 +225,8 @@ void dcd_init(uint8_t rhport)
|
||||
|
||||
usb_attach();
|
||||
|
||||
USBD->INTSTS = enabled_irqs;
|
||||
USBD->INTEN = enabled_irqs;
|
||||
USBD->INTSTS = ENABLED_IRQS;
|
||||
USBD->INTEN = ENABLED_IRQS;
|
||||
}
|
||||
|
||||
void dcd_int_enable(uint8_t rhport)
|
||||
@ -252,10 +251,23 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
|
||||
// do it at dcd_edpt0_status_complete()
|
||||
}
|
||||
|
||||
static void remote_wakeup_delay(void)
|
||||
{
|
||||
// try to delay for 1 ms
|
||||
uint32_t count = SystemCoreClock / 1000;
|
||||
while(count--) __NOP();
|
||||
}
|
||||
|
||||
void dcd_remote_wakeup(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
USBD->ATTR = USBD_ATTR_RWAKEUP_Msk;
|
||||
// Enable PHY before sending Resume('K') state
|
||||
USBD->ATTR |= USBD_ATTR_PHYEN_Msk;
|
||||
USBD->ATTR |= USBD_ATTR_RWAKEUP_Msk;
|
||||
|
||||
// Per specs: remote wakeup signal bit must be clear within 1-15ms
|
||||
remote_wakeup_delay();
|
||||
USBD->ATTR &=~USBD_ATTR_RWAKEUP_Msk;
|
||||
}
|
||||
|
||||
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
|
||||
@ -367,14 +379,16 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
USBD_EP_T *ep = ep_entry(ep_addr, false);
|
||||
ep->CFG |= USBD_CFG_CSTALL_Msk;
|
||||
ep->CFG = (ep->CFG & ~USBD_CFG_DSQSYNC_Msk) | USBD_CFG_CSTALL_Msk;
|
||||
}
|
||||
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
uint32_t status = USBD->INTSTS;
|
||||
// Mask non-enabled irqs, ex. SOF
|
||||
uint32_t status = USBD->INTSTS & (ENABLED_IRQS | 0xffffff00);
|
||||
|
||||
#ifdef SUPPORT_LPM
|
||||
uint32_t state = USBD->ATTR & 0x300f;
|
||||
#else
|
||||
@ -505,7 +519,7 @@ void dcd_int_handler(uint8_t rhport)
|
||||
}
|
||||
|
||||
/* acknowledge all interrupts */
|
||||
USBD->INTSTS = status & enabled_irqs;
|
||||
USBD->INTSTS = status & ENABLED_IRQS;
|
||||
}
|
||||
|
||||
// Invoked when a control transfer's status stage is complete.
|
||||
|
@ -57,11 +57,15 @@
|
||||
// ENDPTCTRL
|
||||
enum {
|
||||
ENDPTCTRL_STALL = TU_BIT(0),
|
||||
ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), ///< used for test only
|
||||
ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), // used for test only
|
||||
ENDPTCTRL_TOGGLE_RESET = TU_BIT(6),
|
||||
ENDPTCTRL_ENABLE = TU_BIT(7)
|
||||
};
|
||||
|
||||
enum {
|
||||
ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field
|
||||
};
|
||||
|
||||
// USBSTS, USBINTR
|
||||
enum {
|
||||
INTR_USB = TU_BIT(0),
|
||||
@ -91,12 +95,15 @@ typedef struct
|
||||
uint32_t : 3 ;
|
||||
uint32_t int_on_complete : 1 ;
|
||||
volatile uint32_t total_bytes : 15 ;
|
||||
uint32_t : 0 ;
|
||||
uint32_t : 1 ;
|
||||
|
||||
// Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page
|
||||
uint32_t buffer[5]; ///< buffer1 has frame_n for TODO Isochronous
|
||||
|
||||
//------------- DCD Area -------------//
|
||||
//--------------------------------------------------------------------+
|
||||
// TD is 32 bytes aligned but occupies only 28 bytes
|
||||
// Therefore there are 4 bytes padding that we can use.
|
||||
//--------------------------------------------------------------------+
|
||||
uint16_t expected_bytes;
|
||||
uint8_t reserved[2];
|
||||
} dcd_qtd_t;
|
||||
@ -109,11 +116,10 @@ typedef struct
|
||||
// Word 0: Capabilities and Characteristics
|
||||
uint32_t : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed.
|
||||
uint32_t int_on_setup : 1 ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received.
|
||||
uint32_t max_package_size : 11 ; ///< This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize)
|
||||
uint32_t max_packet_size : 11 ; ///< Endpoint's wMaxPacketSize
|
||||
uint32_t : 2 ;
|
||||
uint32_t zero_length_termination : 1 ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length.
|
||||
uint32_t iso_mult : 2 ; ///<
|
||||
uint32_t : 0 ;
|
||||
|
||||
// Word 1: Current qTD Pointer
|
||||
volatile uint32_t qtd_addr;
|
||||
@ -125,10 +131,11 @@ typedef struct
|
||||
volatile tusb_control_request_t setup_request;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
/// Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes
|
||||
/// thus there are 16 bytes padding free that we can make use of.
|
||||
// QHD is 64 bytes aligned but occupies only 48 bytes
|
||||
// Therefore there are 16 bytes padding that we can use.
|
||||
//--------------------------------------------------------------------+
|
||||
uint8_t reserved[16];
|
||||
tu_fifo_t * ff;
|
||||
uint8_t reserved[12];
|
||||
} dcd_qhd_t;
|
||||
|
||||
TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct");
|
||||
@ -145,10 +152,6 @@ typedef struct
|
||||
}dcd_controller_t;
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
|
||||
// Each endpoint with direction (IN/OUT) occupies a queue head
|
||||
// Therefore QHD_MAX is 2 x max endpoint count
|
||||
#define QHD_MAX (8*2)
|
||||
|
||||
static const dcd_controller_t _dcd_controller[] =
|
||||
{
|
||||
// RT1010 and RT1020 only has 1 USB controller
|
||||
@ -161,8 +164,6 @@ typedef struct
|
||||
};
|
||||
|
||||
#else
|
||||
#define QHD_MAX (6*2)
|
||||
|
||||
static const dcd_controller_t _dcd_controller[] =
|
||||
{
|
||||
{ .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 },
|
||||
@ -174,8 +175,10 @@ typedef struct
|
||||
|
||||
typedef struct {
|
||||
// Must be at 2K alignment
|
||||
dcd_qhd_t qhd[QHD_MAX] TU_ATTR_ALIGNED(64);
|
||||
dcd_qtd_t qtd[QHD_MAX] TU_ATTR_ALIGNED(32); // for portability, TinyUSB only queue 1 TD for each Qhd
|
||||
// Each endpoint with direction (IN/OUT) occupies a queue head
|
||||
// for portability, TinyUSB only queue 1 TD for each Qhd
|
||||
dcd_qhd_t qhd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(64);
|
||||
dcd_qtd_t qtd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(32);
|
||||
}dcd_data_t;
|
||||
|
||||
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
|
||||
@ -195,9 +198,9 @@ static void bus_reset(uint8_t rhport)
|
||||
// endpoint type of the unused direction must be changed from the control type to any other
|
||||
// type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior
|
||||
// for the data PID tracking on the active endpoint.
|
||||
for( int i=1; i < _dcd_controller[rhport].ep_count; i++)
|
||||
for( uint8_t i=1; i < _dcd_controller[rhport].ep_count; i++)
|
||||
{
|
||||
dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << 2) | (TUSB_XFER_BULK << 18);
|
||||
dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
|
||||
}
|
||||
|
||||
//------------- Clear All Registers -------------//
|
||||
@ -217,11 +220,11 @@ static void bus_reset(uint8_t rhport)
|
||||
tu_memclr(&_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
//------------- Set up Control Endpoints (0 OUT, 1 IN) -------------//
|
||||
_dcd_data.qhd[0].zero_length_termination = _dcd_data.qhd[1].zero_length_termination = 1;
|
||||
_dcd_data.qhd[0].max_package_size = _dcd_data.qhd[1].max_package_size = CFG_TUD_ENDPOINT0_SIZE;
|
||||
_dcd_data.qhd[0].qtd_overlay.next = _dcd_data.qhd[1].qtd_overlay.next = QTD_NEXT_INVALID;
|
||||
_dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1;
|
||||
_dcd_data.qhd[0][0].max_packet_size = _dcd_data.qhd[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE;
|
||||
_dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID;
|
||||
|
||||
_dcd_data.qhd[0].int_on_setup = 1; // OUT only
|
||||
_dcd_data.qhd[0][0].int_on_setup = 1; // OUT only
|
||||
}
|
||||
|
||||
void dcd_init(uint8_t rhport)
|
||||
@ -238,14 +241,15 @@ void dcd_init(uint8_t rhport)
|
||||
dcd_reg->USBMODE = USBMODE_CM_DEVICE;
|
||||
dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION;
|
||||
|
||||
// TODO Force fullspeed on non-highspeed port
|
||||
// dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED;
|
||||
#if !TUD_OPT_HIGH_SPEED
|
||||
dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED;
|
||||
#endif
|
||||
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment
|
||||
dcd_reg->USBSTS = dcd_reg->USBSTS;
|
||||
dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_RESET | INTR_SUSPEND /*| INTR_SOF*/;
|
||||
dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND;
|
||||
|
||||
dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0
|
||||
dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect
|
||||
@ -272,7 +276,8 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
|
||||
|
||||
void dcd_remote_wakeup(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
dcd_reg->PORTSC1 |= PORTSC1_FORCE_PORT_RESUME;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
@ -290,26 +295,33 @@ void dcd_disconnect(uint8_t rhport)
|
||||
//--------------------------------------------------------------------+
|
||||
// HELPER
|
||||
//--------------------------------------------------------------------+
|
||||
// index to bit position in register
|
||||
static inline uint8_t ep_idx2bit(uint8_t ep_idx)
|
||||
{
|
||||
return ep_idx/2 + ( (ep_idx%2) ? 16 : 0);
|
||||
}
|
||||
|
||||
static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes)
|
||||
{
|
||||
// Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the
|
||||
// address to 32-byte boundaries. Buffer must be word aligned
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31);
|
||||
|
||||
tu_memclr(p_qtd, sizeof(dcd_qtd_t));
|
||||
|
||||
p_qtd->next = QTD_NEXT_INVALID;
|
||||
p_qtd->active = 1;
|
||||
p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
|
||||
p_qtd->next = QTD_NEXT_INVALID;
|
||||
p_qtd->active = 1;
|
||||
p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
|
||||
p_qtd->int_on_complete = true;
|
||||
|
||||
if (data_ptr != NULL)
|
||||
{
|
||||
p_qtd->buffer[0] = (uint32_t) data_ptr;
|
||||
p_qtd->buffer[0] = (uint32_t) data_ptr;
|
||||
|
||||
uint32_t const bufend = p_qtd->buffer[0] + total_bytes;
|
||||
for(uint8_t i=1; i<5; i++)
|
||||
{
|
||||
p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096;
|
||||
uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096;
|
||||
if ( bufend <= next_page ) break;
|
||||
|
||||
p_qtd->buffer[i] = next_page;
|
||||
|
||||
// TODO page[1] FRAME_N for ISO transfer
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -324,12 +336,15 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0);
|
||||
|
||||
// flush to abort any primed buffer
|
||||
dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
|
||||
}
|
||||
|
||||
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
// data toggle also need to be reset
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
@ -339,45 +354,87 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
|
||||
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
|
||||
{
|
||||
// TODO not support ISO yet
|
||||
TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
|
||||
uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
|
||||
uint8_t const ep_idx = 2*epnum + dir;
|
||||
uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
|
||||
uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
|
||||
|
||||
// Must not exceed max endpoint number
|
||||
TU_ASSERT( epnum < _dcd_controller[rhport].ep_count );
|
||||
|
||||
//------------- Prepare Queue Head -------------//
|
||||
dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx];
|
||||
dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
|
||||
tu_memclr(p_qhd, sizeof(dcd_qhd_t));
|
||||
|
||||
p_qhd->zero_length_termination = 1;
|
||||
p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size;
|
||||
p_qhd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size;
|
||||
if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
|
||||
{
|
||||
p_qhd->iso_mult = 1;
|
||||
}
|
||||
|
||||
p_qhd->qtd_overlay.next = QTD_NEXT_INVALID;
|
||||
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
// Enable EP Control
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
dcd_reg->ENDPTCTRL[epnum] |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET) << (dir ? 16 : 0);
|
||||
|
||||
uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET;
|
||||
|
||||
if ( dir == TUSB_DIR_OUT )
|
||||
{
|
||||
dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl;
|
||||
}else
|
||||
{
|
||||
dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dcd_edpt_close_all (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
// TODO implement dcd_edpt_close_all()
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
|
||||
// Disable all non-control endpoints
|
||||
for( uint8_t epnum=1; epnum < _dcd_controller[rhport].ep_count; epnum++)
|
||||
{
|
||||
_dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1;
|
||||
_dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1;
|
||||
|
||||
dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum+16);
|
||||
dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
|
||||
}
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
|
||||
_dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1;
|
||||
|
||||
// Flush EP
|
||||
uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0));
|
||||
dcd_reg->ENDPTFLUSH = flush_mask;
|
||||
while(dcd_reg->ENDPTFLUSH & flush_mask);
|
||||
|
||||
// Clear EP enable
|
||||
dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0));
|
||||
}
|
||||
|
||||
static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir)
|
||||
{
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
uint8_t const ep_idx = 2*epnum + dir;
|
||||
dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
|
||||
dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
|
||||
|
||||
p_qhd->qtd_overlay.halted = false; // clear any previous error
|
||||
p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
|
||||
|
||||
// flush cache
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
if ( epnum == 0 )
|
||||
{
|
||||
@ -386,23 +443,87 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
|
||||
while(dcd_reg->ENDPTSETUPSTAT & TU_BIT(0)) {}
|
||||
}
|
||||
|
||||
dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx];
|
||||
dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx];
|
||||
|
||||
// Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the
|
||||
// address to 32-byte boundaries.
|
||||
// void* cast to suppress cast-align warning, buffer must be
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31);
|
||||
|
||||
//------------- Prepare qtd -------------//
|
||||
qtd_init(p_qtd, buffer, total_bytes);
|
||||
p_qtd->int_on_complete = true;
|
||||
p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
|
||||
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
// start transfer
|
||||
dcd_reg->ENDPTPRIME = TU_BIT( ep_idx2bit(ep_idx) ) ;
|
||||
dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0));
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
|
||||
dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
|
||||
|
||||
// Prepare qtd
|
||||
qtd_init(p_qtd, buffer, total_bytes);
|
||||
|
||||
// Start qhd transfer
|
||||
p_qhd->ff = NULL;
|
||||
qhd_start_xfer(rhport, epnum, dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// fifo has to be aligned to 4k boundary
|
||||
bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
|
||||
dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
|
||||
|
||||
tu_fifo_buffer_info_t fifo_info;
|
||||
|
||||
if (dir)
|
||||
{
|
||||
tu_fifo_get_read_info(ff, &fifo_info);
|
||||
} else
|
||||
{
|
||||
tu_fifo_get_write_info(ff, &fifo_info);
|
||||
}
|
||||
|
||||
if ( fifo_info.len_lin >= total_bytes )
|
||||
{
|
||||
// Linear length is enough for this transfer
|
||||
qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// linear part is not enough
|
||||
|
||||
// prepare TD up to linear length
|
||||
qtd_init(p_qtd, fifo_info.ptr_lin, fifo_info.len_lin);
|
||||
|
||||
if ( !tu_offset4k((uint32_t) fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff)) )
|
||||
{
|
||||
// If buffer is aligned to 4K & buffer size is multiple of 4K
|
||||
// We can make use of buffer page array to also combine the linear + wrapped length
|
||||
p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
|
||||
|
||||
for(uint8_t i = 1, page = 0; i < 5; i++)
|
||||
{
|
||||
// pick up buffer array where linear ends
|
||||
if (p_qtd->buffer[i] == 0)
|
||||
{
|
||||
p_qtd->buffer[i] = (uint32_t) fifo_info.ptr_wrap + 4096 * page;
|
||||
page++;
|
||||
}
|
||||
}
|
||||
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO we may need to carry the wrapped length after the linear part complete
|
||||
// for now only transfer up to linear part
|
||||
}
|
||||
}
|
||||
|
||||
// Start qhd transfer
|
||||
p_qhd->ff = ff;
|
||||
qhd_start_xfer(rhport, epnum, dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -410,9 +531,42 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
|
||||
//--------------------------------------------------------------------+
|
||||
// ISR
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir)
|
||||
{
|
||||
dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
|
||||
dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
|
||||
|
||||
uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
|
||||
( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
|
||||
|
||||
if ( result != XFER_RESULT_SUCCESS )
|
||||
{
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
// flush to abort error buffer
|
||||
dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
|
||||
}
|
||||
|
||||
uint16_t const xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes;
|
||||
|
||||
if (p_qhd->ff)
|
||||
{
|
||||
if (dir == TUSB_DIR_IN)
|
||||
{
|
||||
tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes);
|
||||
} else
|
||||
{
|
||||
tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// only number of bytes in the IOC qtd
|
||||
dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), xferred_bytes, result, true);
|
||||
}
|
||||
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs;
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
|
||||
uint32_t const int_enable = dcd_reg->USBINTR;
|
||||
uint32_t const int_status = dcd_reg->USBSTS & int_enable;
|
||||
@ -421,18 +575,46 @@ void dcd_int_handler(uint8_t rhport)
|
||||
// disabled interrupt sources
|
||||
if (int_status == 0) return;
|
||||
|
||||
if (int_status & INTR_RESET)
|
||||
{
|
||||
bus_reset(rhport);
|
||||
uint32_t speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS;
|
||||
dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true);
|
||||
}
|
||||
// Set if the port controller enters the full or high-speed operational state.
|
||||
// either from Bus Reset or Suspended state
|
||||
if (int_status & INTR_PORT_CHANGE)
|
||||
{
|
||||
// TU_LOG2("PortChange %08lx\r\n", dcd_reg->PORTSC1);
|
||||
|
||||
// Reset interrupt is not enabled, we manually check if Port Change is due
|
||||
// to connection / disconnection
|
||||
if ( dcd_reg->USBSTS & INTR_RESET )
|
||||
{
|
||||
dcd_reg->USBSTS = INTR_RESET;
|
||||
|
||||
if (dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS)
|
||||
{
|
||||
uint32_t const speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS;
|
||||
bus_reset(rhport);
|
||||
dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true);
|
||||
}else
|
||||
{
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Triggered by resuming from suspended state
|
||||
if ( !(dcd_reg->PORTSC1 & PORTSC1_SUSPEND) )
|
||||
{
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (int_status & INTR_SUSPEND)
|
||||
{
|
||||
// TU_LOG2("Suspend %08lx\r\n", dcd_reg->PORTSC1);
|
||||
|
||||
if (dcd_reg->PORTSC1 & PORTSC1_SUSPEND)
|
||||
{
|
||||
// Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration.
|
||||
// Skip suspend event if we are not addressed
|
||||
if ((dcd_reg->DEVICEADDR >> 25) & 0x0f)
|
||||
{
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
|
||||
@ -440,21 +622,11 @@ void dcd_int_handler(uint8_t rhport)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we read the latest version of _dcd_data.
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
// TODO disconnection does not generate interrupt !!!!!!
|
||||
// if (int_status & INTR_PORT_CHANGE)
|
||||
// {
|
||||
// if ( !(dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS) )
|
||||
// {
|
||||
// dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_UNPLUGGED };
|
||||
// dcd_event_handler(&event, true);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (int_status & INTR_USB)
|
||||
{
|
||||
// Make sure we read the latest version of _dcd_data.
|
||||
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE;
|
||||
dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge
|
||||
|
||||
@ -462,26 +634,21 @@ void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
//------------- Set up Received -------------//
|
||||
// 23.10.10.2 Operational model for setup transfers
|
||||
dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;// acknowledge
|
||||
dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
|
||||
|
||||
dcd_event_setup_received(rhport, (uint8_t*) &_dcd_data.qhd[0].setup_request, true);
|
||||
dcd_event_setup_received(rhport, (uint8_t*) &_dcd_data.qhd[0][0].setup_request, true);
|
||||
}
|
||||
|
||||
// 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
|
||||
// nothing to do, we will submit xfer as error to usbd
|
||||
// if (int_status & INTR_ERROR) { }
|
||||
|
||||
if ( edpt_complete )
|
||||
{
|
||||
for(uint8_t ep_idx = 0; ep_idx < QHD_MAX; ep_idx++)
|
||||
for(uint8_t epnum = 0; epnum < DCD_ATTR_ENDPOINT_MAX; epnum++)
|
||||
{
|
||||
if ( tu_bit_test(edpt_complete, ep_idx2bit(ep_idx)) )
|
||||
{
|
||||
// 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
|
||||
dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx];
|
||||
|
||||
uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
|
||||
( p_qtd->xact_err ||p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
|
||||
|
||||
uint8_t const ep_addr = (ep_idx/2) | ( (ep_idx & 0x01) ? TUSB_DIR_IN_MASK : 0 );
|
||||
dcd_event_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); // only number of bytes in the IOC qtd
|
||||
}
|
||||
if ( tu_bit_test(edpt_complete, epnum) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_OUT);
|
||||
if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -490,9 +657,6 @@ void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
|
||||
}
|
||||
|
||||
if (int_status & INTR_NAK) {}
|
||||
if (int_status & INTR_ERROR) TU_ASSERT(false, );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user