Tag Archives: ARM

Čipų trūkumas 2

Seniau lupinėdavau iš šroto (Husqvarnos žoliapjovės) STM32F103 čipus. Ne tiek jau daug rasdavau, nes dažniausiai čipai užlakuoti. Dabar vėl parvežė, matau keletą nelakuotu, čiumpu ir namie matau klastą:
STM32F103 clone
Tai kinietiškas analogas- ne toks “ekologiškas”, bet sako kad greitesnis. Čipo viduje yra du kristalai- atskirai ROMas ir atskirai MCU. Čipo paleidimo metu programa perrašoma į RAM ir veikia iš ten. Teoriškai gaunasi lėtesnis boot, bet greitesnis kontroleris.
Lygtai pilnai suderinamas su STM produktu, bet tikriausiai yra savų prigulnybių. Čipas užnumeruotas kaip 303, bet čia tikrai ne trečia serija.
Seniau visi čipai buvo STM. Matyt arba taupo pinigus arba tikrai nėra kur pirkti naujų STM (nereikia barstyti).
Continue reading →

ARM37: zuikis ir vėžliukas

Kas nesidomi mikroprocesorių programavimų, gali ir neskaityti. Bus nelabai įdomu… 🙂

Klasikinė bėda- yra du procesai, kurių veikimo greičiai labai skiriasi. Šiam variante: USB ir UART. Kaip suderinti jų bendrą veikimą? Štai imat kokį source code iš interneto platybėse publikuotos pamokėlės, viskas kaip ir veikia kol spaudžiojat duomenis iš klaviatūros, o jei pabandot “copy-paste” ir staiga tekstas pradeda nebepersiduoti, raidės prapuola ir procesoriukas pastringa. Kodėl? Todėl, kad reikia suderinti skirtingo greičio ir veikimo principo procesus:
Pirmas procesas, USB, tai paketinis duomenų perdavimas su galimybe pristabdyti duomenis ar net paprašyti juos pakartoti. Viskas vyksta gana greitai.
Antras procesas, UART, tai nuoseklus, lėtas duomenų perdavimas. Ir pats perdavimas pririštas prie laiko. Jei nenaudojam kontrolinių linijų, procesą negalime sustabdyti. Kai duomenų per daug, jie prarandami.

Taip atrodo iš žmogaus pusės, iš kontrolerio pusės tai jau keturi procesai: USB TX, USB RX, UART TX, UART RX.

Kad suvaldyti šį chaosą, reikia procesus paleisti nepriklausomai, per pertraukimus. Arba, kai siunčiam, tai galima ir pastabdyti pagrindinį ciklą (bent jau šiame eksperimente). Gaunais taip:

  1. UART RX, per pertraukima ir net DMA. Tačiau nežinom kiek baitų gausim, tai visas mūsų DMA/IRQ tvarko tik vieną baitą.
  2. UART TX, siuntimas blokuojant procesoriaus darbą. Mūsų programa nieko protingo nedaro, tai galima blokuoti.
  3. USB RX, tikriausiai per pertraukimą, naudojam HAL biblioteką.
  4. USB TX, blokuojamas ar tai IRQ, naudojam HAL biblioteką*.

Visi procesai per pertraukimą daro tik vieną darbą- jei gaunam duomenis, įrašom duomenis į buferį (jei yra vietos). Buferis vadinasi “circle” nes tai kaip ir cirkuliarinis buferis**, tik aš jo neperpildau, prarandu duomenis jei buffer overflow. O pats smagumas vyksta pagrindiniam, amžinam cikle:

 while(1)
	{
	HAL_IWDG_Refresh(&hiwdg); //watchdogas

	while(circle_available(&cc)>0) //ar yra duomenu gautu is UART?
		{
		i=circle_available(&cc);
		for(j=0;j<i;j++)
			{
			tmp[j]=circle_pull(&cc); //viska persikopijuojam ir issiunciam
			}
		CDC_Transmit_FS(tmp, i); //siuntimas per USB (blocking?. gal ne)
		}

	while(circle_available(&cu)>0) //ar yra duomenu gautu is USB?
		{
		i=circle_available(&cu);
		for(j=0;j<i;j++)
			{
			tmp[j]=circle_pull(&cu); //viska persikopijuojam ir issiunciam
			}
		send_uart((char *) tmp,i); //siunciam per UART (blocking)
		}
	}
}


