Fórum témák

» Több friss téma
Fórum » ARM - Miértek hogyanok
 
Témaindító: gtk, idő: Jún 26, 2007
Lapozás: OK   83 / 83
(#) csabeszq válasza csatti2 hozzászólására (») Jan 7, 2017 /
 
Lehet, hogy első menetben kihagynám az oszcilláció fojtását.
(#) csatti2 válasza csabeszq hozzászólására (») Jan 7, 2017 /
 
Hagyd ki nyugodtan. Csak ilyen példám volt hirtelen.
(#) Kovidivi válasza rascal hozzászólására (») Jan 7, 2017 /
 
Én úgy szoktam, hogy ha elhanyagolható a terhelés, mint pl. az ADC referenciája, akkor minimum 1mA folyik a TL431-en, de inkább több.
(#) csabeszq hozzászólása Jan 8, 2017 /
 
Nagyon elszállt a kódméret STM32 alatt C++-ban.

Az egyik absztrakt osztály üres virtuális destruktora szimplán 2kb-tal nyomta meg a kódméretet.
A vtable amit a gcc gyárt 20%-a komplett kódnak.

Ti szoktatok virtuális osztályokat csinálni, vagy mi kell ahhoz, hogy ne triplázzuk a kódméretet?
Nálam elég dinamikusan nő a kódméret egy új osztály hozzáadásával...
(#) Balázs válasza csabeszq hozzászólására (») Jan 8, 2017 /
 
Ami a kódméretet (és a futásidőt) drasztikusan meg tudja növelni C++-ban, az tipikusan a kivételkezelés. Azt érdemes letiltani. Illetve most ugye megvan a lehetőséged egy tisztán virtuális függvény meghívására, ezért valószínűleg hozzáadja a pure virtual function call kezelését. Bővebben lásd itt, "Provide a __cxa_pure_virtual() implementation" rész.
(#) csatti2 válasza csabeszq hozzászólására (») Jan 8, 2017 /
 
Nem biztos, hogy jó döntés olyan pici mikrokontrollerbe C++-ban programozni. Sima C-vel jobban járnál. A C++ képességei úgysem jönnek ki ilyen méretben vagy éppen kockázatos használni, hisz simán megehetik a kicsi rendelkezésre álló memóriát.
(#) csabeszq válasza csatti2 hozzászólására (») Jan 9, 2017 /
 
Igen, a C++ nem java, pláne nem mikrokontroller alatt. Bár virtuális osztályok készíthetőek, de ha 1-2 metódus különbözik, akkor nem új osztályt csinálunk, hanem callback-ezünk, esetleg template-ezünk. Javaban ugye nincs callback, ezért rááll a kezem a virtuális osztályokra. A probléma, hogy mikrovezérlő alatt ettől elszabadul a pokol kódméretben.

Kevés virtuális osztály kevés probléma.
A hozzászólás módosítva: Jan 9, 2017
(#) silent15 hozzászólása Jan 9, 2017 /
 
Sziasztok!

Egy olyan kérdéssel fordulnék hozzátok, hogy szeretnék előállítani egy xMhz-es megszakítást, amihez egy adott kódot rendelnék. STM32-ről lenne szó Atollic környezetben. PIC-nél tudtam olyat hogy bekonfiguráltam a timert hogy miként számoljon, majd csináltam egy megszakítást, ami a timer túlcsordulásánál triggerelt, és akkor elvégezhettem azt a pár parancsot, amit szerettem volna. Ugyanezt szeretném megcsinálni, csak STM32-vel. A neten talált tutorialok nem teljesen tiszták nekem, illetve az egyik teljes ( ez ) nem működik, de nem értem miért. Valaki el tudná nekem magyarázni, hogy hogyan lehet ezt itt megoldani?

Köszönöm!
(#) cpt.zoltan.simon válasza silent15 hozzászólására (») Jan 9, 2017 /
 
Ha arra van szükséged hogy X időnként egy megszakítás az elég egyszerű.
Upcounter mod nulláról n-ig. AHB órajelből annak tovább osztásából (léptető jel) ki lehet számolni mit szeretnél.
Annyit fűznék hozzá, hogy én a PLL minden egyes pontját a Clocks.(ez, az, amaz) struktúrában tárolom, mikor melyik perifériának ami éppen kell, onnan számolja ki saját magát. Tehát a Clocks.APB1TimersFreq az vagy 60, vagy 30MHz (most nem emlékszem melyik mennyi lehet de ezek max értékek az adott domain-hez) 120Mhz core órajel mellett.

  1. //Timer3 Setup
  2. void InitTimer3 (void){
  3. RCC->APB1ENR |= (1<<1)//Enable Timer3
  4. //BaudRate:
  5. TIM3->PSC = 100 * Clocks.APB1TimersFreq;        //1Mhz time base (100us)
  6. TIM3->CR1 = CKD(0) | APRE(1) | CMS(0) | DIR(0) | OPM(0) | URS(1) | UDIS(0) | CEN(0);
  7. TIM3->ARR = 2500;       //100us * 2500 = 0.25s
  8. TIM3->DIER |= 0x01; //Update interrupt enabled
  9. NVIC->ISER[0] |= 0x20000000;    //Timer3 Global Interrupt Enabled
  10. }
A hozzászólás módosítva: Jan 9, 2017
(#) silent15 válasza cpt.zoltan.simon hozzászólására (») Jan 9, 2017 /
 
Köszönöm! Most sajnos nem vagyok eszköz közelében, de holnap kipróbálom
(#) cpt.zoltan.simon válasza silent15 hozzászólására (») Jan 9, 2017 /
 
Az interrupt handler:

  1. //Timer3 Interrupt handler starts conversion in every 250ms on K-Type Thermocoupler
  2. void TIM3_IRQHandler       (void)     __irq{
  3. NVIC->ICER[0] |= 0x20000000; //Disable TIM3 interrupt
  4. //IDE ÍROD AMIT PERIÓDIKUSAN SZERETNÉL
  5.  
  6. //Erase all bits needed for clean exit
  7. TIM3->SR--;     //Clear TIM3 Status register: Update Interrupt Flag
  8. NVIC->ICPR[0] |= 0x20000000; //Clear pending TIM2 interrupt
  9. NVIC->ISER[0] |= 0x20000000; //Enable TIM3 interrupt
  10.         }


Ez pedig a TIMER-hez a header file

  1. //TIM2-CR1
  2. #define  CKD(x)   (x << 8)
  3. #define  APRE(x)  (x << 7)
  4. #define  CMS(x)   (x << 5)
  5. #define  DIR(x)   (x << 4)
  6. #define  OPM(x)   (x << 3)
  7. #define  URS(x)   (x << 2)
  8. #define  UDIS(x)  (x << 1)
  9. #define  CEN(x)   (x << 0)
  10.  
  11. //TIM2->CR2
  12. #define  TI1S(x)  (x << 7)
  13. #define  MMS(x)   (x << 4)
  14. #define  CCDS(x)  (x << 3)
  15.  
  16. //TIM2->CCMR1 (input mode)
  17. #define  IC2F(x)    (x << 12)  
  18. #define  IC2PSC(x)        (x << 10)
  19. #define  CC2S(x)    (x << 8)
  20. #define  IC1F(x)    (x << 4)
  21. #define  IC1PSC(x)        (x << 2)
  22. #define  CC1S(x)    (x << 0)
  23.  
  24. //TIM2->CCER
  25. #define  CC1E(x)    (x << 0)
  26. #define  CC1P(x)    (x << 1)
  27.  
  28. //TIM2->DIER
  29. #define  TIE(x)      (x << 6)
  30. #define  CC4IE(x) (x << 4)
  31. #define  CC3IE(x) (x << 3)
  32. #define  CC2IE(x) (x << 2)
  33. #define  CC1IE(x) (x << 1)
  34. #define  UIE(x)      (x << 0)
(#) cpt.zoltan.simon hozzászólása Jan 10, 2017 /
 
Helló!

Van egy 429I Discovery board-om. A rajta lévő F103 két átforrasztható jumperrel tud csatlakozni a 429 PA9,10 lábaira USART céljából. Tehát a 429-re megírt USART az STLINK-en keresztül ki tudna dumálni a PC-nek putty-nak, hyperterm-nek.
Nagyon kevés infó van erről. És ez nem ugyan az mint az SWO ami a PB3 lábra menne. Az egész abból indult ki, hogy szeretném használni a Keil printf(Debug) screen-jét egy kis kényelem gyanánt.
Szóval van itt olyan aki már STLINK-V2-t rá tudta bírni hogy Debug mellett ugyan azon a szingli USB kábelen virtuális soros port legyen?
(#) icserny válasza cpt.zoltan.simon hozzászólására (») Jan 10, 2017 /
 
Az UART csatlakozás ott van a többi Discovery kártyán is, de nem jó semmire, mert az STLINK V2 firmware nem biztosít virtuális soros portot hozzá.

Amit te keresel, az valószínűleg a semihosting, amihez nem kell külön drót, hanem a debuggeren keresztül (SWDIO) kommunikál.
(#) cpt.zoltan.simon válasza icserny hozzászólására (») Jan 10, 2017 /
 
Végülis mindegy melyikkel foglalkozom. SWDIO talán annyiból jobb lenne, ahogy láttam core szinten van implementálva, és a Cortex mag része. Ilyen formán a core-cm4.h file-ban találtam is hozzá rutinokat. Jó kérdés, hogy hogy fog működni.
Akárhogy is, azt szeretném elérni, és ebben kérném a segítséget hogy:
Egy db USB kábel az ST-Link-en
PC képernyőre írja ki amit szeretnék debug jelleggel. pl a Printf ablakba.
Jah és a watch windows nem ér!
(#) icserny válasza cpt.zoltan.simon hozzászólására (») Jan 10, 2017 /
 
Erre gondoltál? STM32F4 Discovery and printf() redirection to debug viewer in Keil MDK-ARM Bővebben: Link
(#) cpt.zoltan.simon válasza icserny hozzászólására (») Jan 10, 2017 /
 
Pontosan erre. És végig is csináltam, csak éppen nem jelenik meg semmi a Printf ablakban.
(#) csabeszq válasza cpt.zoltan.simon hozzászólására (») Jan 10, 2017 /
 
Nem értek a dologhoz de itt egy cikk, hogyan lehet az ST-LINK V2-t SWO pinnel kiegészíteni:

https://lujji.github.io/blog/stlink-clone-trace/

Én rendeltem olyan st-link v2-t, amin van SWO:

https://www.aliexpress.com/item/Best-Quality-ST-Link-stlink-V2-for-...6.html
(#) csabeszq hozzászólása Jan 10, 2017 /
 
DMA-ról kérdeznék, ADC-t mintavételezek:
- circular módban folyamatosan jár
- normal módban feltölti a puffert és leáll

A kérdés normal módra vonatkozik. 32 mintavételes puffereket szeretnék, először az elsőt töltöm fel, utána a következőt,... viszont néha leállítom, amikor befejeztem a mintavételezést. Olyankor nem töltök fel több puffert.

Normal módot csak úgy tudtam újraindítani, hogy DMA disable -> DMA enable. Bármilyen flag-et töröltem (GL1, TC1, HT1, TE1), semmi sem történt, nem indult újra. Ez a helyes újraindítás, vagy van egyéb szebb módja is, hogy a lejárt DMA-t újraindítsam?
A hozzászólás módosítva: Jan 10, 2017
(#) csatti2 válasza csabeszq hozzászólására (») Jan 10, 2017 /
 
Jól csináltad. Idézet a kézikönyvből:
Idézet:
„If the channel is configured in noncircular mode, no DMA request is served after the last
transfer (that is once the number of data items to be transferred has reached zero). In order
to reload a new number of data items to be transferred into the DMA_CNDTRx register, the
DMA channel must be disabled.”
A hozzászólás módosítva: Jan 10, 2017
(#) icserny válasza cpt.zoltan.simon hozzászólására (») Jan 11, 2017 /
 
Idézet:
„...végig is csináltam, csak éppen nem jelenik meg semmi a Printf ablakban.”

Ezen az oldalon azt írják, hogy az STM32F429 Discovery kártyán az SB9 átkötést össze kell forrasztani. Gondolom, ez viszi el az SWO jelet az STlink-re.
(#) cpt.zoltan.simon válasza icserny hozzászólására (») Jan 11, 2017 /
 
Igen. Az is megtörtént. Ma majd jobban nekiugrom kialudtam magam. Igazság szerint (mellesleg, jelen helyzetben) nem sok értelme van a szenvedésemnek, a vége úgyis egy valós debug port valódi usart csatival (RJ11). Csak a kíváncsiság hajt(ott), ennél több időt viszont nem vagyok hajlandó egy zsákutcára àlldozni.
(#) csabeszq hozzászólása Csü, 0:03 /
 
Egy vicces bug az STM32 API-ban. A problémám az, hogy 2 eszköz DMA-zik interrupttal, az egyik LCD-re és az interrupt sok számítást igényelt, a másik ADC-t mintavételez DMA-val, gyors reakcióra van szükség, viszont gyorsan véget is ér a rutin.

Azt vártam, hogy az ADC DMA interrupt preemptíven belehív az LCD interruptjába, amikor az éppen szüttyög, viszont API doksi ide, vagy oda, nem hívott az semmit. Megvárta, míg az LCD szépen lassan kiszámolja a végeredményt, utána pedig már sajnos késő volt.

A hibás kód:
  1. // 2 bit preemptív interruptnak, 2 bit alprioritásnak
  2. NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
  3.  
  4. NVIC_InitTypeDef NVIC_InitStructure;
  5.  
  6. // Ez lenne az ADC interrupt: 0/0 prioritással
  7. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  8. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  9. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  10. NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  11. NVIC_Init(&NVIC_InitStructure);
  12.  
  13. // Ez pedig az LCD interrupt 2/1 prioritással
  14. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  15. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  16. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  17. NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
  18. NVIC_Init(&NVIC_InitStructure);


Az élet szép és jó, csakhogy a fenti kód nem működik.
Pár sort hozzá kellett raknom:
  1. // külön azért még beállítom a prioritást, mert fentebb úgysem fog sikerülni
  2. NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(5,0,0));
  3. NVIC_SetPriority(DMA1_Channel5_IRQn, NVIC_EncodePriority(5,2,1));
  4. // az NVIC_EncodePriority(5,2,1)-ból az 5 jelenti a 2+2 bitet.
  5. // gondolom rajtam kívül mindenkinek tök logikus, hogy ha 2+2 bitet használsz
  6. // (prioritás/alprioritás), akkor 5-öt kell tenned az NVIC_EncodePriority-be.
  7. // Ki debuggoltam és ez adta a jó eredményt a köztes számításoknál.
  8. // Nem kell mindenen fennakadni, legyünk toleránsak a másként gondolkodók iránt.
  9. // - 0+4 bitnél 7-et írj
  10. // - 1+3 bitnél 6-ot
  11. // - 2+2 bitnél 5-öt
  12. // - 3+1 bitnél 4-et
  13. // - 4+0 bitnél 3-at


Szóval miután ügyesen még kézzel is beállítottuk a jó prioritást, valóban bele fog hívni az ADC csatorna DMA interruptja az LCD DMA interruptjába. Hurrá.
A hozzászólás módosítva: Csü, 0:08
(#) csabeszq válasza csabeszq hozzászólására (») Csü, 0:16 /
 
Ennyi elég és nem is fog bajt okozni később:

  1. NVIC_SetPriority(DMA1_Channel5_IRQn, NVIC_EncodePriority(5,2,1));
  2. NVIC_EnableIRQ(DMA1_Channe5_IRQn);


Az eredeti kóddal az a baj, hogy rossz regiszterbe ír, így jobb mellőzni a hívását, ha nem akarunk meglepetést később magunknak.
A hozzászólás módosítva: Csü, 0:17
(#) csatti2 válasza csabeszq hozzászólására (») Csü, 18:20 /
 
Azok a "másként gondolkodók" azért nem teljesen hülyék.

Az általad most használt funkciók a CMSIS részei, amit az összes hasonló ARM procihoz terveztek, legyen az M0, M3, M4, stb. és gyártsa az ST, NXP, Atmel, stb. . A specifikáció szerint max. 256 szint lehetséges, amiből az IC tervezője dönti el, hogy hány szintet implementál (min. 8, azaz 3bit). Mivel mindig az alsó nem használt bitek 0-ák, ezért a forráskódok elméletileg kompatibilisek maradnak akkor is ha egy több prioritásszintű uC-ről egy kevesebb szintet használó uC-re viszik át, lévén csak a legfinomabb prioritást hangoló bit(ek) vesznek el. Mivel a te általad használt uC 4 bitet használ a lehetséges 7-ből, ezért hát a 2+2bit konfiguráció teljesen jól kijön a 7-2 = 5 egyenlet megoldásaként .

Bónusz infó: Bár a subprioritás szintek első ránézésre (és második, harmadik stb. ránézésre is ) eléggé haszontalannak tűnnek, azért van némi hasznuk. Ezek a szintek ugyanis nem játszanak szerepet a megszakítások megszakításánál (nested interrupt ugye) csak a sorban álló ugyanolyan főprioritású megszakítások végrehajtási sorrendjénél számít az értékük.
A hozzászólás módosítva: Csü, 18:28
(#) csabeszq válasza csatti2 hozzászólására (») Pé, 11:05 /
 
Egyébként menet közben rájöttem, hogy nem bugos a kód.

Statikus konstruktor hívta meg az NVIC_Init-et és félreszámolt. Miután átraktam, hogy a main után állítsa be az interruptokat, működött.

Nem hasznontalan a szubprioritás. Nem mindig akarom, hogy egymást megszakítsák a rutinok, néha elég, ha sorrendben végrehajtódnak. Valljuk be, nehezebb preemption-ös interrupt handlert írni, mint ha nem lenne. Szórakozásból eszembe nem jutna saját magamat szívatni.

Csak akkor szakítsák meg egymást, ha indokolt, egyébként egyik lefuthat a másik után.
A hozzászólás módosítva: Pé, 11:07
(#) icserny válasza cpt.zoltan.simon hozzászólására (») Vas, 7:14 / 1
 
printf átirányítás SWO kimenentre Keil MDK alatt

Idézet:
„Végig is csináltam, csak éppen nem jelenik meg semmi a Printf ablakban.”

Nem csodálom, mert úgy látom, hogy az ebben a cikkben leírt printf átirányítás nem működik. Leírom, hogy nekem hogy sikerült:

0. Keil MDK Lite 5.20 van telepítve nálam. STM32F103C8T8-cal kísérleteztem, de ennek nincs jelentősége. A PB3 kivezetés az SWO kimenet.

1. Trace engedélyezés (úgy, ahogy a fenti cikkben írják): Trace enable pipa, CPU frekvencia a ténylegesen beállított legyen, s az ITM Stimulus Port 0-nál legyen pipa (lehet a többinél is, de ez kell)

2. Első körben csak ITM_SendChar(ch); hívásokkal próbálkoztam, ehhez nem kellett semmilyen bűvészkedés (ch helyére valamilyen karakterkódot vár a függvény).

Fordítás, debug módban programfuttatás esetén szépen pötyögtek a karakterek a debug printf ablakba.

3. Printf átirányítás: egy UART átirányítási mintapélda alapján az alábbi kódot szúrtam be a programba, s így működött a printf() debugolás is.

  1. //----- print átirányítás SWO kimenetre ------------
  2. #include <stdio.h>
  3. #pragma import(__use_no_semihosting_swi)
  4.  
  5. struct __FILE { int handle; /* Add whatever you need here */ };
  6.  
  7. FILE __stdout;
  8. FILE __stdin;
  9.  
  10. int fputc(int ch, FILE *f) {
  11.   ITM_SendChar(ch);
  12.   return (ch);
  13. }
  14.  
  15. void _sys_exit(int return_code) {
  16. label:  goto label;  /* endless loop */
  17. }
A hozzászólás módosítva: Vas, 7:16

Blinky.zip
    
Következő: »»   83 / 83
Bejelentkezés

Belépés

Hirdetés
Frissek
2017. Jan, 18. Sze
2:51:31
Jelenleg 78 fő olvassa az oldalt
Online tagok:
Lapoda.hu     XDT.hu     HEStore.hu