Aloittelua ARM LPC1768 alustalla

Tämä kirjoitus käsittelee omia kokemuksiani robomaasta hankittusta blueboard LPC1768-H:sta sekä CP210 pohjaisesta USB to TTL muuntimesta. Tämän kirjoituksen tarkoitus on lähinnä täydentää ruuvipenkin ARM-kontrolleritutoriaalia, bootloaderin sekä softapuolen osalta.

[size=150]Piuhat kiinni[/size]
Tarina alkaa viime viikonlopusta, jolloin vihdoin oli aikaa säätää ruuvipenkistä voittamaani ja robomaasta hankkimiani rojuja.

http://www.robomaa.com/index.php?main_page=product_info&cPath=106&products_id=745

http://www.robomaa.com/index.php?main_page=product_info&cPath=70_73&products_id=602

Ensin varmistin USB-UART muuntimen toimivuuden yhdistämällä hyppylangalla RXD ja TXD linjat ja kytkemällä muuntimen PC:hen. dmesg osoitti että laite tunnistui, kun kernelistä sattui löytymään tuki sarjaporttilaitteille. muuntimen toimivuuden osoittaminen käy vaikka minicom:lla. Tai ehkä helpommin pythoninpätkällä

# -*- coding: iso-8859-1 -*-
import serial
ser = serial.Serial("/dev/ttyUSB3",9600)
print ser.portstr
ser.write("?\n")
while(1):
	line = ser.readline()
	print "luettiin "+line
ser.close()

Control+C lopettaa, ruudulle pitäisi tulla luettiin “?”

Muunnin toimi, loistavaa. Muistutuksena, että kyseinen muunnin käyttää +5V:n jännitetasoja, onneksi LPC1768:n UART0 on +5V tolerantti.

Sitten blueboard kiinni usb-mini johdolla PC:hen, valot syttyivät, hyvä ja jokin demosofta alkoi pyörimään. Muistaakseni USB-liitäntä esitti jotain HID laitetta. Oma blueboardini nyt sattui olemaan sellaista erää, että USB bootloaderi ei siihen jostainsyystä oltu asennetu. Manuaalin mukaan uudemmissa levyissä sellainen pitäisi olla asennettuna Siispä perinteinen USB-loaderi käyttöön.

Bootloaderi tarkoittaa suomeksi sellaista koodinpätkää, joka kyttää käynnistyksessä jonkinaikaa jonkin tietyn pinnin tilaa. Jos linjaa kiskotaan kontrollerin käynnistyksenaikana alas, bootloaderi tietää että kontrolleri on tarkoitus uudellenohjelmoida tai käyttää debuggaustilassa. Tällöin bootloaderi jää odottamaan ohjeita USB:stä,UART linjasta tai ethernet liitännästä. Atmelin atmega U2 ja U4 sarjan kontrollereissa bootloaderi muuttaa kontrollerin näyttämään USB:n kannalta DFU-laitteelta. Tällöin kontrolleriin saa ohjelmoitua dfu-programmer nimisellä ohjelmalla.

Kuitenkin LPC1768:n tapauksessa kontrollerin natiivi bootloaderi haluaa jutella uart0:n kanssa, ei USB:n.LPC1768:lle on kuitenkin tarjolla erillinen bootloaderi, joka muuttaa LPC1768:n näyttämään USB-levyasemalta eli erillistä poltto-ohjelmaa ei tarvita. Siispä keksimään, miten Blueboard lankun saa kiinni USB-UART muuntimeen.

Kurotin käden romulootaani ja sieltä löytyi CD-rom aseman ja äänikortin välillemenevä nelilinjainen piuha, mikä sopii myös piikkirimaan. RX ja TX linjat ovat blueboardilla näppärästi riman päissä, joten sen puolen sai helposti kiinni. Irroitin blueboardin puoleisesta liittimestä yhden piuhan ja varmuuden vuoksi erikseen yhdistin sen läheiseen GND pinniin. Vaikka kortti saakin maata varsin hyvin varsinaisen USB liittimen kautta.
usbuartkytkenta.png
USB-uart muuntimen puolella tarvitiin kolvia. kolvasin kaksi piikkirimaa vastakkain, jotta johdon saisi naaraspuoleiseen liittimeen kiinni. Pinoutti usb-uart muuntimelle on

  • GND
  • +5V
  • RTS
  • TXD
  • RXD
  • NC
  • NC