Tikriausiai senas Wordpresas nenusiaubė programos teksto.

Iš principo programa veikia taip: yra ką perduoti? perduodam! ir vėl iš naujo.

Tačiau galima dar labiau viską užkomplikuoti- TX padaryti su atskirais buferiais ir siuntimo procesą irgi padaryti asinchroninį. Tada procesoriuje išsilaisvintu dar šiek tiek resursų kokiai nors pagrindinei programai.
Dar viena bėda- nenumatytas atvejis, kai trumpuose momentuose, kol ištraukiami duomenys į buferį, kas nors įrašytu naujus duomenis. Teoriškai circle buferis apsaugo nuo tokių nemalonumų… Praktiškai, buitiniams reikalams viskas veikia.

Šis straipsniukas skirtas man pačiam prisiminti, nes reikėjo ir neatsiminiau. Teko kiek parašinėti.

*) HAL USB biblioteka netikrina ar duomenys išėjo. Jei reikalingi TIKRAI gerai daryti, reikia tikrinti USB būklę. Tada jau geriau nagrinėtis ATARI disko emuliatoriaus kodą (rodos ten padariau viską)
**) circular buffer, cirkuliarinis buferis leidžia rašyti ir skaityti duomenis iš buferio. T.y duomenys kaip gyvatėlė Uroboras, nauji duomenys prisideda prie galvos, o seni nusiima prie uodegos. Viskas gerai, kol galva nepasiekia uodegos ir gyvatėlė neįsikanda. Tada prarandam duomenis.
P.S. source kodas neoptimizuotas dėl aiškesnio vaizdavimo.

ARM36: Burbuliniai LED

Antikvarinis LED indikatorius, tikriausiai iš kokio nors tarybinio kalkuliatoriaus. Žãvi savo netobulumu:

burbulinis LED
АЛС318

Simboliai mažyčiai (todėl ir plastikinės linzės), šviesumas mizernas (prie tausojančių srovių). Bet savotiškai žavingas.
Tokiam indikatoriui pajungti reikia gana daug laidų ir dinaminės indikacijos. Demonstracijai panaudojau breadboard ir “bluepill” plokštę (STM32F103C8t)- mikroschema mažoka, beveik visos kojos sunaudojamos indikatoriui. Prie anodų (pliusinių elektrodų) reikia prikabinti kokius nors rezistorius, kad apriboti srovę per LED, tik 3mA statiniam režime per vieną segmentą. Naudojant dinaminę indikaciją leistina srovė 40mA, bet jei indikacija sustos, tai atia LEDams.
Continue reading →

ARM35: LCD ir FSMC

Trumpa priešistorė: prisirinkom kažkokių PCB su STM32F103* mikroschemos ir nežinomu LCD. LCD buvo dviejų tipų, o pačios PCB irgi keletos variantų. Kai kurios su kitu STM32 BGA čipu ir ROM/RAM mikroschemom. Dar kitos PCB beveik tuščios ar pažeistos. Užtat visos turi mėlyną dantį ir visokias smulkmes.
Visokius kištukus gana lengvai išaiškinom (gerai, kad ne visos PCB padengtos laku), kai kurie primityvai kaip LCD pasvietimas (ar dar kieno) eina per tranzistorius, tai irgi lengvai atsibūrė. Bet liko LCD. LCD tikrai dviejų tipų- mažesnis, išjungtas juodas ir didesnis, baltas. Abu ekranai grafiniai, nes yra originali firmwarė, kur parašo kad “atnaujink softą”. Pirminis softas lygtai ir universalus abiem plokštėm ir jame aptikom, kad plokštės iš Husqvarnos automatinių žoliapjovių.
Deja informacijos apie LCD ekranus ar kontrolerius nebuvo visiškai. Todėl ėmiau iš eilės visokius LCD ekranus su panašiu kiekiu pinų ir bandžiau… Pagal įtampas, pagal originalios firmwarės siunčiamus signalus atrinkau, kur maždaug duomenys, kur WR ar panašūs signalai.
Mažesnis LCD labai panašu į ST7565 ir ten viskas maždaug buvo aišku. Didelis LCD visiškai neaiškus.
Dar pasirodė labai keista, kodėl pasirinktas toks keistas pajungimas prie MCU:

