diff options
author | Patrick Georgi <pgeorgi@google.com> | 2018-08-16 15:35:43 +0200 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-10-16 10:30:37 -0700 |
commit | 69bc0deb614cc131cd669b5ac8935e68d10ac6e5 (patch) | |
tree | 5d85ef9f55aa7a34ba5d4de3ddefed95d87175e3 | |
parent | 9a16a6b9cf701d43ba0e7e8f71ac081e15430be3 (diff) | |
download | chrome-ec-69bc0deb614cc131cd669b5ac8935e68d10ac6e5.tar.gz |
chip/stm32: Convert usb_endpoints to C so gcc's LTO knows about it
If we keep it assembly-only, the link time optimizer gets confused and
eliminates seemingly unused functions, to then replace references to
them with the "no handler" defaults in a later step.
Similar approach as with vecttable: Implement the table in C so LTO
knows the entire story.
BUG=b:65441143
BRANCH=none
TEST=usb_ep_{rx,tx,event} and usb_iface_request look more reasonable in
disassembly on whiskers.
Change-Id: I35ccfd68cda2d0022aa464ecf622f4eef71c3398
Signed-off-by: Patrick Georgi <pgeorgi@google.com>
Reviewed-on: https://chromium-review.googlesource.com/1177710
Commit-Ready: Patrick Georgi <pgeorgi@chromium.org>
Tested-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
Reviewed-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
-rw-r--r-- | chip/stm32/usb_endpoints.S | 108 | ||||
-rw-r--r-- | chip/stm32/usb_endpoints.c | 169 | ||||
-rw-r--r-- | core/cortex-m0/ec.lds.S | 4 |
3 files changed, 173 insertions, 108 deletions
diff --git a/chip/stm32/usb_endpoints.S b/chip/stm32/usb_endpoints.S deleted file mode 100644 index 9b3c41d175..0000000000 --- a/chip/stm32/usb_endpoints.S +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * USB endpoints/interfaces callbacks declaration - */ - -#include "config.h" - -.section .rodata.usb_ep - -.macro endpoint number suffix -.if \number < USB_EP_COUNT -.long ep_\number\()_\()\suffix -.weak ep_\number\()_\()\suffix -.set ep_\number\()_\()\suffix, ep_undefined -.endif -.endm - -.macro interface number -.if \number < USB_IFACE_COUNT -.long iface_\number\()_request -.weak iface_\number\()_request -.set iface_\number\()_request, iface_undefined -.endif -.endm - -/* align function pointers on a 32-bit boundary */ -.align 2 -/* Endpoint callbacks */ -.global usb_ep_tx -usb_ep_tx: -endpoint 0 tx -endpoint 1 tx -endpoint 2 tx -endpoint 3 tx -endpoint 4 tx -endpoint 5 tx -endpoint 6 tx -endpoint 7 tx -endpoint 8 tx -endpoint 9 tx -endpoint 10 tx -endpoint 11 tx -endpoint 12 tx -endpoint 13 tx -endpoint 14 tx -endpoint 15 tx - -.global usb_ep_rx -usb_ep_rx: -endpoint 0 rx -endpoint 1 rx -endpoint 2 rx -endpoint 3 rx -endpoint 4 rx -endpoint 5 rx -endpoint 6 rx -endpoint 7 rx -endpoint 8 rx -endpoint 9 rx -endpoint 10 rx -endpoint 11 rx -endpoint 12 rx -endpoint 13 rx -endpoint 14 rx -endpoint 15 rx - -.global usb_ep_event -usb_ep_event: -endpoint 0 evt -endpoint 1 evt -endpoint 2 evt -endpoint 3 evt -endpoint 4 evt -endpoint 5 evt -endpoint 6 evt -endpoint 7 evt -endpoint 8 evt -endpoint 9 evt -endpoint 10 evt -endpoint 11 evt -endpoint 12 evt -endpoint 13 evt -endpoint 14 evt -endpoint 15 evt - -.global usb_iface_request -usb_iface_request: -interface 0 -interface 1 -interface 2 -interface 3 -interface 4 -interface 5 -interface 6 -interface 7 - -.text -.code 16 - -.thumb_func -/* Undefined interface callbacks fail by returning non-zero*/ -iface_undefined: - mov r0, #1 -.thumb_func -ep_undefined: - bx lr diff --git a/chip/stm32/usb_endpoints.c b/chip/stm32/usb_endpoints.c new file mode 100644 index 0000000000..e4d595c31d --- /dev/null +++ b/chip/stm32/usb_endpoints.c @@ -0,0 +1,169 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * USB endpoints/interfaces callbacks declaration + */ + +#include <stdint.h> +#include <stddef.h> +#include "config.h" +#include "common.h" +#include "usb_hw.h" + +typedef void (*xfer_func)(void); +typedef void (*evt_func) (enum usb_ep_event evt); + +#if defined(CHIP_FAMILY_STM32F4) +#define iface_arguments struct usb_setup_packet *req +#else +#define iface_arguments usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx +#endif +typedef int (*iface_func)(iface_arguments); + +#ifndef PASS +#define PASS 1 +#endif + +#if PASS == 1 +void ep_undefined(void) +{ + return; +} + +void ep_evt_undefined(enum usb_ep_event evt) +{ + return; +} + +/* Undefined interface callbacks fail by returning non-zero*/ +int iface_undefined(iface_arguments) +{ + return 1; +} + +#define table(type, name, x) x + +#define endpoint_tx(number) \ + extern void __attribute__((used, weak, alias("ep_undefined"))) \ + ep_ ## number ## _tx(void); +#define endpoint_rx(number) \ + extern void __attribute__((used, weak, alias("ep_undefined"))) \ + ep_ ## number ## _rx(void); +#define endpoint_evt(number) \ + extern void __attribute__((used, weak, alias("ep_evt_undefined"))) \ + ep_ ## number ## _evt(enum usb_ep_event evt); +#define interface(number) \ + extern int __attribute__((used, weak, alias("iface_undefined"))) \ + iface_ ## number ## _request(iface_arguments); + +#define null + +#endif /* PASS 1 */ + +#if PASS == 2 +#undef table +#undef endpoint_tx +#undef endpoint_rx +#undef endpoint_evt +#undef interface +#undef null + +/* align function pointers on a 32-bit boundary */ +#define table(type, name, x) type name[] __attribute__((aligned(4), section(".rodata.usb_ep." #name ",\"a\" @"))) = { x }; +#define null (void*)0 + +#define ep_(num, suf) CONCAT3(ep_, num, suf) +#define ep(num, suf) ep_(num, suf) + +#define endpoint_tx(number) \ + [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _tx, +#define endpoint_rx(number) \ + [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _rx, +#define endpoint_evt(number) \ + [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _evt, +#define interface(number) \ + [number < USB_IFACE_COUNT ? number : USB_IFACE_COUNT - 1] = iface_ ## number ## _request, +#endif /* PASS 2 */ + +/* + * The initializers are listed backwards, but that's so that the items beyond + * the chip's limit are first assigned to the last field, then overwritten by + * its actual value due to the designated initializers in the macros above. + * It all sorts out nicely + */ +table(xfer_func, usb_ep_tx, + endpoint_tx(15) + endpoint_tx(14) + endpoint_tx(13) + endpoint_tx(12) + endpoint_tx(11) + endpoint_tx(10) + endpoint_tx(9) + endpoint_tx(8) + endpoint_tx(7) + endpoint_tx(6) + endpoint_tx(5) + endpoint_tx(4) + endpoint_tx(3) + endpoint_tx(2) + endpoint_tx(1) + endpoint_tx(0) +) + +table(xfer_func, usb_ep_rx, + endpoint_rx(15) + endpoint_rx(14) + endpoint_rx(13) + endpoint_rx(12) + endpoint_rx(11) + endpoint_rx(10) + endpoint_rx(9) + endpoint_rx(8) + endpoint_rx(7) + endpoint_rx(6) + endpoint_rx(5) + endpoint_rx(4) + endpoint_rx(3) + endpoint_rx(2) + endpoint_rx(1) + endpoint_rx(0) +) + +table(evt_func, usb_ep_event, + endpoint_evt(15) + endpoint_evt(14) + endpoint_evt(13) + endpoint_evt(12) + endpoint_evt(11) + endpoint_evt(10) + endpoint_evt(9) + endpoint_evt(8) + endpoint_evt(7) + endpoint_evt(6) + endpoint_evt(5) + endpoint_evt(4) + endpoint_evt(3) + endpoint_evt(2) + endpoint_evt(1) + endpoint_evt(0) +) + +#if USB_IFACE_COUNT > 0 +table(iface_func, usb_iface_request, + interface(7) + interface(6) + interface(5) + interface(4) + interface(3) + interface(2) + interface(1) + interface(0) +) +#endif + +#if PASS == 1 +#undef PASS +#define PASS 2 +#include "usb_endpoints.c" +#endif diff --git a/core/cortex-m0/ec.lds.S b/core/cortex-m0/ec.lds.S index c72ec5a5cc..d7830be852 100644 --- a/core/cortex-m0/ec.lds.S +++ b/core/cortex-m0/ec.lds.S @@ -172,6 +172,10 @@ SECTIONS __usb_desc_end = .; . = ALIGN(4); KEEP(*(.rodata.usb_ep)) + KEEP(*(.rodata.usb_ep.usb_ep_tx)) + KEEP(*(.rodata.usb_ep.usb_ep_rx)) + KEEP(*(.rodata.usb_ep.usb_ep_event)) + KEEP(*(.rodata.usb_ep.usb_iface_request)) . = ALIGN(4); *(.rodata*) |