payload: {"action":"opened","issue":{"url":"https://api.github.com/repos/arduino/ArduinoCore-avr/issues/112","repository_url":"https://api.github.com/repos/arduino/ArduinoCore-avr","labels_url":"https://api.github.com/repos/arduino/ArduinoCore-avr/issues/112/labels{/name}","comments_url":"https://api.github.com/repos/arduino/ArduinoCore-avr/issues/112/comments","events_url":"https://api.github.com/repos/arduino/ArduinoCore-avr/issues/112/events","html_url":"https://github.com/arduino/ArduinoCore-avr/issues/112","id":494155073,"node_id":"MDU6SXNzdWU0OTQxNTUwNzM=","number":112,"title":"Arduino Micro USB Serial cannot receive exactly 64 bytes at once","user":{"login":"kervinck","id":12294510,"node_id":"MDQ6VXNlcjEyMjk0NTEw","avatar_url":"https://avatars0.githubusercontent.com/u/12294510?v=4","gravatar_id":"","url":"https://api.github.com/users/kervinck","html_url":"https://github.com/kervinck","followers_url":"https://api.github.com/users/kervinck/followers","following_url":"https://api.github.com/users/kervinck/following{/other_user}","gists_url":"https://api.github.com/users/kervinck/gists{/gist_id}","starred_url":"https://api.github.com/users/kervinck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kervinck/subscriptions","organizations_url":"https://api.github.com/users/kervinck/orgs","repos_url":"https://api.github.com/users/kervinck/repos","events_url":"https://api.github.com/users/kervinck/events{/privacy}","received_events_url":"https://api.github.com/users/kervinck/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2019-09-16T16:31:14Z","updated_at":"2019-09-16T16:31:14Z","closed_at":null,"author_association":"NONE","body":"This issue was first reported in my project here https://github.com/kervinck/gigatron-rom/issues/36 but I now believe the root cause might be in USBCore.cpp\r\n\r\nTested in Ardiuno IDE 1.8.1 and 1.8.6 (arduino-PR-6886-BUILD-734-macosx.zip)\r\nBN: Arduino/Genuino Micro\r\nVID: 2341\r\nPID: 8037\r\nSN: Upload any sketch to obtain it\r\n\r\nThe example sketch just receives lines of text and reports their length:\r\n```\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n}\r\n\r\nvoid loop() {\r\n  static int lineLength = 0;\r\n  if (Serial.available()) {\r\n    char next = Serial.read();\r\n    lineLength++;\r\n    if (next == '\\n' || next == '\\r') {\r\n      Serial.println(lineLength);\r\n      lineLength = 0;\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nTest Python program to demonstrate that the issue is with data messages of exactly 64 bytes:\r\n```\r\nimport serial\r\nfrom time import sleep\r\ntty = '/dev/tty.usbmodem1411' # Adapt for your own computer\r\nser = serial.Serial(tty, baudrate=115200, timeout=1)\r\nsleep(1) # For Arduinos that reboot\r\n\r\nfor length in [10, 70, 65, 64, 10, 10]:\r\n  line = (length-1)*'A' + '\\n'\r\n  print('> %s (%d bytes)' % (repr(line), len(line)))\r\n  ser.write(line)\r\n  reply = ser.readline()\r\n  print('< %s %s' % (repr(reply), 'OK' if reply else 'TIMEOUT'))\r\n```\r\n\r\nOutput shows that the Arduino Micro stops receiving data after having received the 64-byte \"killer\" line. It does see the 64-byte message itself and it is still able to send. But it doesn't see new data anymore.\r\n```\r\n> 'AAAAAAAAA\\n' (10 bytes)\r\n< '10\\r\\n' OK\r\n> 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n' (70 bytes)\r\n< '70\\r\\n' OK\r\n> 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n' (65 bytes)\r\n< '65\\r\\n' OK\r\n> 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n' (64 bytes)\r\n< '64\\r\\n' OK\r\n> 'AAAAAAAAA\\n' (10 bytes)\r\n< '' TIMEOUT\r\n> 'AAAAAAAAA\\n' (10 bytes)\r\n< '' TIMEOUT\r\n```\r\n\r\nExpected output is what the Arduino Uno does:\r\n```\r\n> 'AAAAAAAAA\\n' (10 bytes)\r\n< '10\\r\\n' OK\r\n> 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n' (70 bytes)\r\n< '70\\r\\n' OK\r\n> 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n' (65 bytes)\r\n< '65\\r\\n' OK\r\n> 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n' (64 bytes)\r\n< '64\\r\\n' OK\r\n> 'AAAAAAAAA\\n' (10 bytes)\r\n< '10\\r\\n' OK\r\n> 'AAAAAAAAA\\n' (10 bytes)\r\n< '10\\r\\n' OK\r\n```\r\n\r\nSomewhat related to https://github.com/arduino/Arduino/issues/6669 (\"Arduino Micro USB Serial cannot receive more than 255 data once\") and https://github.com/arduino/Arduino/pull/6886 (\"Handle receiving a ZLP in USB_Available\"), however the proposed solution of that issue doesn't solve this.\r\n\r\nI suspect the problem is caused by not following the datasheet's sequence, specifically:\r\n\r\n> RXOUTI shall always be cleared before clearing FIFOCON\r\n\r\nThe way USB_Recv is written I don't think ReleaseRX will ever be called twice in a row. And that is exactly what gets me out of the hangup situation. In my own project I have integrated a workaround https://github.com/kervinck/gigatron-rom/commit/94d167dd755bdad22af6ae818f879f1d3e961e86 that seems to work by clearing FICOCON after Serial.read() and observing that UEBCLX has become 0. But I haven't considered every possible scenario (race conditions?).\r\n\r\n\r\n----\r\nI have some general remarks about USBCore.cpp, and this is _very_ subjective, so please take no offense. But having studied the code with an actual problem, the Arduino Micro hooked up and the datasheets at hand, I have the impression some more issues might be lurking here. It is not obvious (to me) that the code and the datasheet match.\r\n\r\n-  Why not use RWAL in USB_Available instead of UEBCLX. Tracing its value in different scenarios, UEBCLX doesn't always seem quite the right indicator. It can sometimes momentarily read 0 in the middle of a transfer sequence. (Besides the question what to to with UEBCHX in case that ever becomes relevant)\r\n-  What is the magic constant 0x6B in ReleaseRX? Why not address the desired bits explicitly with masking operations.\r\n- USB_Recv() does some interesting things with its n and len, and the condition before ReleaseRX seems a bit suspect to me."}}
other: {"actor":{"display_login":"kervinck"}}