PD0=D2
PD1=D3
PD4=RD
PD5=WR
PD7=CS1
PD14=D0
PD15=D1
PE3=A0
PE7=D4
PE8=D5
PE9=D6
PE10=D7

Tačiau pernelyg nesivarginau. Nes svarbiau buvo LCD. Su didesniu LCD buvo bėdos- labai panašus LCD yra UltraChip serijos kontroleriai kaip UC1610 ar UC1611. Tačiau komandos nevisos veikia. Bėda tame, kad daug komandų bendros visos serijos čipams (ar net kito gamintojo čipams), kitos komandos ignoruojamos ar panašiai. Ir dar nustebino pačio LCD ekrano pilkumo atspalvių bitų seka. Net vienu metu kilo mintis, kad ten spalvoto ekrano kontroleris pritvirtintas prie juodai-balto LCD ekrano. Dar kilo mintis, kad neteisingai nurašiau pinoutą (tikrai ne, žr. toliau).
Bežaidžiant su bitais, buvo kaip ir parašytas šioks toks softas ekrano valdymui. Tačiau norint paišyti vaizdą ant ekrano pagal pikselius, reikia nuskaityti informaciją iš ekrano. Tai galima padaryti ir “bit bang” režimu ir su STM32F103 tai vyksta gana greitai. Bet vistiek viskas labai kvaila. Buvo pasiskaitytos instrukcijos, paguglinta ir pasinagrinėtas STMkubikas ir pasirodo man nežinomas FSMC režimas, kur kaikurios MCU kojos pavirsta DATA, ADR ir kontroliniais (WE, CS ir pan) signalais. Tada skaitymas iš LCD ar rašymas į LCD (ar į kokį SRAM) pavirsta paprasta operacija- “rašymas ir skaitymas iš RAM”:

*(__IO unsigned char *)(LCD_DAT_ADDR)=d;
d=*(__IO unsigned char *)(LCD_DAT_ADDR);

Ir mūsų LCD būtent ir pajungtas kaip FSMC įrenginys (dėl to ir toks keistas LCD pinouto pajungimas).
Tačiau net dvi dienas man niekas neveikė. Nes dokumentacijoje gana miglotai parašyta ir iš pirmo žvilgsnio viskas labai nelogiška. Bėda susijusi su duomenų šynos pločių ir adresu. LCD ekrano A0 pinas, kuris atskiria duomenis nuo komandų prikabintas prie A19 pino. Šio pino lygį turi reguliuoti adresu bitai:

//Musu LCD A0 pajungtas prie A19 pino.
#define LCD_CMD_ADDR 0x60000000
#define LCD_DAT_ADDR 0x60080000

