You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

asmcommon.inc 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* Name: asmcommon.inc
  2. * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2007-11-05
  5. * Tabsize: 4
  6. * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
  7. * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
  8. * Revision: $Id$
  9. */
  10. /* Do not link this file! Link usbdrvasm.S instead, which includes the
  11. * appropriate implementation!
  12. */
  13. /*
  14. General Description:
  15. This file contains assembler code which is shared among the USB driver
  16. implementations for different CPU cocks. Since the code must be inserted
  17. in the middle of the module, it's split out into this file and #included.
  18. Jump destinations called from outside:
  19. sofError: Called when no start sequence was found.
  20. se0: Called when a package has been successfully received.
  21. overflow: Called when receive buffer overflows.
  22. doReturn: Called after sending data.
  23. Outside jump destinations used by this module:
  24. waitForJ: Called to receive an already arriving packet.
  25. sendAckAndReti:
  26. sendNakAndReti:
  27. sendCntAndReti:
  28. usbSendAndReti:
  29. The following macros must be defined before this file is included:
  30. .macro POP_STANDARD
  31. .endm
  32. .macro POP_RETI
  33. .endm
  34. */
  35. #define token x1
  36. overflow:
  37. ldi x2, 1<<USB_INTR_PENDING_BIT
  38. USB_STORE_PENDING(x2) ; clear any pending interrupts
  39. ignorePacket:
  40. clr token
  41. rjmp storeTokenAndReturn
  42. ;----------------------------------------------------------------------------
  43. ; Processing of received packet (numbers in brackets are cycles after center of SE0)
  44. ;----------------------------------------------------------------------------
  45. ;This is the only non-error exit point for the software receiver loop
  46. ;we don't check any CRCs here because there is no time left.
  47. se0:
  48. subi cnt, USB_BUFSIZE ;[5]
  49. neg cnt ;[6]
  50. sub YL, cnt ;[7]
  51. sbci YH, 0 ;[8]
  52. ldi x2, 1<<USB_INTR_PENDING_BIT ;[9]
  53. USB_STORE_PENDING(x2) ;[10] clear pending intr and check flag later. SE0 should be over.
  54. ld token, y ;[11]
  55. cpi token, USBPID_DATA0 ;[13]
  56. breq handleData ;[14]
  57. cpi token, USBPID_DATA1 ;[15]
  58. breq handleData ;[16]
  59. lds shift, usbDeviceAddr;[17]
  60. ldd x2, y+1 ;[19] ADDR and 1 bit endpoint number
  61. lsl x2 ;[21] shift out 1 bit endpoint number
  62. cpse x2, shift ;[22]
  63. rjmp ignorePacket ;[23]
  64. /* only compute endpoint number in x3 if required later */
  65. #if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT
  66. ldd x3, y+2 ;[24] endpoint number + crc
  67. rol x3 ;[26] shift in LSB of endpoint
  68. #endif
  69. cpi token, USBPID_IN ;[27]
  70. breq handleIn ;[28]
  71. cpi token, USBPID_SETUP ;[29]
  72. breq handleSetupOrOut ;[30]
  73. cpi token, USBPID_OUT ;[31]
  74. brne ignorePacket ;[32] must be ack, nak or whatever
  75. ; rjmp handleSetupOrOut ; fallthrough
  76. ;Setup and Out are followed by a data packet two bit times (16 cycles) after
  77. ;the end of SE0. The sync code allows up to 40 cycles delay from the start of
  78. ;the sync pattern until the first bit is sampled. That's a total of 56 cycles.
  79. handleSetupOrOut: ;[32]
  80. #if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for endpoint != 0, set usbCurrentTok to address */
  81. andi x3, 0xf ;[32]
  82. breq storeTokenAndReturn ;[33]
  83. mov token, x3 ;[34] indicate that this is endpoint x OUT
  84. #endif
  85. storeTokenAndReturn:
  86. sts usbCurrentTok, token;[35]
  87. doReturn:
  88. POP_STANDARD ;[37] 12...16 cycles
  89. USB_LOAD_PENDING(YL) ;[49]
  90. sbrc YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving
  91. rjmp waitForJ ;[51] save the pops and pushes -- a new interrupt is already pending
  92. sofError:
  93. POP_RETI ;macro call
  94. reti
  95. handleData:
  96. #if USB_CFG_CHECK_CRC
  97. CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error
  98. #endif
  99. lds shift, usbCurrentTok;[18]
  100. tst shift ;[20]
  101. breq doReturn ;[21]
  102. lds x2, usbRxLen ;[22]
  103. tst x2 ;[24]
  104. brne sendNakAndReti ;[25]
  105. ; 2006-03-11: The following two lines fix a problem where the device was not
  106. ; recognized if usbPoll() was called less frequently than once every 4 ms.
  107. cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack
  108. brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP
  109. #if USB_CFG_CHECK_DATA_TOGGLING
  110. sts usbCurrentDataToken, token ; store for checking by C code
  111. #endif
  112. sts usbRxLen, cnt ;[28] store received data, swap buffers
  113. sts usbRxToken, shift ;[30]
  114. lds x2, usbInputBufOffset;[32] swap buffers
  115. ldi cnt, USB_BUFSIZE ;[34]
  116. sub cnt, x2 ;[35]
  117. sts usbInputBufOffset, cnt;[36] buffers now swapped
  118. rjmp sendAckAndReti ;[38] 40 + 17 = 57 until SOP
  119. handleIn:
  120. ;We don't send any data as long as the C code has not processed the current
  121. ;input data and potentially updated the output data. That's more efficient
  122. ;in terms of code size than clearing the tx buffers when a packet is received.
  123. lds x1, usbRxLen ;[30]
  124. cpi x1, 1 ;[32] negative values are flow control, 0 means "buffer free"
  125. brge sendNakAndReti ;[33] unprocessed input packet?
  126. ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
  127. #if USB_CFG_HAVE_INTRIN_ENDPOINT
  128. andi x3, 0xf ;[35] x3 contains endpoint
  129. #if USB_CFG_SUPPRESS_INTR_CODE
  130. brne sendNakAndReti ;[36]
  131. #else
  132. brne handleIn1 ;[36]
  133. #endif
  134. #endif
  135. lds cnt, usbTxLen ;[37]
  136. sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set
  137. rjmp sendCntAndReti ;[40] 42 + 16 = 58 until SOP
  138. sts usbTxLen, x1 ;[41] x1 == USBPID_NAK from above
  139. ldi YL, lo8(usbTxBuf) ;[43]
  140. ldi YH, hi8(usbTxBuf) ;[44]
  141. rjmp usbSendAndReti ;[45] 57 + 12 = 59 until SOP
  142. ; Comment about when to set usbTxLen to USBPID_NAK:
  143. ; We should set it back when we receive the ACK from the host. This would
  144. ; be simple to implement: One static variable which stores whether the last
  145. ; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the
  146. ; ACK. However, we set it back immediately when we send the package,
  147. ; assuming that no error occurs and the host sends an ACK. We save one byte
  148. ; RAM this way and avoid potential problems with endless retries. The rest of
  149. ; the driver assumes error-free transfers anyway.
  150. #if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
  151. handleIn1: ;[38]
  152. #if USB_CFG_HAVE_INTRIN_ENDPOINT3
  153. ; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
  154. cpi x3, USB_CFG_EP3_NUMBER;[38]
  155. breq handleIn3 ;[39]
  156. #endif
  157. lds cnt, usbTxLen1 ;[40]
  158. sbrc cnt, 4 ;[42] all handshake tokens have bit 4 set
  159. rjmp sendCntAndReti ;[43] 47 + 16 = 63 until SOP
  160. sts usbTxLen1, x1 ;[44] x1 == USBPID_NAK from above
  161. ldi YL, lo8(usbTxBuf1) ;[46]
  162. ldi YH, hi8(usbTxBuf1) ;[47]
  163. rjmp usbSendAndReti ;[48] 50 + 12 = 62 until SOP
  164. #if USB_CFG_HAVE_INTRIN_ENDPOINT3
  165. handleIn3:
  166. lds cnt, usbTxLen3 ;[41]
  167. sbrc cnt, 4 ;[43]
  168. rjmp sendCntAndReti ;[44] 49 + 16 = 65 until SOP
  169. sts usbTxLen3, x1 ;[45] x1 == USBPID_NAK from above
  170. ldi YL, lo8(usbTxBuf3) ;[47]
  171. ldi YH, hi8(usbTxBuf3) ;[48]
  172. rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP
  173. #endif
  174. #endif