tests: gadget0: test for unaligned buffer read/writes.
This currently fails on stm32F072, which is expected but not normal. See GH issues #401 , #461
This commit is contained in:
parent
c585336766
commit
c3512f4de5
|
@ -318,3 +318,54 @@ class TestControlTransfer_Reads(unittest.TestCase):
|
|||
self.assertEqual(len(q), 10, "In this case, should have gotten wLen back")
|
||||
|
||||
|
||||
class TestUnaligned(unittest.TestCase):
|
||||
"""
|
||||
M0 and M0+ cores don't support unaligned memory accesses. These test
|
||||
how the stack behaves with aligned vs unaligned buffers.
|
||||
https://github.com/libopencm3/libopencm3/issues/401
|
||||
https://github.com/libopencm3/libopencm3/issues/461
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=0xcafe, idProduct=0xcafe, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(self.cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(self.cfg);
|
||||
self.req = uu.CTRL_OUT | uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE
|
||||
self.intf = self.cfg[(0, 0)]
|
||||
# heh, kinda gross...
|
||||
self.ep_out = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_OUT][0]
|
||||
self.ep_in = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_IN][0]
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def set_unaligned(self):
|
||||
# GZ_REQ_SET_UNALIGNED
|
||||
x = self.dev.ctrl_transfer(self.req, 4, 0, 0)
|
||||
|
||||
def set_aligned(self):
|
||||
# GZ_REQ_SET_ALIGNED
|
||||
x = self.dev.ctrl_transfer(self.req, 3, 0, 0)
|
||||
|
||||
def do_readwrite(self):
|
||||
"""
|
||||
transfer garbage data to/from bulk EP; alignment issues will hardfault the target
|
||||
"""
|
||||
data = [x for x in range(int(self.ep_out.wMaxPacketSize / 2))]
|
||||
written = self.dev.write(self.ep_out, data)
|
||||
self.assertEqual(written, len(data), "Should have written all bytes plz")
|
||||
|
||||
read_size = self.ep_in.wMaxPacketSize * 10
|
||||
data = self.dev.read(self.ep_in, read_size)
|
||||
self.assertEqual(len(data), read_size, "Should have read as much as we asked for")
|
||||
|
||||
def test_aligned(self):
|
||||
self.set_aligned()
|
||||
self.do_readwrite()
|
||||
|
||||
def test_unaligned(self):
|
||||
self.set_unaligned()
|
||||
self.do_readwrite()
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
*/
|
||||
#define GZ_REQ_SET_PATTERN 1
|
||||
#define GZ_REQ_PRODUCE 2
|
||||
#define GZ_REQ_SET_ALIGNED 3
|
||||
#define GZ_REQ_SET_UNALIGNED 4
|
||||
#define INTEL_COMPLIANCE_WRITE 0x5b
|
||||
#define INTEL_COMPLIANCE_READ 0x5c
|
||||
|
||||
|
@ -177,42 +179,60 @@ static usbd_device *our_dev;
|
|||
static struct {
|
||||
uint8_t pattern;
|
||||
int pattern_counter;
|
||||
int test_unaligned; /* If 0 (default), use 16-bit aligned buffers. This should not be declared as bool */
|
||||
} state = {
|
||||
.pattern = 0,
|
||||
.pattern_counter = 0,
|
||||
.test_unaligned = 0,
|
||||
};
|
||||
|
||||
static void gadget0_ss_out_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
(void) ep;
|
||||
uint16_t x;
|
||||
/* TODO - if you're really keen, perf test this. tiva implies it matters */
|
||||
/* char buf[64] __attribute__ ((aligned(4))); */
|
||||
char buf[BULK_EP_MAXPACKET];
|
||||
uint8_t buf[BULK_EP_MAXPACKET + 1] __attribute__ ((aligned(2)));
|
||||
uint8_t *dest;
|
||||
|
||||
trace_send_blocking8(0, 'O');
|
||||
uint16_t x = usbd_ep_read_packet(usbd_dev, ep, buf, sizeof(buf));
|
||||
if (state.test_unaligned) {
|
||||
dest = buf + 1;
|
||||
} else {
|
||||
dest = buf;
|
||||
}
|
||||
x = usbd_ep_read_packet(usbd_dev, ep, dest, BULK_EP_MAXPACKET);
|
||||
trace_send_blocking8(1, x);
|
||||
}
|
||||
|
||||
static void gadget0_ss_in_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
(void) usbd_dev;
|
||||
uint8_t buf[BULK_EP_MAXPACKET + 1] __attribute__ ((aligned(2)));
|
||||
uint8_t *src;
|
||||
|
||||
trace_send_blocking8(0, 'I');
|
||||
uint8_t buf[BULK_EP_MAXPACKET];
|
||||
if (state.test_unaligned) {
|
||||
src = buf + 1;
|
||||
} else {
|
||||
src = buf;
|
||||
}
|
||||
|
||||
switch (state.pattern) {
|
||||
case 0:
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(src, 0, BULK_EP_MAXPACKET);
|
||||
break;
|
||||
case 1:
|
||||
for (unsigned i = 0; i < sizeof(buf); i++) {
|
||||
buf[i] = state.pattern_counter++ % 63;
|
||||
for (unsigned i = 0; i < BULK_EP_MAXPACKET; i++) {
|
||||
src[i] = state.pattern_counter++ % 63;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t x = usbd_ep_write_packet(usbd_dev, ep, buf, sizeof(buf));
|
||||
uint16_t x = usbd_ep_write_packet(usbd_dev, ep, src, BULK_EP_MAXPACKET);
|
||||
/* As we are calling write in the callback, this should never fail */
|
||||
trace_send_blocking8(2, x);
|
||||
if (x != sizeof(buf)) {
|
||||
if (x != BULK_EP_MAXPACKET) {
|
||||
ER_DPRINTF("failed to write?: %d\n", x);
|
||||
}
|
||||
/*assert(x == sizeof(buf));*/
|
||||
|
@ -256,6 +276,12 @@ static int gadget0_control_request(usbd_device *usbd_dev,
|
|||
case INTEL_COMPLIANCE_READ:
|
||||
ER_DPRINTF("unimplemented!");
|
||||
return USBD_REQ_NOTSUPP;
|
||||
case GZ_REQ_SET_UNALIGNED:
|
||||
state.test_unaligned = 1;
|
||||
return USBD_REQ_HANDLED;
|
||||
case GZ_REQ_SET_ALIGNED:
|
||||
state.test_unaligned = 0;
|
||||
return USBD_REQ_HANDLED;
|
||||
case GZ_REQ_PRODUCE:
|
||||
ER_DPRINTF("fake loopback of %d\n", req->wValue);
|
||||
if (req->wValue > sizeof(usbd_control_buffer)) {
|
||||
|
@ -280,6 +306,7 @@ static void gadget0_set_config(usbd_device *usbd_dev, uint16_t wValue)
|
|||
ER_DPRINTF("set cfg %d\n", wValue);
|
||||
switch (wValue) {
|
||||
case GZ_CFG_SOURCESINK:
|
||||
state.test_unaligned = 0;
|
||||
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
gadget0_ss_out_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
|
|
Loading…
Reference in New Issue