Tačiau niekas neveikė. Pasirodo, mano pavyzdiniam softe buvo ne “unsigned char”, o “unsigned int” (aka uint16). Kituose pavyzdžiuose net 32 bitų kintamasis. Ir dar baisiau- net keletas straipsnių rašė, kad jei naudojam 16 bitų nuskaitymą, adresas pasislenka per vieną bitą, jei 32 bitus, per du bitus. Tačiau ir tai nepadėjo, nes mano pagrindinė klaida buvo tokia, kad nuskaičius 16 bitų iš 8 pin porto, maniau, kad mažesnieji bitai turės reikalingą informaciją. Pasirodo, kad ne. Kiek suprantu, STM čipas hardwariniam lygyje prisiderina prie “bus width” ir dar net kelis nuskaitymus ar rašymus. O jei sukonfiguruota nelogiškai, viskas ir nelogiškai veikia.
Todėl, jei reikia nuskaityti BAITĄ iš 8 laidų šynos, tai reikia C kalboje ir skaityti BAITĄ. Dar nesu tikras ar skaitant WORD iš BYTE nedaromas dvigubas nuskaitymas. Šitą reikia dar patikrinti, nes LCD ekranos softas dar kiek optimizuotusi. O dėl adreso, čia man irgi kiek neaišku, bet baitų, wordų ir longwordų adresai yra atitinkamai pasislinkę, jei norime juos nuskaityti. Pas ARM gal nėra tos bėdos kur yra pas MC68000, kur negalima skaityti pabaičiui ar panašiai iš nelyginių adresų…
Labai daug ir neaiškiai parašiau, bet čia mano “brain dump” ir ši informacija skirta man prisiminti, kaip pajungti FSMC režimą pas STM32F103. Ką dar gero duoda tas FSMC? Ogi DMA.

Kad straipsnis gautusi indomesnis, va fotkė:
LCD

Tai tas didysis ekranas, deja neįjungtas pašvietimas. Naudojamas keistokas “klasikinis” TI99 šriftas kuris gal netinkamas šiam ekranui.

Ir net trys variantai source code su viskuo: mažas ekranas bitbang, didelis ekranas bitbang ir didelis ekranas FSMC:
Husqvarna LCD ir STM32F103 FSMC.

Visas source tikrai neaptvarkyti, yra labai daug eksperimentavimo ir “reverse engineering” likučių.

*) ne visos STM32F103 palaiko FSMC. Čia STM32F103VGT6.

Ta pati plokštė palaiko kelis tipus LCD ekranų su 24 PIN jungtimi (vienas LCD buvo su PE12864URT): PINOUTAS pdf.

Purple pill arba biruolių plokštė

Pamenat, rašiau apie biruolius. Apie kalną STM32F103VBT čipų su kiek palenktom kojom? Tai va, pasidariau eksperimentinę plokštę. Išvedžiau VISAS kojas į 0.1″ kištukus. Dar biški RS485/CAN prielipų pripaišiau tuščioje vietoje.

Purple pill STM32F103VBT
Tikrai sunku prilituoti mikroshemą, kai kojos biški palankstytos. Bet va iš antro karto lygtai ir gavosi. Diagnostinis softas rodo, kad per visas kojytes eina signalai ir trumpų jungimų nėra. Aišku minimalus kiekis detalių ir maitinimas iš “serial debug” lizdo.
Beja, jei netyčia užblokuosit tą “serial wire”, tai nedidelė bėda, užtrumpinat “Reset”, pradeda programuoti ir atjungiat “Reset”.

Užrašai “AL”, “AH”, “EL” ir panašiai, tai pinų grupės. Pvz. AL – PA(0-7), “low” dalis. AH tai PA(8-15) ir t.t.

Visi failai:
Diagnostine firmwarė – source code, STM32Cube failas, kompiliuotas HEX.
Gerberiai – Standartiniai gerberiai, jei staiga užeis noras užsisakyti PCB.
Schema – Šios plokštės schema. Gana negražiai nupaišyta (pdf).
PCB iliustracijos – Šios plokštės PCB vaizdai (pdf).
BOM.

Dėmesio, PCB, bottom pusėje jumperis SJ1 yra jau užtrumpintas į GND. T.y. BOOT0=GND. Jei reikia kitos reikšmės, reikia nupjauti pačiam jumperyje esantį takelį ir prilituoti atitinkamą rezistorių.

Čipų sakot trūkumas?

Vienas geras žmogus pranešė, kad atvežė biruolių. Bet kažkaip nebuvo laiko- darbai prispaudė. Po kelių dienų nuėjau ir pamačiau likučius….

stm32f103
Net širdelę užspaudė…

stm32f103
STM32F103VBT6: Medium-density performance line ARM ® -based 32-bit MCU with 128 KB Flash, USB, CAN, 7 timers, 2 ADCs, 9 com. interfaces. 20KB RAM.

