ISP example program.
Dependencies: SLCD mbed USBLocalFileSystem
FRDM-KL46Z | LPC810 | |
---|---|---|
UART RXD | PTE23 | p2(P0_4) |
UART TXD | PTE22 | p8(P0_0) |
nRESET | D6 | p1(P0_5) |
nISP | D8 | p5(P0_1) |
GND | GND | p7 |
3.3V | P3V3 | p6 |
Copy binary image to the disk called LPC81ISP.
Push sw1 or sw3, start write to LPC810 flash.
Diff: USBMSD2/USB_MSD.cpp
- Revision:
- 2:eafc1c6787c7
- Parent:
- 1:cccfc461c61f
--- a/USBMSD2/USB_MSD.cpp Sun Feb 16 12:56:12 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,550 +0,0 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or -* substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "USB_MSD.h" - -#if (DEBUG2 > 3) -#define MSD_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); -#else -#define MSD_DBG(...) while(0) -#endif - -#define DISK_OK 0x00 -#define NO_INIT 0x01 -#define NO_DISK 0x02 -#define WRITE_PROTECT 0x04 - -#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 packet size -#define MAX_PACKET MAX_PACKET_SIZE_EPBULK - -// CSW Status -enum Status { - CSW_PASSED, - CSW_FAILED, - CSW_ERROR, -}; - -USB_MSD::USB_MSD(USBDevice* device, DiskInterface* disk) : _device(device),_disk(disk) -{ - MSD_DBG("device=%p", device); - - stage = READ_CBW; - memset((void *)&cbw, 0, sizeof(CBW)); - memset((void *)&csw, 0, sizeof(CSW)); - page = NULL; -} - -bool USB_MSD::connect() { - - //disk initialization - if (_disk->disk_status() & NO_INIT) { - if (_disk->disk_initialize()) { - return false; - } - } - - // get number of blocks - BlockCount = _disk->disk_sectors(); - - // get memory size - MemorySize = _disk->disk_size(); - - if (BlockCount > 0) { - BlockSize = MemorySize / BlockCount; - if (BlockSize != 0) { - free(page); - page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); - if (page == NULL) - return false; - } - } else { - return false; - } - return true; -} - -void USB_MSD::disconnect() { - //De-allocate MSD page size: - free(page); - page = NULL; -} - -void USB_MSD::reset() { - stage = READ_CBW; -} - -bool USB_MSD::Request_callback(CONTROL_TRANSFER* transfer) -{ - static uint8_t msc_maxLUN[1] = {0}; - - if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { - switch (transfer->setup.bRequest) { - case MSC_REQUEST_RESET: - reset(); - return true; - - case MSC_REQUEST_GET_MAX_LUN: - transfer->remaining = 1; - transfer->ptr = msc_maxLUN; - transfer->direction = DEVICE_TO_HOST; - return true; - } - } - return false; -} - -// Called in ISR context called when a data is received -bool USB_MSD::EPBULK_OUT_callback() { - uint32_t size = 0; - uint8_t buf[MAX_PACKET_SIZE_EPBULK]; - _device->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: - _device->stallEndpoint(EPBULK_OUT); - csw.Status = CSW_ERROR; - sendCSW(); - break; - } - - //reactivate readings on the OUT bulk endpoint - _device->readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); - return true; -} - -// Called in ISR context when a data has been transferred -bool USB_MSD::EPBULK_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; - - // the host has received the CSW -> we wait a CBW - case WAIT_CSW: - stage = READ_CBW; - break; - - // an error has occured - default: - _device->stallEndpoint(EPBULK_IN); - sendCSW(); - break; - } - return true; -} - -void USB_MSD::memoryWrite (uint8_t * buf, uint16_t size) { - - if ((addr + size) > MemorySize) { - size = MemorySize - addr; - stage = ERROR; - _device->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)) { - if (!(_disk->disk_status() & WRITE_PROTECT)) { - _disk->disk_write(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 USB_MSD::memoryVerify (uint8_t * buf, uint16_t size) { - uint32_t n; - - if ((addr + size) > MemorySize) { - size = MemorySize - addr; - stage = ERROR; - _device->stallEndpoint(EPBULK_OUT); - } - - // beginning of a new block -> load a whole block in RAM - if (!(addr%BlockSize)) - _disk->disk_read(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 USB_MSD::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 USB_MSD::readFormatCapacity() { - uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, - (uint8_t)((BlockCount >> 24) & 0xff), - (uint8_t)((BlockCount >> 16) & 0xff), - (uint8_t)((BlockCount >> 8) & 0xff), - (uint8_t)((BlockCount >> 0) & 0xff), - - 0x02, - (uint8_t)((BlockSize >> 16) & 0xff), - (uint8_t)((BlockSize >> 8) & 0xff), - (uint8_t)((BlockSize >> 0) & 0xff), - }; - if (!write(capacity, sizeof(capacity))) { - return false; - } - return true; -} - -bool USB_MSD::readCapacity (void) { - uint8_t capacity[] = { - (uint8_t)(((BlockCount - 1) >> 24) & 0xff), - (uint8_t)(((BlockCount - 1) >> 16) & 0xff), - (uint8_t)(((BlockCount - 1) >> 8) & 0xff), - (uint8_t)(((BlockCount - 1) >> 0) & 0xff), - - (uint8_t)((BlockSize >> 24) & 0xff), - (uint8_t)((BlockSize >> 16) & 0xff), - (uint8_t)((BlockSize >> 8) & 0xff), - (uint8_t)((BlockSize >> 0) & 0xff), - }; - if (!write(capacity, sizeof(capacity))) { - return false; - } - return true; -} - -bool USB_MSD::write (uint8_t * buf, uint16_t size) { - - if (size >= cbw.DataLength) { - size = cbw.DataLength; - } - stage = SEND_CSW; - - if (!_device->writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { - return false; - } - - csw.DataResidue -= size; - csw.Status = CSW_PASSED; - return true; -} - -bool USB_MSD::modeSense6 (void) { - uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; - if (!write(sense6, sizeof(sense6))) { - return false; - } - return true; -} - -void USB_MSD::sendCSW() { - csw.Signature = CSW_Signature; - _device->writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); - stage = WAIT_CSW; -} - -bool USB_MSD::requestSense (void) { - uint8_t request_sense[] = { - 0x70, - 0x00, - 0x05, // Sense Key: illegal request - 0x00, - 0x00, - 0x00, - 0x00, - 0x0A, - 0x00, - 0x00, - 0x00, - 0x00, - 0x30, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - }; - - if (!write(request_sense, sizeof(request_sense))) { - return false; - } - - return true; -} - -void USB_MSD::fail() { - csw.Status = CSW_FAILED; - sendCSW(); -} - -void USB_MSD::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 { - _device->stallEndpoint(EPBULK_OUT); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - case WRITE10: - case WRITE12: - if (infoTransfer()) { - if (!(cbw.Flags & 0x80)) { - stage = PROCESS_CBW; - } else { - _device->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 { - _device->stallEndpoint(EPBULK_IN); - csw.Status = CSW_ERROR; - sendCSW(); - } - } - break; - case MEDIA_REMOVAL: - csw.Status = CSW_PASSED; - sendCSW(); - break; - default: - fail(); - break; - } - } - } - } -} - -void USB_MSD::testUnitReady (void) { - - if (cbw.DataLength != 0) { - if ((cbw.Flags & 0x80) != 0) { - _device->stallEndpoint(EPBULK_IN); - } else { - _device->stallEndpoint(EPBULK_OUT); - } - } - - csw.Status = CSW_PASSED; - sendCSW(); -} - -void USB_MSD::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->disk_read(page, addr/BlockSize); - - // write data which are in RAM - _device->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; - stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; - } -} - -bool USB_MSD::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) { - _device->stallEndpoint(EPBULK_IN); - } else { - _device->stallEndpoint(EPBULK_OUT); - } - - csw.Status = CSW_FAILED; - sendCSW(); - return false; - } - - return true; -}