Для продолжения знакомства с контроллерами LPC13xx, установленными на плате VE-XC6SLX9 на сей раз изучим пример использования встроенного класса USB mass storage (или попросту USB-флешки). В контроллер LPC13xx встроен драйвер для USB-MSC класса. Этот драйвер используется USB загрузчиком, но и вы его можете использовать в своих целях.
Изложенный материал базируется на аппноуте AN10905, который вы можете найти в разделе Application Notes сайта NXP. Работа с обычными не SHDC картами изложена в статье LPCXpresso Урок 11. USB+SPI. Делаем картридер.. Автор в своем примере использует код для работы с устаревшими картами низкой емкости.
Для исправления этой досадной оплошности необходимо заменить файл sdcard.c на sdhccard.c.
После этого нужно изменить функции чтения и записи секторов флэш карты в файле msccallback.c:
C++ Code:
/*---------------------------------------------------------------------------- * U S B - K e r n e l *---------------------------------------------------------------------------- * Name: mscuser.c * Purpose: Mass Storage Class Custom User Module * Version: V1.20 *---------------------------------------------------------------------------- * This software is supplied "AS IS" without any warranties, express, * implied or statutory, including but not limited to the implied * warranties of fitness for purpose, satisfactory quality and * noninfringement. Keil extends you a royalty-free right to reproduce * and distribute executable files created using this software for use * on NXP Semiconductors LPC microcontroller devices only. Nothing else * gives you the right to use this software. * * Copyright (c) 2009 Keil - An ARM Company. All rights reserved. *---------------------------------------------------------------------------*/ #include "lpc13xx.h" #include "type.h" #include "usb.h" #include "msccallback.h" #include "sdhccard.h" const uint8_t InquiryStr[] = {'K','e','i','l',' ',' ',' ',' ', \ 'L','P','C','1','3','x','x',' ', \ 'D','i','s','k',' ',' ',' ',' ', \ '1','.','0',' ',}; uint8_t CardBuffer[512]; uint32_t Sector = 0; uint8_t Cached = 0; uint8_t Changed = 0; void SetLed(uint32_t val); void SwitchSector(uint32_t number) { if(Cached) { if(Sector == number) { return; } if(Changed) { disk_write(0,CardBuffer,Sector,1); //SD_WriteSector(Sector, CardBuffer); Changed = 0; } } Sector = number; //if(SD_ReadSector(Sector, CardBuffer)) if(disk_read(0,CardBuffer,Sector,1)) while(1); Cached = 1; } void MSC_MemoryRead (uint32_t offset, uint8_t dst[], uint32_t length) { uint32_t n; SetLed(1); SwitchSector(offset/512); offset %= 512; for (n = 0; n < length; n++) { dst[n] = CardBuffer[offset + n]; } SetLed(0); } void MSC_MemoryWrite (uint32_t offset, uint8_t src[], uint32_t length) { uint32_t n; SetLed(1); SwitchSector(offset/512); offset %= 512; for (n = 0; n < length; n++) { CardBuffer[offset+n] = src[n]; } Changed = 1; if(offset + length == 512) { disk_write(0,CardBuffer,Sector,1); //SD_WriteSector(Sector, CardBuffer); Changed = 0; } SetLed(0); }
Изменения достаточно просты: необходимо поменять файлы чтения и записи карты низкой емкости SD_ReadSector(Sector, CardBuffer) и SD_WriteSector(Sector, CardBuffer) на аналогичные функции для работы с SDHC картами disk_write(0,CardBuffer,Sector,1) и disk_read(0,CardBuffer,Sector,1). Далее я долго думал как с помощью 32 бит передать объем карты больше 4 GB :))))) Оказалось все достаточно банально: необходимо в качестве объема карты MSC_MemorySize передать все 1 т.е. 0xFFFFFFFF. В данном случае объем кары определяется как произведение MSC_BlockCount*MSC_BlockSize. Походит на какой-то чит :)))) Для имевшейся у меня карточки Toshiba 8 GB получилось следующее:
C++ Code:
#define MSC_BlockCount 15130624 #define MSC_BlockSize 512 #define MSC_MemorySize 0xFFFFFFFF
После этого проект собирается и запускается. Осталось привести результат тестирования скорости и исходные файлы.
Проект USB диск с картой MicroSDHC: usb_mem_rom.zip