Čia biruoliai, matosi, kad kojelės biški kreivos. Dabar reikia projektuoti universalią PCB. Jei kam reikia, galiu semtelėti. Tikiuosi geri ir nepadirbti.

ARM21: STM32-USB-CDC ir hardware handshake

Bežaidžiant su savadarbiu Atari kilo mintis iki galo iššifruoti kaip visdėlto persiduoda senoviniai RS232 būklės signalai į host kompiuterį. O pasirodo, čia didelė bėda. Daugelis interneto puslapių dažniausiai sako, kad tie visi RI, CTS, DSR, CD, DTR ir RTS jums nebus reikalingi “ir esamo straipsnio lygyje nebus padaryti”. Šūdeliai tie autoriai. Todėl, kiek pavargau ir po gabaliuką surinkau informaciją apie tai. Pakeliui STM32CubeMX gamintojai įpaišė eilinį sisteminį atnaujinimą ir su 1.8.0 versija viskas veikia, o su 1.8.3 kažkai biški neveikia ir biški veikia. Todėl pavyzdukinis softas kompiliuojasi su 1.8.0 firmwarės biblioteka.
Visi linijos kontrolės signalai iš įrenginio (device) į host eina per atskirą IN✻ endpointą (interrupt). Jis pagal nutylėjimą sukuriamas CDC pavyzdyje, bet nenaudojamas. Signalai iš host į įrenginį eina per standartinį komandinį (0 – nulinį) endpointą. Standartiniam kubo softe ten biški net padaryta.
Vienintelis signalas CTS niekaip negaminamas per USB, jo būklę nusprendžia host draiveris pagal esamą situaciją. Beja, net keli interneto šaltiniai rašo, kad windows standartiniai draiveriai to nemoka daryti ir iš viso ten bėda. Todėl visokie “hardwariniai” USB-COM adapteriai turi savo draiverius.

Biški prirašiau miglos? 🙂 Gerai- paprasčiau. RS232 būklė perduodama 7 bitais, per CDC status, per dedikuotą IN interrupt endpointą:

// 7 reserved 0.
// 6 bOverRun - received data has been discarded due to overrun in the device.
// 5 bParity - parity klaida, parity error
// 4 bFraming - framing error
// 3 BRingSignal =RI - ring signalas, vienas iš nepriklausomu RS232 signalų
// 2 bBreak - tai BREAK komandos statusas. Kai siunčiama BREAK komanda, RS232 siuntimas stabdomas, o duomenų linija užkeliama high.
// 1 bTxCarrier =DSR, data sender ready ar panašiai. Šitie du signalai užsikeldavo, kai modemas susijungdavo su kitu modemu.
// 0 bRxCarrier =DCD

Tokia informacija eina iš įrenginio. Tuo tarpu host gali siuntinėti daugiau komandų (nes CDC standartas tai ne tik COM portas). RS232 aišku naudoja greičio, stop bitų, parity valdymo signalus. Tai puikiausiai padaryta demonstraciniam kubo softe (komandos CDC_SET_LINE_CODING ir CDC_GET_LINE_CODING). Komanda sukurianti BREAK irgi lengvai randama (CDC_SEND_BREAK).
Lieka valdymo komanda CDC_SET_CONTROL_LINE_STATE, kurios paleisti aš ilgai negalėjau. Ten iš esmės tik du bitai iš 16:

//bitai: 15:2 - 0.
//bitas 1- carrier control. 0- deactivate carrier, 1- activate.
//bitas 0- DTR bukle, 0-not present, 1- present.

Tik kur tie bitai paslėpti? Pasirodo, kad USB CDC standarto kurėjai nutarė juos paslėpti kiek kitoje vietoje- wValue, o ne duomenų bloke. Kodėl? Tikriausiai, kad užsiknistum. Kubo kūrėjai irgi pasistengė viską paslėpti toje procedūroje kur viskas labai elegantiškai surašyta. Tačiau jei pakrutintume vienos struktūros prikabinta substruktūrą, tai joje ir rastume tą reikšmę. Aš tikrai nesuprantu struktūrų ir kaip iš jų traukiami duomenys, tai padariau taip, kaip nei vienam source kode nemačiau:

