USB MSD using the AHBSRAM banks 0 and 1 to create a 32k RAM disk. After FAT format 12kb is writable
Dependencies: USBDevice USBMSD_RAM mbed
Fork of USB-MSD_SD_HelloWorld_Mbed-RAMVersion by
Revision 13:32b8a767cf0e, committed 2011-12-05
- Comitter:
- samux
- Date:
- Mon Dec 05 14:34:29 2011 +0000
- Parent:
- 12:a12eb1fc05f3
- Child:
- 14:757226626acb
- Commit message:
- big cleaning up. all is working!!!
Changed in this revision
--- a/ChaNFSSD/SDFileSystem.cpp Wed Nov 30 17:50:35 2011 +0000 +++ b/ChaNFSSD/SDFileSystem.cpp Mon Dec 05 14:34:29 2011 +0000 @@ -208,7 +208,7 @@ return 1; } - _spi.frequency(1000000); // Set to 1MHz for data transfer + _spi.frequency(5000000); // Set to 5MHz for data transfer return 0; } @@ -439,19 +439,24 @@ fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n"); return 0; } - + // memory capacity = BLOCKNR * BLOCK_LEN // where // BLOCKNR = (C_SIZE+1) * MULT // MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8) // BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12) - + int block_len = 1 << read_bl_len; int mult = 1 << (c_size_mult + 2); int blocknr = (c_size + 1) * mult; - int capacity = blocknr * block_len; - + capacity = blocknr * block_len; + int blocks = capacity / 512; return blocks; } + + +int SDFileSystem::disk_size() { + return capacity; +}
--- a/ChaNFSSD/SDFileSystem.h Wed Nov 30 17:50:35 2011 +0000 +++ b/ChaNFSSD/SDFileSystem.h Mon Dec 05 14:34:29 2011 +0000 @@ -59,6 +59,7 @@ virtual int disk_status(); virtual int disk_sync(); virtual int disk_sectors(); + virtual int disk_size(); protected: @@ -75,6 +76,8 @@ int _sd_sectors(); int _sectors; + int capacity; + SPI _spi; DigitalOut _cs; };
--- a/USBMSD/USBMSD.cpp Wed Nov 30 17:50:35 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,615 +0,0 @@ -// USBMSD.cpp -// USB mass storage device example -// Copyright (c) 2011 ARM Limited. All rights reserved. - -#include "stdint.h" -#include "USBMSD.h" -#include "USBBusInterface.h" - -#define CBW_Signature 0x43425355 -#define CSW_Signature 0x53425355 - -// SCSI Commands -#define TEST_UNIT_READY 0x00 -#define REQUEST_SENSE 0x03 -#define FORMAT_UNIT 0x04 -#define INQUIRY 0x12 -#define MODE_SELECT6 0x15 -#define MODE_SENSE6 0x1A -#define START_STOP_UNIT 0x1B -#define MEDIA_REMOVAL 0x1E -#define READ_FORMAT_CAPACITIES 0x23 -#define READ_CAPACITY 0x25 -#define READ10 0x28 -#define WRITE10 0x2A -#define VERIFY10 0x2F -#define READ12 0xA8 -#define WRITE12 0xAA -#define MODE_SELECT10 0x55 -#define MODE_SENSE10 0x5A - -// MSC class specific requests -#define MSC_REQUEST_RESET 0xFF -#define MSC_REQUEST_GET_MAX_LUN 0xFE - -#define DEFAULT_CONFIGURATION (1) - -// Max In/Out Packet Size on the bulk endpoint */ -#define MAX_PACKET MAX_PACKET_SIZE_EPBULK - -// CSW Status -enum Status { - CSW_PASSED, - CSW_FAILED, - CSW_ERROR, -}; - - -USBMSD::USBMSD(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) { -} - - -DigitalOut l2(LED2); -// Called in ISR context to process a class specific request -bool USBMSD::USBCallback_request(void) { - - bool success = false; - CONTROL_TRANSFER * transfer = getTransferPtr(); - - if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { - switch (transfer->setup.bRequest) { - case MSC_REQUEST_RESET: - reset(); - success = true; - break; - case MSC_REQUEST_GET_MAX_LUN: - transfer->remaining = 1; - transfer->ptr = getMaxLUN(); - transfer->direction = DEVICE_TO_HOST; - success = true; - break; - default: - break; - } - } - - return success; -} - - -bool USBMSD::connect() { - - //disk initialization - disk_initialize(); - - // get block size - BlockSize = 512; - if (BlockSize != 0) { - page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); - if (page == NULL) - return false; - } - - BlockCount = disk_sectors(); - - //get memory size - MemorySize = BlockCount * BlockSize; - if (!MemorySize) { - return false; - } - - //connect the device - USBDevice::connect(); - return true; -} - - -void USBMSD::reset() { - stage = READ_CBW; -} - -uint8_t * USBMSD::getMaxLUN() { - static uint8_t LUN[] = {0}; - return LUN; -} - -// Called in ISR context called when a data is received -bool USBMSD::EP2_OUT_callback() { - uint16_t size = 0; - uint8_t buf[MAX_PACKET_SIZE_EPBULK]; - readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK); - switch (stage) { - // the device has to decode the CBW received - case READ_CBW: - CBWDecode(buf, size); - break; - - // the device has to receive data from the host - case PROCESS_CBW: - switch (cbw.CB[0]) { - case WRITE10: - case WRITE12: - memoryWrite(buf, size); - break; - case VERIFY10: - memoryVerify(buf, size); - break; - } - break; - - // an error has occured: stall endpoint and send CSW - default: - stallEndpoint(EPBULK_OUT); - csw.Status = CSW_ERROR; - sendCSW(); - break; - } - - //reactivate readings on the OUT bulk endpoint - readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); - return true; -} - -// Called in ISR context when a data has been transferred -bool USBMSD::EP2_IN_callback() { - switch (stage) { - - // the device has to send data to the host - case PROCESS_CBW: - switch (cbw.CB[0]) { - case READ10: - case READ12: - memoryRead(); - break; - } - break; - - //the device has to send a CSW - case SEND_CSW: - sendCSW(); - break; - - // an error has occured - case ERROR: - stallEndpoint(EPBULK_IN); - sendCSW(); - break; - - // the host has received the CSW -> we wait a CBW - case WAIT_CSW: - stage = READ_CBW; - break; - } - return true; -} - - -void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) { - - if ((addr + size) > MemorySize) { - size = MemorySize - addr; - stage = ERROR; - stallEndpoint(EPBULK_OUT); - } - - // we fill an array in RAM of 1 block before writing it in memory - for (int i = 0; i < size; i++) - page[addr%BlockSize + i] = buf[i]; - - // if the array is filled, write it in memory - if (!((addr + size)%BlockSize)) - disk_write((const char *)page, addr/BlockSize); - - addr += size; - length -= size; - csw.DataResidue -= size; - - if ((!length) || (stage != PROCESS_CBW)) { - csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; - sendCSW(); - } -} - -void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) { - uint32_t n; - - if ((addr + size) > MemorySize) { - size = MemorySize - addr; - stage = ERROR; - stallEndpoint(EPBULK_OUT); - } - - // beginning of a new block -> load a whole block in RAM - if (!(addr%BlockSize)) - disk_read((char *)page, addr/BlockSize); - - // info are in RAM -> no need to re-read memory - for (n = 0; n < size; n++) { - if (page[addr%BlockSize + n] != buf[n]) { - memOK = false; - break; - } - } - - addr += size; - length -= size; - csw.DataResidue -= size; - - if ( !length || (stage != PROCESS_CBW)) { - csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; - sendCSW(); - } -} - - -bool USBMSD::inquiryRequest (void) { - uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, - 36 - 4, 0x80, 0x00, 0x00, - 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', - 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', - '1', '.', '0', ' ', - }; - if (!write(inquiry, sizeof(inquiry))) { - return false; - } - return true; -} - - -bool USBMSD::readFormatCapacity() { - uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, - (BlockCount >> 24) & 0xff, - (BlockCount >> 16) & 0xff, - (BlockCount >> 8) & 0xff, - (BlockCount >> 0) & 0xff, - - 0x02, - (BlockSize >> 16) & 0xff, - (BlockSize >> 8) & 0xff, - (BlockSize >> 0) & 0xff, - }; - if (!write(capacity, sizeof(capacity))) { - return false; - } - return true; -} - - -bool USBMSD::readCapacity (void) { - uint8_t capacity[] = { - ((BlockCount - 1) >> 24) & 0xff, - ((BlockCount - 1) >> 16) & 0xff, - ((BlockCount - 1) >> 8) & 0xff, - ((BlockCount - 1) >> 0) & 0xff, - - (BlockSize >> 24) & 0xff, - (BlockSize >> 16) & 0xff, - (BlockSize >> 8) & 0xff, - (BlockSize >> 0) & 0xff, - }; - if (!write(capacity, sizeof(capacity))) { - return false; - } - return true; -} - -bool USBMSD::write (uint8_t * buf, uint16_t size) { - - if (size >= cbw.DataLength) { - size = cbw.DataLength; - } - stage = SEND_CSW; - - if (!writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { - return false; - } - - csw.DataResidue -= size; - csw.Status = CSW_PASSED; - return true; -} - - -bool USBMSD::modeSense6 (void) { - uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; - if (!write(sense6, sizeof(sense6))) { - return false; - } - return true; -} - -void USBMSD::sendCSW() { - csw.Signature = CSW_Signature; - writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); - stage = WAIT_CSW; -} - -bool USBMSD::requestSense (void) { - uint8_t request_sense[] = { - 0x70, // Response Code - 0x00, - 0x05, // Sense Key: illegal request - 0x00, - 0x00, - 0x00, - 0x00, - 0x0A, // Additional Length - 0x00, - 0x00, - 0x00, - 0x00, - 0x30, // ASC - 0x01, // ASCQ - 0x00, - 0x00, - 0x00, - 0x00, - }; - - if (!write(request_sense, sizeof(request_sense))) { - return false; - } - - return true; -} - -void USBMSD::fail() { - csw.Status = CSW_FAILED; - sendCSW(); -} - -DigitalOut l1(LED1); -void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) { - if (size == sizeof(cbw)) { - memcpy((uint8_t *)&cbw, buf, size); - if (cbw.Signature == CBW_Signature) { - csw.Tag = cbw.Tag; - csw.DataResidue = cbw.DataLength; - if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { - fail(); - } else { - switch (cbw.CB[0]) { - case TEST_UNIT_READY: - testUnitReady(); - break; - case REQUEST_SENSE: - requestSense(); - break; - case INQUIRY: - inquiryRequest(); - break; - case MODE_SENSE6: - modeSense6(); - break; - case READ_FORMAT_CAPACITIES: - readFormatCapacity(); - break; - case READ_CAPACITY: - readCapacity(); - break; - case READ10: - case READ12: - if (infoTransfer()) { - if ((cbw.Flags & 0x80)) { - stage = PROCESS_CBW; - memoryRead(); - } else { - stallEndpoint(EPBULK_OUT); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - case WRITE10: - case WRITE12: - if (infoTransfer()) { - if (!(cbw.Flags & 0x80)) { - stage = PROCESS_CBW; - } else { - stallEndpoint(EPBULK_IN); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - case VERIFY10: - if (!(cbw.CB[1] & 0x02)) { - csw.Status = CSW_PASSED; - sendCSW(); - break; - } - if (infoTransfer()) { - if (!(cbw.Flags & 0x80)) { - stage = PROCESS_CBW; - memOK = true; - } else { - stallEndpoint(EPBULK_IN); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - default: - fail(); - break; - } - } - } - } -} - -void USBMSD::testUnitReady (void) { - - if (cbw.DataLength != 0) { - if ((cbw.Flags & 0x80) != 0) { - stallEndpoint(EPBULK_IN); - } else { - stallEndpoint(EPBULK_OUT); - } - } - - csw.Status = CSW_PASSED; - sendCSW(); -} - - -void USBMSD::memoryRead (void) { - uint32_t n; - - n = (length > MAX_PACKET) ? MAX_PACKET : length; - - if ((addr + n) > MemorySize) { - n = MemorySize - addr; - stage = ERROR; - } - - // we read an entire block - if (!(addr%BlockSize)) - disk_read((char *)page, addr/BlockSize); - - // write data which are in RAM - writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK); - - addr += n; - length -= n; - - csw.DataResidue -= n; - - if ( !length || (stage != PROCESS_CBW)) { - csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; - sendCSW(); - } -} - - -bool USBMSD::infoTransfer (void) { - uint32_t n; - - // Logical Block Address of First Block - n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); - - addr = n * BlockSize; - - // Number of Blocks to transfer - switch (cbw.CB[0]) { - case READ10: - case WRITE10: - case VERIFY10: - n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); - break; - - case READ12: - case WRITE12: - n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); - break; - } - - length = n * BlockSize; - - if (!cbw.DataLength) { // host requests no data - csw.Status = CSW_FAILED; - sendCSW(); - return false; - } - - if (cbw.DataLength != length) { - if ((cbw.Flags & 0x80) != 0) { - stallEndpoint(EPBULK_IN); - } else { - stallEndpoint(EPBULK_OUT); - } - - csw.Status = CSW_FAILED; - sendCSW(); - return false; - } - - return true; -} - - - - - -// Called in ISR context -// Set configuration. Return false if the -// configuration is not supported. -bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) { - if (configuration != DEFAULT_CONFIGURATION) { - return false; - } - - // Configure endpoints > 0 - addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK); - addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); - - //activate readings - readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); - return true; -} - - -uint8_t * USBMSD::stringIinterfaceDesc() { - static uint8_t stringIinterfaceDescriptor[] = { - 0x08, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'M',0,'S',0,'D',0 //bString iInterface - MSD - }; - return stringIinterfaceDescriptor; -} - -uint8_t * USBMSD::stringIproductDesc() { - static uint8_t stringIproductDescriptor[] = { - 0x12, //bLength - STRING_DESCRIPTOR, //bDescriptorType 0x03 - 'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio - }; - return stringIproductDescriptor; -} - - -uint8_t * USBMSD::configurationDesc() { - static uint8_t configDescriptor[] = { - - // Configuration 1 - 9, // bLength - 2, // bDescriptorType - LSB(9 + 9 + 7 + 7), // wTotalLength - MSB(9 + 9 + 7 + 7), - 0x01, // bNumInterfaces - 0x01, // bConfigurationValue: 0x01 is used to select this configuration - 0x00, // iConfiguration: no string to describe this configuration - 0xC0, // bmAttributes - 100, // bMaxPower, device power consumption is 100 mA - - // Interface 0, Alternate Setting 0, MSC Class - 9, // bLength - 4, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - 0x08, // bInterfaceClass - 0x06, // bInterfaceSubClass - 0x50, // bInterfaceProtocol - 0x04, // iInterface - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - PHY_TO_DESC(EPBULK_IN), // bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) - 0, // bInterval - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) - 0 // bInterval - }; - return configDescriptor; -}
--- a/USBMSD/USBMSD.h Wed Nov 30 17:50:35 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -/* USBMSD.h */ -/* USB mass storage device example */ -/* Copyright (c) 2011 ARM Limited. All rights reserved. */ - -/* -* Guide to adapt this class to your storage chip: -* -*/ - -#ifndef USBMSD_H -#define USBMSD_H - -/* These headers are included for child class. */ -#include "USBEndpoints.h" -#include "USBDescriptor.h" -#include "USBDevice_Types.h" - -#include "USBDevice.h" - -#define DEFAULT_CONFIGURATION (1) - - -// MSC Bulk-only Stage -enum Stage { - READ_CBW, // wait a CBW - ERROR, // error - PROCESS_CBW, // process a CBW request - SEND_CSW, // send a CSW - WAIT_CSW, // wait that a CSW has been effectively sent -}; - -// Bulk-only CBW -typedef __packed struct { - uint32_t Signature; - uint32_t Tag; - uint32_t DataLength; - uint8_t Flags; - uint8_t LUN; - uint8_t CBLength; - uint8_t CB[16]; -} CBW; - -// Bulk-only CSW -typedef __packed struct { - uint32_t Signature; - uint32_t Tag; - uint32_t DataResidue; - uint8_t Status; -} CSW; - - -class USBMSD: public USBDevice { -public: - - /** - * Constructor - * - * @param vendor_id Your vendor_id - * @param product_id Your product_id - * @param product_release Your preoduct_release - */ - USBMSD(uint16_t vendor_id = 0x0703, uint16_t product_id = 0x0104, uint16_t product_release = 0x0001); - - /* - * read a block on a storage chip - * - * @param data pointer where will be stored read data - * @param block block number - * @returns 0 if successful - */ - virtual int disk_read(char * data, int block){return 1;}; - - /* - * write a block on a storage chip - * - * @param data data to write - * @param block block number - * @returns 0 if successful - */ - virtual int disk_write(const char * data, int block){return 1;}; - - /* - * Disk initilization - */ - virtual int disk_initialize(){return -1;}; - - /* - * Return the number of blocks - * - * @returns number of blocks - */ - virtual int disk_sectors(){return 0;}; - - /* - * Return memory size - * - * @returns memory size - */ - virtual uint32_t memorySize(){return 0;}; - - /* - * Connect the USB MSD device. Establish disk initialization before really connect the device. - * - * @returns - */ - bool connect(); - - -protected: - - - /* - * Get number of logical unit - 1 (here 0) - * - * @returns Pointer containing the number of logical unit - 1 - */ - uint8_t * getMaxLUN(); - - /* - * Get string product descriptor - * - * @returns pointer to the string product descriptor - */ - virtual uint8_t * stringIproductDesc(); - - /* - * Get string interface descriptor - * - * @returns pointer to the string interface descriptor - */ - virtual uint8_t * stringIinterfaceDesc(); - - /* - * Get configuration descriptor - * - * @returns pointer to the configuration descriptor - */ - virtual uint8_t * configurationDesc(); - - /* - * Callback called when a packet is received - */ - virtual bool EP2_OUT_callback(); - - /* - * Callback called when a packet has been sent - */ - virtual bool EP2_IN_callback(); - - /* - * Set configuration of device. Add endpoints - */ - virtual bool USBCallback_setConfiguration(uint8_t configuration); - - /* - * Callback called to process class specific requests - */ - virtual bool USBCallback_request(); - - -private: - //state of the bulk-only state machine - Stage stage; - - // current CBW - CBW cbw; - - // CSW which will be sent - CSW csw; - - // addr where will be read or written data - uint32_t addr; - - // length of a reading or writing - uint32_t length; - - // memory OK (after a memoryVerify) - bool memOK; - - // cache in RAM before writing in memory. Useful also to read a block. - uint8_t * page; - - uint16_t BlockSize; - uint32_t MemorySize; - uint16_t BlockCount; - - void CBWDecode(uint8_t * buf, uint16_t size); - void sendCSW (void); - bool inquiryRequest (void); - bool write (uint8_t * buf, uint16_t size); - bool readFormatCapacity(); - bool readCapacity (void); - bool infoTransfer (void); - void memoryRead (void); - bool modeSense6 (void); - void testUnitReady (void); - bool requestSense (void); - void memoryVerify (uint8_t * buf, uint16_t size); - void memoryWrite (uint8_t * buf, uint16_t size); - void reset(); - void fail(); -}; - -#endif
--- a/main.cpp Wed Nov 30 17:50:35 2011 +0000 +++ b/main.cpp Mon Dec 05 14:34:29 2011 +0000 @@ -1,7 +1,7 @@ #include "mbed.h" #include "SDFileSystem.h" -SDFileSystem sd(p11, p12, p13, p14, "sd"); +SDFileSystem sd(p5, p6, p7, p8, "sd"); DigitalIn button(p16);