Tarkoitus oli kytkeä liitin TDX,RXD,NC ja NC paikkoihin. NC linjat olivat nimenomaan not connected…hmm… miksiköhän, joten samantien yhdistin ne lyhyellä hyppylangalla maahan, jotta saisin maahankytkentyn piuhan muuntimen GND:hen LPC:n RX tulee muuntimen TX:ään ja LPC:n TX ->RX.

blueboardKytkenta.png

[size=150]USB-Bootloaderin poltto[/size]

Natiivi-bootloaderi kyttää 2.10 linjaa eli bsl-linjaa. Virallinen USB bootloader taas 2.12 linjaa. Ja blueboardilla olisi kytkin 2.10:iin liitettynä. Satuin löytämään googlatessani ongelmaan ratkaisun
Blogi:
http://gvworks.blogspot.com/2010/10/usb-bootloader-for-blueboard.html
Ja kasa esimerkkejä
http://code.google.com/p/cortex-m3-tutorials/
http://code.google.com/p/embeddedhobby/downloads/list

Sieltä
LPC1700 Secondary USB bootloader for NGX BlueBoard.rar
En tässävaiheessa jaksanut alkaa miettimään kääntämistä… Joten luotin että kukaan ei ole bootloaderibinin sijaan kirjoittanut koodia joka saa blueboardin muuttumaan usb näppäimistöksi joka hmm… joko windows käyttäjien riesaksi painaa win+r näppäintä painaa backspacea kirjoittaa cmd ja perään enter, ja tämän jälkeen antaa muutaman hassun komennon. (tai vaihtoehtoisesti toivoo, että käyttäjä on roottina sisällä, sulkee X-ikkunoinnin ja antaa muutaman komennon)

Seuraavaksi piti löytää pätevä uart-ohjelmointisofta. Sellainen on flash magic…
http://www.flashmagictool.com/
Joka toimii vain windowsissa… :frowning: Ja tietenkin winessä. :sunglasses:

Heti tulee mieleen… miksiköhän kukaan ei ole tehnyt open source-versiota… pitäisiköhän sitä itse vaivautua? Sehän on vaan sarjaporttiin kirjoittelua ja lukemista :smiley:

Asennus-exe:n kopiointi ~/.wine/drive_c/ asennusohjelman ajo, pari klikkausta ja flashmagic asennettu ongelmitta. Seuraava ongelma “miten saan linuxin sarjaporttilaitteen näkymään winelle”. Ratkaisu: tehdään hakemistoon
~/.wine/dosdevices/
linkki

ln -s /dev/ttyUSB3 com10

missä ttyUSB3 oli usb-sarja muuntimelle tuleva portti. com10 taas voi olla mikätahansa vapaa com-portti

flashmagic.png
Flash magic päälle
Deviceksi LPC1768, COM10, 9600,erase blocks ja verify päälle.Valitaan heksa.
Painetaan blueboardin resetti ja BSL nappi alas, vapautetaan reset ja sen jälkeen BSL. Lankulla olevan yksi lankun ledeistä pitäisi hehkua himmeänä. Ja painetaan flash magickistä start.

Allekirjoittaneella oli pieniä vaikeuksia :mrgreen: , johtuen huolimattomasta johtoviritelmästä. Kun törmäätte ongelmiin, kannattaa vianhaku aloittaa

  • Ottamalla LPC:n puoleiset piuhat irti ja oikosulkemalla RX ja TX linjat, lähetetään terminalilla jotain ja katsotaan että merkit tulee läpi
    (puttyn ajaminen winellä, että wine käsittelee porttia oikein. Tosin luultavasti fonttiongelmien takia jotkin merkit tulostuvat C kirjaimina)
  • LPC:n bootloaderin pitäisi vastata Syncronized, jos sille heittää terminaalilla kysymysmerkkiä (kts python-testikoodi)