wValue=hUsbDeviceFS.request.wValue;

Ir čia randam tuos du bitus, kurie konkrečiam projekte nereikalingi.

Einam atgal prie būklės siuntimo per INT IN endpoitą. Kubo softo kūrėjai nenumatė duomenų perdavimą vartotojui per endpointus. Nu gal numatė, bet per žemesnio lygio procedūrą:
USBD_LL_Transmit(&hUsbDeviceFS, endpointo numeris, duomenų buferis, ilgis duomenų);
Alia, ką ten reikia siuntinėti nelabai ir rašo. Vargom vargom ir radom paketo aprašą:

buf[0]=0b10100001; //request type (0xA1). Nu tokis skaičius rodo, kad męs norim kažką pranešti CDC.
buf[1]=0x20; //notification SERIAL STATE, o čia kad pranešam COM porto būseną.
buf[2]=0; //wValue
buf[3]=0; //wValue
buf[4]=0; //wIndex - interface number, 16 bit, LSB
buf[5]=0; //wIndex - nes gali būti keli COM portai ant to pačio USB. MSB.
buf[6]=2; // Čia pranešimo ilgis. Ne paketo ilgis, o "svarbių" duomenų. LSB.
buf[7]=0; // Čia irgi ilgis. Viso du baitai. MSB.
buf[8]=status; // Šitie svarbūs. LSB pirmiau
buf[9]=0; // o šitie visada nuliai.

Šitą masyvą išsiunčiam:

USBD_LL_Transmit(&hUsbDeviceFS, 0x82, buf,10);

..ir? Nifiga neveikia. Tiksliau veikia dalinai. Kodėl? Ogi todėl, kad kubo softo kūrėjai nusprendė, kad “control endpointui” užtenka aštuonių (8) baitų. O šio paketo ilgis- 10. USB Shark ir parodo, kad eina 8 baitai mūsų, ir du randominiai. Todėl einam į “usbd_cdc.h” failą ir taisom:

#define CDC_CMD_PACKET_SIZE 10U /* Control Endpoint Packet size */

Va dabar, jau kažkas pradeda veikti. Paleidžiam softą skirta Atari diskų emuliacijai ir … neveikia. Be “flow control” veikia, su bet kokiu “flow control” trukinėja ryšis. Kol kas nežinau kur bėda. Vienas svarbus momentas, kad USB labai jau “asinchroniškai” nusiskaito būklę. Kartais labai vėluoja. Nes principas toks- “ei! Kompiuteriau, pasikeitė laidų būklė. O kompas po kažkiek laiko- gerai, gerai, jau supratau”. Ar tai MS draiverio bėda, ar mano, aš dar nežinau.

Nu ir pats pilnas softas:
ATARI 1088XEL SMD on board USB firmware for STM32F103, full source code and compiled hex and binary.

Ir kam buvo neįdomu ar nesupratot, va viena iliustracija:
Atari disk emulator with STM32F103
Tikrai veikia.

✻) USB endpointų kryptis visada rašoma iš kompiuterio, hosto pusės. Visi signalai iš kompo yra “OUT”, visi signalai į kompą yra “IN”. Ir nesvarbu kas iššaukia perdavimą. Taip padaryta todėl, kad USB yra vienkryptis (pagal hierarchiją) protokolas. Tuo tarpu senovinis COM yra lygiavertis. Kartais susibalamutinasi protas, kai duomenys iš MCU eina į IN endpointą, o gaunami per OUT. Pas COM dažnai susipainioja laidai, nes TX sujungtas su RX. Pas kokį modemą RX pavadintas TX ir laide sujungta RX-RX. Taip darosi painiava.

ARM:0020 smurtinis hardcorinis žaidimas Rogue

