5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 /* Includes ------------------------------------------------------------------*/
23 #include "FatFs/diskio.h"
26 #if defined(__cplusplus) && !defined(SIMU)
30 #include "usbd_msc_mem.h"
33 enum MassstorageLuns
{
39 /* USB Mass storage Standard Inquiry Data */
40 const unsigned char STORAGE_Inquirydata
[] = { //36
46 (USBD_STD_INQUIRY_LENGTH
- 5),
50 USB_MANUFACTURER
, /* Manufacturer : 8 bytes */
51 USB_PRODUCT
, /* Product : 16 Bytes */
52 'R', 'a', 'd', 'i', 'o', ' ', ' ', ' ',
53 '1', '.', '0', '0', /* Version : 4 Bytes */
59 (USBD_STD_INQUIRY_LENGTH
- 5),
63 USB_MANUFACTURER
, /* Manufacturer : 8 bytes */
64 USB_PRODUCT
, /* Product : 16 Bytes */
65 'R', 'a', 'd', 'i', 'o', ' ', ' ', ' ',
66 '1', '.', '0' ,'0', /* Version : 4 Bytes */
69 #define RESERVED_SECTORS (1 /*Boot*/ + 2 /*Fat table */ + 1 /*Root dir*/ + 8 /* one cluster for firmware.txt */)
71 int32_t fat12Write(const uint8_t * buffer
, uint16_t sector
, uint16_t count
);
72 int32_t fat12Read(uint8_t * buffer
, uint16_t sector
, uint16_t count
);
74 int8_t STORAGE_Init (uint8_t lun
);
76 int8_t STORAGE_GetCapacity (uint8_t lun
,
78 uint32_t *block_size
);
80 int8_t STORAGE_IsReady (uint8_t lun
);
82 int8_t STORAGE_IsWriteProtected (uint8_t lun
);
84 int8_t STORAGE_Read (uint8_t lun
,
89 int8_t STORAGE_Write (uint8_t lun
,
94 int8_t STORAGE_GetMaxLun (void);
96 const USBD_STORAGE_cb_TypeDef USBD_MICRO_SDIO_fops
= // modified my OpenTX
101 STORAGE_IsWriteProtected
,
105 (int8_t *)STORAGE_Inquirydata
,
108 const USBD_STORAGE_cb_TypeDef
* const USBD_STORAGE_fops
= &USBD_MICRO_SDIO_fops
; // modified my OpenTX
110 #if defined(__cplusplus) && !defined(SIMU)
114 int8_t STORAGE_Init (uint8_t lun
)
116 NVIC_InitTypeDef NVIC_InitStructure
;
117 NVIC_InitStructure
.NVIC_IRQChannel
= SDIO_IRQn
;
118 NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
=0;
119 NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= 0;
120 NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
121 NVIC_Init(&NVIC_InitStructure
);
123 /* TODO if no SD ... if( SD_Init() != 0)
132 * @brief return medium capacity and block size
133 * @param lun : logical unit number
134 * @param block_num : number of physical block
135 * @param block_size : size of a physical block
138 int8_t STORAGE_GetCapacity (uint8_t lun
, uint32_t *block_num
, uint32_t *block_size
)
140 if (lun
== STORAGE_EEPROM_LUN
) {
141 *block_size
= BLOCK_SIZE
;
143 *block_num
= RESERVED_SECTORS
+ EEPROM_SIZE
/BLOCK_SIZE
+ FLASHSIZE
/BLOCK_SIZE
;
145 *block_num
= RESERVED_SECTORS
+ FLASHSIZE
/BLOCK_SIZE
;
150 if (!SD_CARD_PRESENT())
153 *block_size
= BLOCK_SIZE
;
155 static DWORD sector_count
= 0;
156 if (sector_count
== 0) {
157 if (disk_ioctl(0, GET_SECTOR_COUNT
, §or_count
) != RES_OK
) {
163 *block_num
= sector_count
;
168 uint8_t lunReady
[STORAGE_LUN_NBR
];
172 lunReady
[STORAGE_SDCARD_LUN
] = 1;
173 lunReady
[STORAGE_EEPROM_LUN
] = 1;
177 * @brief check whether the medium is ready
178 * @param lun : logical unit number
181 int8_t STORAGE_IsReady (uint8_t lun
)
184 if (lun
== STORAGE_EEPROM_LUN
) {
185 return (lunReady
[STORAGE_EEPROM_LUN
] != 0) ? 0 : -1;
189 return (lunReady
[STORAGE_SDCARD_LUN
] != 0 && SD_CARD_PRESENT()) ? 0 : -1;
193 * @brief check whether the medium is write-protected
194 * @param lun : logical unit number
197 int8_t STORAGE_IsWriteProtected (uint8_t lun
)
203 * @brief Read data from the medium
204 * @param lun : logical unit number
205 * @param buf : Pointer to the buffer to save data
206 * @param blk_addr : address of 1st block to be read
207 * @param blk_len : nmber of blocks to be read
211 int8_t STORAGE_Read (uint8_t lun
,
216 WATCHDOG_SUSPEND(100/*1s*/);
218 if (lun
== STORAGE_EEPROM_LUN
) {
219 return (fat12Read(buf
, blk_addr
, blk_len
) == 0) ? 0 : -1;
222 // read without cache
223 return (__disk_read(0, buf
, blk_addr
, blk_len
) == RES_OK
) ? 0 : -1;
226 * @brief Write data to the medium
227 * @param lun : logical unit number
228 * @param buf : Pointer to the buffer to write from
229 * @param blk_addr : address of 1st block to be written
230 * @param blk_len : nmber of blocks to be read
234 int8_t STORAGE_Write (uint8_t lun
,
239 WATCHDOG_SUSPEND(100/*1s*/);
241 if (lun
== STORAGE_EEPROM_LUN
) {
242 return (fat12Write(buf
, blk_addr
, blk_len
) == 0) ? 0 : -1;
245 // write without cache
246 return (__disk_write(0, buf
, blk_addr
, blk_len
) == RES_OK
) ? 0 : -1;
250 * @brief Return number of supported logical unit
252 * @retval number of logical unit
255 int8_t STORAGE_GetMaxLun (void)
257 return STORAGE_LUN_NBR
- 1;
262 const char firmware_txt
[] =
268 " for " FLAVOUR
"\r\n\r\n"
274 "opentx-" FLAVOUR
"-" VERSION
" (" GIT_STR
")\r\n"
277 "req SD ver " REQUIRED_SDCARD_VERSION
"\r\n"
285 //------------------------------------------------------------------------------
287 * FAT12 boot sector partition.
290 #define TOTALSECTORS (RESERVED_SECTORS + (EEPROM_SIZE/BLOCK_SIZE) + (FLASHSIZE/BLOCK_SIZE))
292 #define TOTALSECTORS (RESERVED_SECTORS + (FLASHSIZE/BLOCK_SIZE))
294 const char g_FATboot
[BLOCK_SIZE
] =
296 0xeb, 0x3c, 0x90, // Jump instruction.
297 'O', 'p', 'e', 'n', 'T', 'x', 0x00, 0x00, // OEM Name
298 0x00, 0x02, // Bytes per sector
299 0x08, // Sectors per FS cluster.
300 0x01, 0x00, // Reserved sector count
302 0x01, // Number of FATs
303 0x10, 0x00, // Number of root directory entries
304 TOTALSECTORS
& 0x00ff, (TOTALSECTORS
& 0xff00) >> 8, // Total sectors
305 0xf8, // Media descriptor
306 0x02, 0x00, // Sectors per FAT table
307 0x20, 0x00, // Sectors per track
308 0x40, 0x00, // Number of heads
309 0x00, 0x00, 0x00, 0x00, // Number of hidden sectors
311 0x00, 0x00, 0x00, 0x00, // Large number of sectors.
312 0x00, // Physical drive number
314 0x29, // Extended boot signature
315 'O', 'T', 'x', 0xD1, // Disk ID (serial number)
316 'V', 'I', 'R', 'T', 'F', 'S', ' ', ' ', ' ', ' ', ' ', // Volume label
317 'F', 'A', 'T', '1', '2', ' ', ' ', ' ', // FAT file system type
318 0x00, 0x00, // OS boot code
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
357 // 3 0x08 Volume Label.
358 // 4 0x10 Subdirectory.
369 uint8_t create_time_ms
;
370 uint16_t create_time
;
371 uint16_t create_date
;
372 uint16_t access_date
;
374 uint16_t modify_time
;
375 uint16_t modify_date
;
376 uint16_t start_cluster
;
380 // First 16 FAT root directory entries (1 sector)
381 const FATDirEntry_t g_DIRroot
[] =
399 { 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E'},
401 0x21, // Readonly+Archive
411 sizeof(firmware_txt
) + strlen(getOtherVersion())
414 { 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E'},
419 0x21, // Readonly+Archive
434 { 'E', 'E', 'P', 'R', 'O', 'M', ' ', ' '},
445 0x0003 + (FLASHSIZE
/BLOCK_SIZE
)/8,
449 // Emty entries are 0x00, omitted here. Up to 16 entries can be defined here
452 static void writeByte(uint8_t *buffer
, uint16_t sector
, int byte
, uint8_t value
)
454 if (byte
>= sector
* BLOCK_SIZE
&& byte
< (sector
+1)* BLOCK_SIZE
)
455 buffer
[byte
- sector
*BLOCK_SIZE
] = value
;
458 static void pushCluster(uint8_t *buffer
, uint16_t sector
, uint16_t & cluster
, int & rest
, uint16_t value
)
460 // boot sector is in front of FAT
463 // First byte of the cluster
464 int startbyte
= cluster
*3/2;
465 if (cluster
% 2 == 0) {
468 writeByte(buffer
, sector
, startbyte
, value
& 0xff);
470 // second 12 bit half, write rest and next byte
471 writeByte(buffer
, sector
, startbyte
, value
<< 4 | rest
);
472 writeByte(buffer
, sector
, startbyte
+1, (value
>> 4) & 0xff);
477 // count is number of 512 byte sectors
478 int32_t fat12Read(uint8_t * buffer
, uint16_t sector
, uint16_t count
)
481 memset(buffer
, 0x00, BLOCK_SIZE
);
483 memcpy(buffer
, g_FATboot
, sizeof(g_FATboot
) ) ;
485 else if (sector
== 1 || sector
== 2) {
486 // FAT table. Generate on the fly to save the 1024 byte flash space
489 pushCluster (buffer
, sector
, cluster
, rest
, (uint16_t) 0xFF8);
490 pushCluster (buffer
, sector
, cluster
, rest
, (uint16_t) 0xFFF);
492 // Entry for firmware.txt, exactly one cluster
493 pushCluster (buffer
, sector
, cluster
, rest
, (uint16_t) 0xFFF);
495 // Entry for firmware.bin
496 for (int i
=0;i
<FLASHSIZE
/BLOCK_SIZE
/8 -1;i
++)
497 pushCluster (buffer
, sector
, cluster
, rest
, cluster
+1);
498 pushCluster (buffer
, sector
, cluster
, rest
, (uint16_t) 0xFFF);
501 // Entry for eeprom.bin
502 for (int i
=0;i
<EEPROM_SIZE
/BLOCK_SIZE
/8 -1;i
++)
503 pushCluster (buffer
, sector
, cluster
, rest
, cluster
+1);
504 pushCluster (buffer
, sector
, cluster
, rest
, (uint16_t) 0xFFF);
507 // Ensure last cluster is written if it is the first half
508 pushCluster (buffer
, sector
, cluster
, rest
, (uint16_t) 0x000);
510 // Rest is 0x0 as per memset
512 else if (sector
== 3) {
513 memcpy(buffer
, g_DIRroot
, sizeof(g_DIRroot
) ) ;
515 else if (sector
== 4)
517 memcpy(buffer
, firmware_txt
, sizeof(firmware_txt
));
518 memcpy(buffer
+ sizeof(firmware_txt
), getOtherVersion(), strlen(getOtherVersion()));
520 else if (sector
< RESERVED_SECTORS
)
522 // allocated to firmware.txt
524 else if (sector
< RESERVED_SECTORS
+ (FLASHSIZE
/BLOCK_SIZE
)) {
526 address
= sector
- RESERVED_SECTORS
;
527 address
*= BLOCK_SIZE
;
528 address
+= FIRMWARE_ADDRESS
;
529 memcpy(buffer
, (uint8_t *)address
, BLOCK_SIZE
);
532 else if (sector
< RESERVED_SECTORS
+ (EEPROM_SIZE
/BLOCK_SIZE
) + (FLASHSIZE
/BLOCK_SIZE
)) {
533 eepromReadBlock(buffer
, (sector
- RESERVED_SECTORS
- (FLASHSIZE
/BLOCK_SIZE
))*BLOCK_SIZE
, BLOCK_SIZE
);
536 buffer
+= BLOCK_SIZE
;
545 int32_t fat12Write(const uint8_t * buffer
, uint16_t sector
, uint16_t count
)
547 enum FatWriteOperation
{
553 // Silence compiler warning that this is not used on X10
554 __attribute__((unused
)) static uint8_t operation
= FATWRITE_NONE
;
556 TRACE("FAT12 Write(sector=%d, count=%d)", sector
, count
);
558 if (sector
< RESERVED_SECTORS
) {
559 // reserved, read-only
561 else if (sector
< RESERVED_SECTORS
+ (FLASHSIZE
/BLOCK_SIZE
)) {
562 #if !defined(BOOT) // Don't allow overwrite of running firmware
567 address
= sector
- RESERVED_SECTORS
;
568 address
*= BLOCK_SIZE
;
569 address
+= FIRMWARE_ADDRESS
;
571 for (uint32_t i
=0; i
<BLOCK_SIZE
/FLASH_PAGESIZE
; i
++) {
572 if (address
>= FIRMWARE_ADDRESS
+BOOTLOADER_SIZE
/*protect bootloader*/ && address
<= FIRMWARE_ADDRESS
+FLASHSIZE
-FLASH_PAGESIZE
) {
573 if (address
== FIRMWARE_ADDRESS
+BOOTLOADER_SIZE
&& isFirmwareStart(buffer
)) {
574 TRACE("FIRMWARE start found in sector %d", sector
);
575 operation
= FATWRITE_FIRMWARE
;
577 if (operation
== FATWRITE_FIRMWARE
) {
578 flashWrite((uint32_t *)address
, (uint32_t *)buffer
);
581 address
+= FLASH_PAGESIZE
;
582 buffer
+= FLASH_PAGESIZE
;
586 if (sector
-RESERVED_SECTORS
>= (FLASHSIZE
/BLOCK_SIZE
)) {
587 TRACE("FIRMWARE end written at sector %d", sector
-1);
588 operation
= FATWRITE_NONE
;
594 else if (sector
< RESERVED_SECTORS
+ (EEPROM_SIZE
/BLOCK_SIZE
) + (FLASHSIZE
/BLOCK_SIZE
)) {
597 if (operation
== FATWRITE_NONE
&& isEepromStart(buffer
)) {
598 TRACE("EEPROM start found in sector %d", sector
);
599 operation
= FATWRITE_EEPROM
;
601 if (operation
== FATWRITE_EEPROM
) {
602 eepromWriteBlock((uint8_t *)buffer
, (sector
-RESERVED_SECTORS
-(FLASHSIZE
/BLOCK_SIZE
))*BLOCK_SIZE
, BLOCK_SIZE
);
604 buffer
+= BLOCK_SIZE
;
607 if (sector
-RESERVED_SECTORS
>= (EEPROM_SIZE
/BLOCK_SIZE
)+(FLASHSIZE
/BLOCK_SIZE
)) {
608 TRACE("EEPROM end written at sector %d", sector
-1);
609 operation
= FATWRITE_NONE
;