Obsługa pamięci masowych z USB za pomocą mikrokontrolerów LPC1300 firmy NXP
Rodzina mikrokontrolerów LPC1300 została zbudowana w oparciu o rdzeń ARM Cortex-M3, który przeznaczony jest do zastosowań w systemach embedded. Peryferia, w jakie wyposażone są układy rodziny LPC1300 to m.in.: do 32 kB pamięci Flash, do 8 kB pamięci danych, interfejs USB, kontrolery UART i SSP, interfejsy SPIf oraz I2C, 8-kanałowy 10-bitowy przetwornik A/C, 4 timery ogólnego przeznaczenia z PWM i do 40 wyprowadzeń wejścia/wyjścia ogólnego przeznaczenia. Oprócz tego mikrokontrolery mają też 16 kB wbudowanej pamięci ROM. W pamięci tej znajduje się bootloader dający możliwość programowania pamięci Flash przez UART i USB. Bootloader wyposażony jest w API pozwalające użytkownikom pisać własny firmware do umieszczenia w pamięci Flash. API to implementuje prosty interfejs do wbudowanej w układ funkcji programowania pamięci Flash. API do obsługi USB pomaga oprogramowywać urządzenia USB dwóch klas: interfejsu użytkownika (ang. Human Interface Device, HID) oraz pamięci masowej (ang. Mass Storage Class, MSC). Niniejszy poradnik opisuje sposób wykorzystania sterownika USB pracującego zgodnie z klasą MSC.
W artykule zostaną omówione kolejno następujące zagadnienia:
- podstawowe cechy wbudowanego sterownika USB układów LPC1300,
- konfigurację sterownika USB,
- uruchomienie przykładowego programu usbmemrom.
Interfejs USB w LPC1300
Sterownik USB w układach rodziny LPC1300 znajduje się we wbudowanej pamięci ROM. Ułatwia on projektowanie prostych urządzeń USB i pozwala zaoszczędzić pamięć Flash. Wbudowany sterownik USB implementuje zarówno urządzenia klasy HID jak i MSC.
Sterownik dla klasy HID jest przydatny przy transferowaniu umiarkowanych ilości danych (poniżej 64 kB/s) do hosta USB, do którego jest podłączony projektowany przez nas układ. Obsługuje on transfery przerywane, co pozwala na odpytywanie układu przez komputer-host. Sterownik urządzeń klasy MSC implementuje z kolei napęd dyskowy, który pozwala na odczytywanie i zapis plików z hosta.
Tab. 1. Charakterystyka wbudowanego sterownika USB
Funkcja | Sterownik HID | Sterownik MSC |
Transfery przerywane | Tak | Nie |
Punkty końcowe (endpoints) | Sterowanie, 1 wej., 1 wyj. | Sterowanie, 1 wej., 1 wyj. |
Transfery w czasie rzeczywistym | Tak | Nie |
Zapis/odczyt plików | Nie | Tak |
Źródło zegara | Zewnętrzny kwarc 12 MHz* | Zewnętrzny kwarc 12 MHz* |
Zużycie pamięci RAM | Pierwsze 384 bajty | Pierwsze 384 bajty + przechowywane dane |
Alokacja pamięci RAM
Wbudowany sterownik USB wymaga zaalokowania obszaru pamięci RAM od 0x10000050 do 0x10000180 na bufor ramek. Metoda alokacji tej częścif RAM-u zależy od konkretnego środowiska programistycznego, ale zwykle wymaga modyfikacji skryptu linkera i zmiany zakresu adresów wykorzystywanych dla danych. Jako że linkery zwykle nie są wyposażone w inteligentne algorytmy rozmieszczania działające dla małych segmentów pamięci, zalecane jest pozostawienie adresów od 0x10000000 do 0x10000050 niezaalokowanych, jak to jest pokazane na rysunku 1. Następne podrozdziały opisują procesy konfiguracji linkera w środowiskach Keil, IAR oraz LPCXpresso.
Rys. 1. Mapa pamięci mikrokontrolerów LPC1300
Pakiet LPCXpresso zwykle generuje skrypty linkera automatycznie dopasowując je do mapy pamięci wybranego mikrokontrolera LPC. Aby dostosować skrypt linkera ręcznie, należy skonfigurować LPCXpresso tak, by nie generowało skryptu ponownie (nie nadpisywało go automatycznie).
- Najpierw trzeba stworzyć i skompilować projekt (za pomocą polecenia Build). Utworzone zostaną wtedy standardowe skrypty linkera, dopasowane do konfiguracji pamięci wybranego układu LPC1300. Pliki zawierające skrypty maja rozszerzenie .ld i pojawiają się w katalogu project\build lub usbmemrom\Debug.
- Wygenerowane pliki skryptów posłużą jako baza do modyfikacji. Aby łatwo było je odróżnić od plików generowanych automatycznie, warto nadać im inne nazwy (na potrzeby tego tekstu nazwiemy je lpc1343_romusb_buffer) i przenieść do podkatalogu (np. lpcxpresso_tool, aby można je było odróżnić od plików dla środowisk Keil i IAR).
- Należy zmodyfikować plik lpc1343_romusb_buffer_mem.ld tak, aby wyłączyć obszar od 0x10000000 do 0x10000180 z mapy pamięci. Fragmenty, które należy zmienić w przypadku mikrokontrolera LPC1343 zostały wyróżnione w poniższym przykładzie
MEMORY
{
/* Define each memory region */
MFlash32 (rx) : ORIGIN = 0x0, LENGTH = 0x8000 /* 32k */
RamLoc8 (rwx) : ORIGIN = 0x10000180, LENGTH = 0x1E80 /* 8k */
}
- Następnie trzeba zmienić ścieżki dyrektyw include. Domyślnie istnieją trzy skrypty linkera: usb_buffer_lib.ld, usb_buffer_mem.ld oraz usb_buffer.ld. W pliku lpc1343_romusb_buffer.ld należy zmienić linie INCLUDE na poprawne ścieżki do plików lpc1343_romusb_buffer_lib.ld i lpc1343_romusb_buffer_mem.ld, jak jest to pokazane poniżej.
* (created from nxp_lpc13_c.ld (v3.0.6 (200911181345)) on Fri Nov 20 17:14:35 PST 2009)
*/
INCLUDE „../lpcxpreso_tool/lpc1343_romusb_buffer_lib.ld” INCLUDE „../lpcxpreso_tool/lpc1343_romusb_buffer_mem.ld”
ENTRY(ResetISR)
SECTIONS
{
…
- Na koniec trzeba skonfigurować LPCXpresso, aby używał zmodyfikowanych skryptów, co można ustawić w oknie ustawień Project Properties, w sekcji C/C++ Build Settings. W zakładce Tool Settings należy wybrać MCU Linker Target, a potem odznaczyć opcję Manage linker scripts i wstawić w polu tekstowym Linker scripts ścieżkę do nowych skryptów linkera. Ścieżka powinna być podana względem folderów wyjściowych Debug lub Release i wskazywać na główny plik skryptu, czyli ten, którego nazwa nie jest zakończona „_lib” ani „_mem”.