Jau rašiau, kad internetuose radau Rogue žaidimo source code kuris netikėtai susikompiliavo ant mano kompiuterio. Deja ant kitų kompiuterių jis neveikė. Bandžiau tokį iškrypimą, kaip perkelti source code į Microsoft Visual Studio Express, bet ten tikriausiai iš principo negali veikti jokie senoviški C kalbos failai- microsofto programa pranešinėjo keistas klaidas. Numojau į tai ranka ir pagalvojau- jei kompiliuojasi su gcc, tai kodėl jis nesikompiliuoti ir su ARM gcc (AVR tai gal per silpnas). Pasirodo, puikiausiai kompiliuojasi. Teko tik išpjauti dali paprogramiu susijusiu su failais ir prikabinti savo. Taip gavosi toks monstras:

Rogue running on STM32F103 MCU USB

Tai USB-COM-Rogue su STM32F103. Tereikia tik USB terminalo. Po tiekos programinimo, manau UART versija dar greičiau gautusi. Dar beliko viską sukultūrinti, nes dar liko visokių bugų- pvz. po žaidėjo mirties, jis kaip zombis toliau gali vaikščioti po labirintą. Nesvarbu, kad jau parodė mirties ekraną- turėjo pasileisti žaidimas iš naujo, bet kažkaip neišsivalė buferiai ir viskas liko iš seno žaidimo. Visiškai nesupratau dėl TERMCAP failo- vieną įdėjau ir veikia, įdėjau antrą- neveikia. Vėl įdėjau pirmą- neveikia. Veikia tik iš vakar dienos backupo. Originalus source kodas gana užsuktas. Užtat ir ant ARM gcc kompiliuojasi be jokių “warningų”.

Žaidimo source code ir kompiliuotas HEX. Dėmesio! Binaras gaunasi didelis (92kB ir neaišku kiek RAM jam reikia) ir tikrai neveiks ant BluePill. Jis veikia ant mano “white pill“, su pilnaverčiu STM32F106RET6.

ARM:0019 Printeris iš kalkuliatoriaus 2

Buvo straipsniukas, kaip aš sugadinau Citizen CX-123II kalkuliatorių. O dabar šio straipsniuko pratesimas. Toks ilgas tarpas gavosi todėl, kad aš tik mokinuosi. O ir kažkaip įtariu, kad į Bluepill plokšteles kinai sudėjo kažką mažesnio. Nes kartais labai magiškai projektas pradėdavo daryti nesąmones. Todėl labai ilgam sustojau, nes reikėjo savo PCB pasidaryti ir sunaudoti turimas mikroschemas. Dabar mano testavimui teko didesnė mikroschema STM32F103RET6, kuri rodos turi 512K ROMo ir 64K RAM. Tačiau spėju, kad galutinė programa turi tilpti ir į bluepill, jei tik Kinas labai nepataupė.

ARM STM32F103 printer device - calculator impact printer

Šis “printeris” susideda iš kelių modulių: USB modulio, tarpininko tarp USB printerio ir mano citizeno programos. Šio eksperimento pamoka- USB pertraukimas turi būti mažesnio prioriteto nei machaninio printerio. Taip, mechaninis printeris veikia grynai per pertraukimus ir visi “taimingai” svarbūs.
Deja, šis projektas mano nusibodo- aš pilnai nesupratau, kaip veikia spalvos perjungimas ir pirmo (paskutinio) simbolio spausdinimas. Dabar printeris daro tai, kad jam nurodyta- spausdina skaičiukus iš bet kokio teksto paleisto į printerį. Jis kiek stengiasi filtruoti, tačiau vistiek dažnai spausdina nesąmones. Ir kartais užsispiria ir prispausdina ne to, ką norėjau.