Bootloaderi ohjelmoitui. Modifioitu USB bootloaderi aktivoidaan siten, että

  • Resetoidaan blueboard
  • Kun ledi alkaa vilkkua (aikaa vajaa pari sekunttia), painetaan sen aikana BSL nappia.
    Jos halutaan että natiivi uart0-bootloaderi aktivoituu, tällöin tietysti pidetään BSL nappia pohjassa resetin aikana.

[size=150]USB-Bootloader juttelemaan linuxin kanssa[/size]

LPC1768 ilmestyi näkymään /dev/sdb-laitteena. Ja sen sai mountattua. Levyltä löytyi sen kokonaan täyttämä firmware.bin, joka tietenkin pitää poistaa ennenkuin sinne voi kopioida oman .bin tiedoston.

26521.450134] scsi 10:0:0:0: Direct-Access Keil LPC1700 Disk 1.0 PQ: 0 ANSI: 0 CCS
[26521.450332] sd 10:0:0:0: Attached scsi generic sg3 type 0
[26521.450750] usb-storage: device scan complete
[26521.456085] sd 10:0:0:0: [sdb] 1012 512-byte logical blocks: (518 kB/506 KiB)
[26521.459091] sd 10:0:0:0: [sdb] Write Protect is off

Säätämisestä huolimatta, bootloaderi ei tuntunut suostunut päivittämään firmistä. Ja kyllä… juu, kokeilin kaikki mahdolliset “sync” komennon antamisen mounttauksen jälkeen, kopioinnin jälkeen… umountin tekemisen yms. mountin -o optiolla remountit, useri dev sync nosync yms yritelmät.
http://mbed.org/handbook/Mounting-with-sync

Meinasin jo heittää blueboardilla rauhoitettua vesilintua, kunnes nöyrryin tarpeeksi ja buuttasin windowsiin…Siellä se toimi… WTF!!!

Syy loppupeleissä oli se että usb bootloaderi on vaan niin keharisti ja standardia rikkoen toteutettu, että se ei kykene juttelemaan linuxin ajureiden kanssa, wintöötissä se toimii… Niinkuin hurrit sanovat, Lika barn leker best, eli samanlaiset ladot leikkivät parhaiten.

Googlailu tuotti tulosta… AH-HAA!!! :bulb:
http://www.gnu.org/software/mtools/

Ilman mitään mounttauksia, kun tarvittavilla oikeuksilla (roottina) käskee

mdel -i /dev/sdb ::/firmware.bin
mcopy -i /dev/sdb main.bin ::/

ja painaa odottelun jälkeen resettiä (olettaen että kontrolleri ajettiin ohjelmointimoodiin)

Ja homma pelittää. ARM:in ohjelmointiongelma ratkaistu, seuraavaksi mietitään miten omia .bin tiedostoja pitäisi tuottaa.

[size=150]Ohjelmanvääntö[/size]

Laiskanmiehen ratkaisu toolchainiksi on ruuvipenkin artikkeleissa esitelty code sourcery, minkä saa syntisesti binääripakettina ilman ylimääräistä häslinkiä asennettua. (johon allekirjoittanutkin sortui)
http://www.gnuarm.com/
http://www.yagarto.de
ja muut gcc pohjaiset.
http://www.gentoo.org/proj/en/base/embedded/handbook

Paras tapa aloittaa on mallikoodi

http://code.google.com/p/cortex-m3-tutorials/downloads/detail?name=LPC1700%20Secondary%20USB%20bootloader%20for%20NGX%20BlueBoard.rar

