Teensy 4.1 core updated for C++20
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.

343 line
7.5KB

  1. //#define USB_SERIAL_PRIVATE_INCLUDE
  2. //#include "usb_mass_storage_debug.h"
  3. //#include "flash.h"
  4. //#include "pauls_ugly_debug.h"
  5. inline uint32_t media_size(void);
  6. void media_init(void);
  7. uint8_t media_lock(void);
  8. void media_unlock(void);
  9. void media_poll(void);
  10. static void media_send_begin(uint32_t lba);
  11. static void media_send_chunk(uint32_t lba, uint8_t chunk);
  12. static void media_send_end(void);
  13. static void media_receive_begin(uint32_t lba);
  14. static void media_receive_chunk(uint32_t lba, uint8_t chunk);
  15. static void media_receive_end(void);
  16. /**************************************************************************
  17. *
  18. * Storage Media Access Functions
  19. *
  20. **************************************************************************/
  21. #if defined(__AVR_ATmega32U4__)
  22. #define LPM "lpm "
  23. #define EPZ 0x3F
  24. #define READ_ONLY 1
  25. #elif defined(__AVR_AT90USB646__)
  26. #define LPM "lpm "
  27. #define EPZ 0x7E
  28. #define READ_ONLY 0
  29. #elif defined(__AVR_AT90USB1286__)
  30. #define LPM "elpm "
  31. #define EPZ 0xFE
  32. #define READ_ONLY 0
  33. #endif
  34. #ifndef USBSTATE
  35. #define USBSTATE
  36. #endif
  37. volatile uint8_t media_rdonly USBSTATE;
  38. #define MEDIA_PRESENT_MASK 0x10
  39. #define MEDIA_STATE_READY 0x12
  40. #define MEDIA_STATE_CLAIMED 0x80 // media is claimed
  41. #define MEDIA_STATE_CLAIMED_STATUS 0x40 // claimed status reported
  42. #define MEDIA_STATE_CLAIMED_SENSE 0x20 // claimed scsi sense sent
  43. volatile uint8_t media_state USBSTATE;
  44. void media_restart(void)
  45. {
  46. }
  47. void media_init(void)
  48. {
  49. media_state = MEDIA_STATE_READY;
  50. media_rdonly = READ_ONLY;
  51. }
  52. void media_claim(void)
  53. {
  54. if (media_state & MEDIA_STATE_CLAIMED) return;
  55. while (!media_lock()) /*wait*/ ;
  56. media_state = MEDIA_STATE_CLAIMED;
  57. print("Media claimed by user program\n");
  58. media_unlock();
  59. }
  60. void media_release(uint8_t read_only_mode)
  61. {
  62. uint8_t mstate;
  63. mstate = media_state;
  64. if (!(mstate & MEDIA_STATE_CLAIMED)) return;
  65. print("Media release begin\n");
  66. while (mstate != (MEDIA_STATE_CLAIMED|MEDIA_STATE_CLAIMED_STATUS|MEDIA_STATE_CLAIMED_SENSE)) {
  67. if (!usb_configuration) break;
  68. // TODO: a timeout??
  69. mstate = media_state;
  70. }
  71. // a brief delay is needed here... but why?
  72. delayMicroseconds(12500);
  73. print("Media released by user program\n");
  74. media_state = MEDIA_STATE_READY;
  75. #if READ_ONLY
  76. media_rdonly = READ_ONLY;
  77. #else
  78. media_rdonly = read_only_mode;
  79. #endif
  80. }
  81. void media_poll(void)
  82. {
  83. if ((media_state & MEDIA_STATE_CLAIMED)) return;
  84. media_state = MEDIA_STATE_READY;
  85. }
  86. // return the number of 512 byte blocks, or 0 if the media is offline
  87. //
  88. inline uint32_t media_size(void)
  89. {
  90. uint8_t r;
  91. asm volatile(
  92. "ldi %0, %1" "\n\t"
  93. "subi %0, hi8(pm(__data_load_end))" "\n"
  94. : "=d" (r) : "M" (EPZ - 1));
  95. return r;
  96. }
  97. // __data_load_start = 07A8
  98. // end = 7E00, FC00, 1FC00
  99. // pm(__data_load_start) = 3D4
  100. // end = 3F00, 7E00, FE00
  101. uint8_t media_read_sector(uint32_t lba, uint8_t *buffer)
  102. {
  103. while (!media_lock()) /*wait*/ ;
  104. asm volatile(
  105. "clr r30" "\n\t"
  106. "ldi r31, %0" "\n\t"
  107. "sub r31, %2" "\n\t"
  108. "lsl r31" "\n\t"
  109. #if defined(__AVR_AT90USB1286__)
  110. "adc __zero_reg__, __zero_reg__" "\n\t"
  111. "out 0x3B, __zero_reg__" "\n\t"
  112. "clr __zero_reg__" "\n\t"
  113. #endif
  114. "L_%=_looop:" "\n\t"
  115. LPM "__tmp_reg__, Z+" "\n\t"
  116. "st X+, __tmp_reg__" "\n\t"
  117. LPM "__tmp_reg__, Z+" "\n\t"
  118. "st X+, __tmp_reg__" "\n\t"
  119. LPM "__tmp_reg__, Z+" "\n\t"
  120. "st X+, __tmp_reg__" "\n\t"
  121. LPM "__tmp_reg__, Z+" "\n\t"
  122. "st X+, __tmp_reg__" "\n\t"
  123. LPM "__tmp_reg__, Z+" "\n\t"
  124. "st X+, __tmp_reg__" "\n\t"
  125. LPM "__tmp_reg__, Z+" "\n\t"
  126. "st X+, __tmp_reg__" "\n\t"
  127. LPM "__tmp_reg__, Z+" "\n\t"
  128. "st X+, __tmp_reg__" "\n\t"
  129. LPM "__tmp_reg__, Z+" "\n\t"
  130. "st X+, __tmp_reg__" "\n\t"
  131. "tst r30" "\n\t"
  132. "brne L_%=_looop" "\n\t"
  133. "sbrc r31, 0" "\n\t"
  134. "rjmp L_%=_looop" "\n\t"
  135. : : "M" (EPZ - 1), "x" (buffer), "r" ((uint8_t)lba)
  136. : "r0", "r30", "r31"
  137. );
  138. media_unlock();
  139. return 1;
  140. }
  141. static void media_send_begin(uint32_t lba)
  142. {
  143. }
  144. static inline void media_send_chunk(uint32_t lba, uint8_t chunk)
  145. {
  146. uint8_t addr = lba;
  147. asm volatile(
  148. "ldi r31, %1" "\n\t"
  149. "sub r31, %3" "\n\t"
  150. "lsl r31" "\n\t"
  151. #if defined(__AVR_AT90USB1286__)
  152. "adc __zero_reg__, __zero_reg__" "\n\t"
  153. "out 0x3B, __zero_reg__" "\n\t"
  154. "clr __zero_reg__" "\n\t"
  155. #endif
  156. "mov r30, %0" "\n\t"
  157. "andi r30, 7" "\n\t"
  158. "swap r30" "\n\t"
  159. "lsl r30" "\n\t"
  160. "lsl r30" "\n\t"
  161. "adc r31, __zero_reg__" "\n\t"
  162. "ldi %0, 8" "\n\t"
  163. "L_%=_looop:" "\n\t"
  164. LPM "__tmp_reg__, Z+" "\n\t"
  165. "st X, __tmp_reg__" "\n\t"
  166. LPM "__tmp_reg__, Z+" "\n\t"
  167. "st X, __tmp_reg__" "\n\t"
  168. LPM "__tmp_reg__, Z+" "\n\t"
  169. "st X, __tmp_reg__" "\n\t"
  170. LPM "__tmp_reg__, Z+" "\n\t"
  171. "st X, __tmp_reg__" "\n\t"
  172. LPM "__tmp_reg__, Z+" "\n\t"
  173. "st X, __tmp_reg__" "\n\t"
  174. LPM "__tmp_reg__, Z+" "\n\t"
  175. "st X, __tmp_reg__" "\n\t"
  176. LPM "__tmp_reg__, Z+" "\n\t"
  177. "st X, __tmp_reg__" "\n\t"
  178. LPM "__tmp_reg__, Z+" "\n\t"
  179. "st X, __tmp_reg__" "\n\t"
  180. "subi %0, 1" "\n\t"
  181. "brne L_%=_looop" "\n\t"
  182. : "+d" (chunk)
  183. : "M" (EPZ - 1), "x" (&UEDATX), "r" (addr)
  184. : "r0", "r30", "r31"
  185. );
  186. UEINTX = 0x3A;
  187. }
  188. static void media_send_end(void)
  189. {
  190. }
  191. uint8_t media_write_sector(uint32_t lba, const uint8_t *buffer)
  192. {
  193. #if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  194. uint8_t addr = lba;
  195. uint8_t offset = 0;
  196. uint32_t a;
  197. while (!media_lock()) /*wait*/ ;
  198. a = ((uint32_t)(EPZ - 1 - addr) << 9);
  199. while (1) {
  200. do {
  201. uint16_t tmp = *buffer++;
  202. tmp |= (*buffer++ << 8);
  203. boot_flash_fill_temp_buffer(tmp, offset);
  204. offset += 2;
  205. } while (offset);
  206. print_hex32("writing flash address: ", a);
  207. asm volatile("clr r0 \n\tcom r0\n\tmov r1, r0\n\tcli");
  208. boot_flash_page_erase_and_write(a);
  209. asm volatile("sei\n\tclr __zero_reg__");
  210. if ((a & 256)) break;
  211. a |= 256;
  212. }
  213. media_unlock();
  214. return 1;
  215. #else
  216. return 0;
  217. #endif
  218. }
  219. static void media_receive_begin(uint32_t lba)
  220. {
  221. // TODO: check media_rdonly, return error is read only mode
  222. }
  223. static void media_receive_chunk(uint32_t lba, uint8_t chunk)
  224. {
  225. #if 1
  226. #if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  227. uint8_t addr = lba;
  228. uint8_t i;
  229. uint8_t aa;
  230. uint32_t a;
  231. aa = chunk << 6;
  232. //print("fill tmp buffer @ ");
  233. //phex32(aa);
  234. //print("\n");
  235. for (i=0; i<32; i++) {
  236. uint16_t tmp;
  237. tmp = UEDATX;
  238. tmp |= (UEDATX << 8);
  239. //phex16(tmp);
  240. boot_flash_fill_temp_buffer(tmp, aa);
  241. aa += 2;
  242. }
  243. UEINTX = 0x6B;
  244. if ((chunk & 0x03) == 3) {
  245. a = ((uint32_t)(EPZ - 1 - addr) << 9) | ((uint16_t)(chunk & 4) << 6);
  246. //print("writing @ ");
  247. //phex32(a);
  248. //print("\n");
  249. asm volatile("clr r0 \n\tcom r0\n\tmov r1, r0");
  250. boot_flash_page_erase_and_write(a);
  251. asm volatile("clr __zero_reg__");
  252. }
  253. #else
  254. UEINTX = 0x6B;
  255. #endif
  256. #endif
  257. #if 0
  258. uint8_t addr = lba;
  259. asm volatile(
  260. "ldi r18, 1" "\n\t"
  261. "ldi r19, 32" "\n\t"
  262. "ldi r31, %2" "\n\t"
  263. "sub r31, %3" "\n\t"
  264. "mov r30, %0" "\n\t"
  265. "andi r30, 7" "\n\t"
  266. "swap r30" "\n\t"
  267. "lsl r30" "\n\t"
  268. "lsl r30" "\n\t"
  269. "rol r31" "\n\t"
  270. "rol __zero_reg__" "\n\t"
  271. "out 0x3B, __zero_reg__" "\n\t"
  272. "L_%=_loooop:" "\n\t"
  273. "ld r0, X" "\n\t"
  274. "ld r1, X" "\n\t"
  275. "call 0x1FF00" "\n\t"
  276. "subi r30, 254" "\n\t"
  277. "subi r19, 1" "\n\t"
  278. "brne L_%=_loooop" "\n\t"
  279. "ldi r18, 0x6B" "\n\t"
  280. "sts 0x00E8, r18" "\n\t"
  281. "mov r18, %0" "\n\t"
  282. "andi r18, 3" "\n\t"
  283. "cpi r18, 3" "\n\t"
  284. "brne L_%=ennd" "\n\t"
  285. "call 0x1FEB2" "\n\t"
  286. "L_%=ennd:" "\n\t"
  287. "clr __zero_reg__" "\n\t"
  288. :
  289. : "r" (chunk), "x" (&UEDATX), "M" (EPZ - 1), "r" (addr)
  290. : "r0", "r18", "r19", "r30", "r31"
  291. );
  292. #endif
  293. }
  294. static void media_receive_end(void)
  295. {
  296. }