Printeriui užtenka energijos iš USB lizdo. Kad paleisti reikia tik dviejų n-kanalo laukinių tranzų (su 3V tolerantišku valdymu, iš kompiuterio motininės plokštės, gal dviejų diodų. Ant PWM motoro valdymo reikia nedidelio elektrolitinio kondensatoriaus.

Ir aišku visas source kodas ir kompiliuotas binaras. Dėmesio! STM Cube projektas neatitinka pačio kodo, pergeneravus, gali nebesusikompliuoti. Dabar binaras yra skirtas STM32F103RET6 mikroschemai.

STM32F103RET6 USB printer device source code and binary – printing on Citizen CX-123II calculator printer.

Buvo smagu.

ARM:0018 STM32CubeMX hack – printerio klasė

Tai projektas kuris pilnai užstrigo dėl mano neprofesionalumo ir dėl dokumentacijos trūkumo. Užduotis- konvertuoti vieną iš STM32CubeMX projektų į printerio klasę (Printer Class). Tam reikalui panaudojau CDC klasę ir perdariau pagal savo seną AVR projektą į printerio klasę. Ir jis, rupužė, neveikia taip kaip reikia.

Ką daro publikuotas projektas:

  • Prisijungia kaip kompo kaip USB įrenginys, nuskaito standartinius deskriptorius ir kompiuteris mato kaip printerio klasę.
  • Printeris duoda 1284 stringą į hostą, tačiau ar teisingai hostas tai interpretuoja nežinau.
  • Printeris spausdina. Tačiau veikia tik uni ir bi- directional režime. Kažkodėl 1284.4 režime mano windows pastringa.
  • Printeris nesigavo pilnai “plug ir peilis”. Jį reikia dagrūsti rankiniam režime. Mano AVR variantas buvo pilnas “plug and play”.
  • Kaip ir AVR versijoje nesugebu perduoti STATUS (baigėsi popierius, printeris “on-line/selected”) į hostą. Lygtai viską parašiau, bet windows draiveris paprasčiausiai neklausia ir ignoruoja mano bandymus.
  • “MS descriptor” teoriškai padarytas (0xEE), bet kažkodėl neveikia. Gal Windows neklausia, arba klausia taip, kad aš nepastebiu.

Kad atkartoti projektą, reikia pradėti STM32CubeMX su USB ir CDC klase. Poto, viską CDC pašalinti ir sudėti mano source. Kas svarbu- “midlevares”- klasė “PRINTER”. Pagrindiniam “src”: usbd_princer_if.c – printerio ryšis su USB, usbd_conf ir usb_desc – ne pilnai išvalyti nuo CDC klasės ir kiek pribūrta dėl MS deskriptoriaus.
Tačiau jei laikyti kodą teisingu, tai useriui reikalingas tik vienas failas- printer_hardware.c. Tai pats fizinis spausdinimas. Šiuo metu nuvestas į USARTą. Prisijungus išorinį UART (COM adapterį) galima lengvai debuginti ir monitorinti kas vyksta.

Dėmesio! Nepergeneruokit kubiko kodo, nes nužudys kai kuriuos failus.

Download STM32CubeMX USB PRINTER CLASS demo code (source and compiled hex for bluepill STM32F103C8.

Kodėl tai sunkiai einasi ir kodėl dedu nepilną kodą? Todėl, kad nėra free programų, kurie lengvai analizuotu kas vyksta ant USB. Todėl, kad dokumentacijos labai mažai- daug kas rašo kodą ir daro aparačiukus kurie naudoją printerius, tačiau visiškai niekas nedaro pačių printerių. Todėl, kad USB.ORG tik apibrėžė klasę, o realiam pasaulyje tiek microsoftas, tie obuolys, tie printerių gamintojai prisigalvojo savo “piblūdų ir navarotų” kuriuos mažai kur viešai publikavo. Ir dar aišku, visiškai nėra laiko tokiems žaidimams, o ir šiaip, nėra tiek žinių, kad greitai perprasti svetimą kodą. Ypač kai kodą rašo narkomanai- vien ko vertas STM inžinierių “universalus” metodas bendrauti tarp usb device, usb interface ir userio kodo per pointerius ir pointerių struktūras. Ar pointerių struktūrų pointerius struktūruose per pointerius ar panašiai 🙂 (gi narkomanai rašė).

O postinu, kad kiti gal pasinaudos, o ir pats turėsiu rezervinę kopiją.