Esimerkit käyttävät CMSIS:iä eli “ARM® Cortex™ Microcontroller Software Interface Standard”:ia.
Eli abstraktiolayeri, jotta sama koodi pyörisi kaikissa cortex-M sarjan kontrollereissa ja kääntäjissä.
Periaatteessa hyvä asia, tällöin kääntäjävalmistajat eivät tee omia matalan tason rutiineitaan ja rekistereiden uudelleennimeämisiä. Standardit auttavat lasta. Jos valmista koodikirjastoa tai modulia katselette, valitkaa aina CMSIS:iä käyttävä.

Esimerkiksi FreeRTOS käyttää CMSIS:iä, tai vaikkapa CMSIS:in USB ajurin päälle tehdyt USB laiteluokka-ajurit.
http://support.code-red-tech.com/CodeRedWiki/RDB1768cmsisExampleProjects
(viittaus tuohon, latauslinkki palauttaa meikäläiselle jostain syystä rikkinäisen zip-tiedoston)

Oleelliset tiedostot tässä ledivilkuttelussa ovat:

  • core_cm3.h ja core_cm3.c
  • system_LPC17xx.h ja system_LPC17xx.c
  • LPC17xx.h ja startup_LPC17xx.c
  • LPC17xx.ld
  • main.c
  • makefile

main.c
Itsestäänselvä

core_cm3.h ja core_cm3.c
debuggaus, ja matalantason funktioita

system_LPC17xx.h system_LPC17xx.c

system_LPC17xx.c modulissa on SystemInit. Siinä asetetaan muun muassa kiteestä CPU kelloksi muuttavan PLL kertoja&jakaja yhdistelmän asetukset. On makuasia, mutta minä en kyseiseen moduliin menisi koskemaan. Jos ja kun CPU:n ja oheislaitteiden kelloihin pitää mennä tekemään muutoksi, niin tehdään ne main() rutiinissa tai sen kutsumissa aliohjelmissa. Tällöin kellotaajuudet tulevat itse-dokumentoiduksi koodiksi omaan koodiin, eikä muutoksia tarvitse etsiä kissojen ja koirien kanssa jostain vakiokirjastosta.

system_LPC17xx.h headeri sisältää kasan strukteja, joilla kuvataan muistiosoitteisiin mäpätyt rekisterit
Ja struktipointterit osoittamaan vastaaviin muistipaikkoihin esim.
LPC_SC
LPC_GPIO0 yms…

startup_LPC17xx.c:stä taas löytyy “External interrupt vector handler”:it, joidenka nimiä kannattaa katsella kun tekee keskeytysrutiineja.

Vihje:

#pragma weak TIMER0_IRQHandler = Default_Handler

tarkoittaa tässätapauksessa sitä että Defaut_Handler:iä asetetaan jos TIMER0_IRQHandler funktio on määritelty

makefilu:

Ei kannata pelästyä, makefilut ovat varsin sekavaa luettavaa.
Rivit johin kannattaa ehkä kannattaa puuttua ovat ehkä jotkin flagit, optimointitaso -O2 ? yms…
Ja
CSRC+= main.c, mihin lisätään käännettävät c-tiedostot

Ja muistutetaan, että bootloaderille kopioidaan .bin tiedosto.
(ei elf, ei hex)

Pienissä projekteissa koodin voi nykykoneilla kääntää sekunneissa aina “puhtaalta pöydältä”, suuremmissa (512k rajana?) ajansäästö voi olla makefilen säätämisen arvoinen.

LPC17xx.ld

Linkkeriskripti, sekaisin ja hankalin tiedosto, pakko myöntää, kun se ei ole C:tä :-/
Linkkeriskriptin tarkoitus on kuvata mihinkohtaa muistiavaruutta minkäkinlaiset muistialueet sijoittuvat.

Aloittelijoiden kannalta huomionarvoisin rivi linkkeriskriptissä on

IROM (rx) : ORIGIN = 0x00002000, LENGTH = 512k

Käytettäessä usb-bootloaderia, rom-ohjelma alkaa osoitteesta 0x2000

Henk. koht en aiemmin joutunut muokkaamaan linkkeriskriptejä, joten tämän pätevämpiä neuvoja en osaa vielä antaa.

Näistä tiedostoista (ja datalehdestä) ja lunttaamaan kun pitää keksiä miten prossua ja sen toimilaitteita käskytetään.

linkkivinkit:
http://dev.frozeneskimo.com/notes/getting_started_with_cortex_m3_cmsis_and_gnu_tools
http://www.mcu-related.com/pdf/CMSIS_Doulos_Tutorial.pdf
http://msys-mv.blogspot.com/
http://gvworks.blogspot.com
http://cortex-m3-tutorials.googlecode.com
http://gandalf.arubi.uni-kl.de/avr_projects/arm_projects/index_cortex.html

[size=150]USB:n käyttäminen lpcusb, CMSIS:n USB?[/size]
Jotta Blueboard voisi näyttää joltain laitteelta (HID, sarjaportti, massamuisti yms…) se tarvitsee sitävarten ajurit. LPC:n rauta hoitaa USB:n matalan tason temput ja CMSIS näiden kutsumisen. Ajurillä tässätapauksessa tarkoitetaan tämän päälle tulevaa koodia.

USB-luokkia on useita.
http://www.usb.org/developers/devclass_docs#approved
Harrastelijan kannalta aiheellisemmat, käyttöjärjestelmien natiivisti tukevat luokat ovat

  • CDC eli Communications Device Class, “sarjaportilta näyttävät”
  • Massamuistilta näyttävä (kuten bootloader)
  • HID-laitteelta, kuten hiireltä, näppikseltä, joystikiltä/ratilta näyttävät

Erikoisempia laitteita varten tarvitaan erilliset ajurit PC-puolelle tai varsinainen ohjelma käyttämään vaikka libusb:tä http://www.libusb.org/

http://support.code-red-tech.com/CodeRedWiki/RDB1768ExampleProjects
Netti on täynnä epämääräisiä usb-kirjastoja, Mielestäni kannattaisi käyttää CMSIS:in matalan tason USB-funktioiden päälle rakennenettuja kirjastoja (zipin latauslinkin takana rikkinäinen zip-filu)
http://support.code-red-tech.com/CodeRedWiki/RDB1768cmsisExampleProjects

Bootloaderissa on toki “massamuistiajuri”, mutta se ei käytä CMSIS:iä Vielä kun löytäisi (tai jaksaisi tehdä) bootloaderin, joka käyttäisi CMSIS:iä ja bootloaderin massamuistiajuria (usb-hostille näyttää levyasemalta) voisi kutsua omasta koodista… niin wau… muistinsäästöä kun samaa koodia ei käännetä kahteen eri paikkaan.

[size=150]Käyttöjärjestelmä? No onhan meillä muistia…[/size]
http://www.freertos.org/
Kun kumminkin jossainvaiheessa rakenteluprojektia tulee tarve sille, että laite tekisi useampaa asiaa yhtäaikaa. Itsekirjoittaen “rinnakkain” ajettavaa koodia, tulee poikkeuksetta kumminkin paska scheduleri tai jokin scheduleria muistuttava epävarma häröviritelmä, mielummin sitä ottaa käyttöön valmiin ja testatun käyttöjärjestelmän.

FreeRTOS:n esimerkkikoodeissa vilahtelee CMSIS ja näemmä CDC-eli sarjaporttiajurikin kuuluu pakettiin mukaan

[size=150]Loppusanat[/size]
Asiasta voisi vielä kirjoittaa lisää CMSIS:n käytöstä, saisi luotua aika kattavan kuvan LPC1768:n sielunelämästä. Tai Freertos:n, käyttöönotosta, debuggauksesta, DSP kirjastosta, ethernet-liitännän rakentamisesta tai jonkin skriptikielen (lua,python, forth ja kumppanit…) käytöstä kontrollerilla.
http://en.wikipedia.org/wiki/Lua_(programming_language)
http://en.wikipedia.org/wiki/Forth_(programming_language)

PS.

Henk. koht olen sitämieltä että kuukauden parhaan artikkelin äänestys voisi olla arvontaa parempi vaihtoehto.