Renesas RX210, kul men tröttande!
Renesas RX210, kul men tröttande!
Har påbörjat ett projekt med en Renesas RX210 µC. Jag är rimligt nöjd med den, tanken är att den ska ersätta en "gammal" Fujitsi MB90F583CB som är en 16-bitars på max 16MHz. Gamla kretsen tuggar på ganska duktigt osv. men efter skalvet i Japan är tillverkningen skakig och priset högt.
Så nu är det vald en Renesas Rx210 istället. Det är en 32 bitars med en massa(!) godis inbyggd, den tuggar iväg med upp till 50MHz (intern osc. på 32, 36,864, 40 och 50MHz) vilket jag tycker räcker fint, speciellt eftersom den "gamla" 16-bitaren på 16MHz klarade samma jobb utan att svettas allt för mycket. Såklart kan den en massa med externa kristaller, PLL osv. men jag ämnar att använda den interna 32MHz klocka, den räcker långt.
Men nu kommer det roliga...
Många funktioner ger många register! Hårdvaramanualen är bara på 1612 sidor, det finns säkerhetsregister som man måste "öppna" med specifika värden för att kunde skriva i vissa vitala delar. Och jag har nu suttit 2 dagar med att öppna en satans serieport!!! Nu är jag i mål. Man ska:
* Sätta portpinnarna rätt (in/ut + startnivå) samt open-drain eller inte, pull-up eller inte osv.
* Sätta portpinnerna till att fungera med deras alternativa funktion (i detta fall UART Tx + Rx). En bit per portpinne.
* Slå av avstängningen av UART'en i "Low Power Consumption"-funktionen, bara en bit i något register. Är dock skyddad av skyddsfunktionen varför man får öppna den först, ändra och låsa efter sig.
* Sätta UART'en till rätt typ (Asynk, n81, baudrate osv.) En uppsjö av I2C, SPI, Smart Card, Async. och andra funktioner gör att det är en hel del register att ställa rätt för detta.
* Sedan ska "Multi-Function Pin Controllern" ställas rätt (et register per portpinne!)
* Interruptnivåer väljas, läggas in, enablas/disablas osv.
Tro mig, jag höll på att bli mer skvatt galen än jag redan är. Renesas är bra på att tillverka häftiga kretsar men i tydlighet och hjälp i databladet är de på nivå med Atmel. Inte imponerande alltså.
Men nu har jag grejen liggande bredvid mig, jag har kopplat två serieporta på den samt 3 st LED och den gör som den får besked på. Programmeringen fungerar bra med HEW (Renesas IDE + kompiler), jag skulle dock gärna vilja ha den till att fungera i Eclipse och KPIT GNU-kompilern men det får jag lägga kraft på senare.
Jag ska också viderutveckla mitt Flash-program till den, det fungerar redan på Renesas M16Coch fungerar via den inbyggda (från fabriken) bootloader samt handskakningssignalerna i serieporten. Då kan jag välja att aktivera en terminalfunktion i det program då jag ju redan använder en vanlig UART att programmera via.
Totalen är att mitt flashningsprogram kan övervaka HEX-filen datum/tid, om den ändras inaktiveras terminalfunktionen, kretsen resettas och snäpps in i bootloder-läget, programmet överförs varefter terminalfunktionen återaktiveras om man har vald detta. MYCKET smidigt vid utveckling och debuggning!
Men satan i gatan vad krångligt det har varit att få gång i den första serieport! Att få gång i nästa serieport tog 3 minuter, nu vet jag ju hur man gör...
Att jag har vald just RX210 är för att den kan drivas med 5V. Detta ger mer störimmunitet och i de miljöer som projektet kan komma att användas i är det en kännbar fördel.
Så nu är det vald en Renesas Rx210 istället. Det är en 32 bitars med en massa(!) godis inbyggd, den tuggar iväg med upp till 50MHz (intern osc. på 32, 36,864, 40 och 50MHz) vilket jag tycker räcker fint, speciellt eftersom den "gamla" 16-bitaren på 16MHz klarade samma jobb utan att svettas allt för mycket. Såklart kan den en massa med externa kristaller, PLL osv. men jag ämnar att använda den interna 32MHz klocka, den räcker långt.
Men nu kommer det roliga...
Många funktioner ger många register! Hårdvaramanualen är bara på 1612 sidor, det finns säkerhetsregister som man måste "öppna" med specifika värden för att kunde skriva i vissa vitala delar. Och jag har nu suttit 2 dagar med att öppna en satans serieport!!! Nu är jag i mål. Man ska:
* Sätta portpinnarna rätt (in/ut + startnivå) samt open-drain eller inte, pull-up eller inte osv.
* Sätta portpinnerna till att fungera med deras alternativa funktion (i detta fall UART Tx + Rx). En bit per portpinne.
* Slå av avstängningen av UART'en i "Low Power Consumption"-funktionen, bara en bit i något register. Är dock skyddad av skyddsfunktionen varför man får öppna den först, ändra och låsa efter sig.
* Sätta UART'en till rätt typ (Asynk, n81, baudrate osv.) En uppsjö av I2C, SPI, Smart Card, Async. och andra funktioner gör att det är en hel del register att ställa rätt för detta.
* Sedan ska "Multi-Function Pin Controllern" ställas rätt (et register per portpinne!)
* Interruptnivåer väljas, läggas in, enablas/disablas osv.
Tro mig, jag höll på att bli mer skvatt galen än jag redan är. Renesas är bra på att tillverka häftiga kretsar men i tydlighet och hjälp i databladet är de på nivå med Atmel. Inte imponerande alltså.
Men nu har jag grejen liggande bredvid mig, jag har kopplat två serieporta på den samt 3 st LED och den gör som den får besked på. Programmeringen fungerar bra med HEW (Renesas IDE + kompiler), jag skulle dock gärna vilja ha den till att fungera i Eclipse och KPIT GNU-kompilern men det får jag lägga kraft på senare.
Jag ska också viderutveckla mitt Flash-program till den, det fungerar redan på Renesas M16Coch fungerar via den inbyggda (från fabriken) bootloader samt handskakningssignalerna i serieporten. Då kan jag välja att aktivera en terminalfunktion i det program då jag ju redan använder en vanlig UART att programmera via.
Totalen är att mitt flashningsprogram kan övervaka HEX-filen datum/tid, om den ändras inaktiveras terminalfunktionen, kretsen resettas och snäpps in i bootloder-läget, programmet överförs varefter terminalfunktionen återaktiveras om man har vald detta. MYCKET smidigt vid utveckling och debuggning!
Men satan i gatan vad krångligt det har varit att få gång i den första serieport! Att få gång i nästa serieport tog 3 minuter, nu vet jag ju hur man gör...
Att jag har vald just RX210 är för att den kan drivas med 5V. Detta ger mer störimmunitet och i de miljöer som projektet kan komma att användas i är det en kännbar fördel.
Re: Renesas RX210, kul men tröttande!
Jag känner med dig! 
Att lära sig en ny processor är JOBBIGT. När det gäller Renesas kan jag väl tycka att databladen språkligt ibland är undermåliga. Men hårdvaran har vettiga defaults och oftast tycker jag saker brukar fungerar någolunda även på första eller andra försöket när man konfat bitarna efter bästa förmåga. (Har plöjt igenom två 16-bitars R8C modeller.)
Har kämpat med en CC2430 (?) processor från TI och där kan jag inte säga samma sak! I den måste varenda sketna bit vara absolut rätt för att något överhuvudtaget skulle röra på sig.
Håller för tillfället på att plöja ner i en ARM Coretex-M4 och det tar tid. Hobbyprojekt så det får ta tid. Fick igång SPI ikväll. Avancerad processor med coola features, men också lika avancerad att konfa och lära sig.
Man byter inte processor så där bara.

Att lära sig en ny processor är JOBBIGT. När det gäller Renesas kan jag väl tycka att databladen språkligt ibland är undermåliga. Men hårdvaran har vettiga defaults och oftast tycker jag saker brukar fungerar någolunda även på första eller andra försöket när man konfat bitarna efter bästa förmåga. (Har plöjt igenom två 16-bitars R8C modeller.)
Har kämpat med en CC2430 (?) processor från TI och där kan jag inte säga samma sak! I den måste varenda sketna bit vara absolut rätt för att något överhuvudtaget skulle röra på sig.
Håller för tillfället på att plöja ner i en ARM Coretex-M4 och det tar tid. Hobbyprojekt så det får ta tid. Fick igång SPI ikväll. Avancerad processor med coola features, men också lika avancerad att konfa och lära sig.
Man byter inte processor så där bara.
Re: Renesas RX210, kul men tröttande!
mri: Jag har kört en del andra projekt med Renesas M16C i olika tappningar, allt från M16C-62 till M16C-26A och visst, de kan vara lite intressanta i vissa delar rörande databladet och "interagerande" med andra delar som kan vara svåra att överskåda - men RX-serien tar priset!
Å andra sidan får jag ju respektera att den kör med 50MHz och drar runt 20mA för µC själv. En '386 på 50MIPS med FPU lär knappast klara sig med den ström!
Å andra sidan får jag ju respektera att den kör med 50MHz och drar runt 20mA för µC själv. En '386 på 50MIPS med FPU lär knappast klara sig med den ström!
Re: Renesas RX210, kul men tröttande!
Jag trodde att onödig komplexitet var karakrtäristiskt för Amerikanska grejer. Tydligen ännu värre med Japanska.
Hoppas bara inte Kineserna tar över och slår rekord!
Hoppas bara inte Kineserna tar över och slår rekord!
Re: Renesas RX210, kul men tröttande!
Nu vet jag ju inte vad du menar med "onödig komplexitet" men när antalet interruptvektorer når 250 st, interrupt nivåer når 15 st (+ inaktiv) samt att många pinnar kan ha fler olika funktioner samtidig, då kan jag förstå att det är många saker som ska ställas rätt.
Men just nu känns det som lite väl många saker på en och samma gång! Och jag har redan hittat ett fel i kompilerns data...
EDIT: Jahopp, helgen har gått åt... Men nu har jag en time-tick med interrupt, jag har en seriell port som sänder interrupt-driven. Jag mätte lite för att ha lite argument inför ett par Ex-jobbare som är med i detta.
Att överföra 34 tecken med 9k6n81 tar en tid. Att skriva ut dom tar en tid. Men förhållandet är så att om det tar 1 tidenhet att skriva ut datan och peta i buffer tar det 232 gångar så lång tid att sända skiten! Och då har jag räknat med overheaden vid interrupten!
Nu där jag är lite mindre osams med RX210'an börjar det vara lite kul att klämma in lite hastighet och göra grejer. Den har tydligen lite DSP-funktioner, det finns exempelkod för FFT osv.
Men just nu känns det som lite väl många saker på en och samma gång! Och jag har redan hittat ett fel i kompilerns data...
EDIT: Jahopp, helgen har gått åt... Men nu har jag en time-tick med interrupt, jag har en seriell port som sänder interrupt-driven. Jag mätte lite för att ha lite argument inför ett par Ex-jobbare som är med i detta.
Att överföra 34 tecken med 9k6n81 tar en tid. Att skriva ut dom tar en tid. Men förhållandet är så att om det tar 1 tidenhet att skriva ut datan och peta i buffer tar det 232 gångar så lång tid att sända skiten! Och då har jag räknat med overheaden vid interrupten!
Nu där jag är lite mindre osams med RX210'an börjar det vara lite kul att klämma in lite hastighet och göra grejer. Den har tydligen lite DSP-funktioner, det finns exempelkod för FFT osv.
Re: Renesas RX210, kul men tröttande!
Åh ja, jag börjar trivas bättre med RX'en faktisk. Håller på att lägga in den i ett par design, ett av dom är bara byte av µC för att få en som tillverkas, den gamla modell slutade tillverkas efter skalvet i Japan.
På jobbet har vi ju LED-moduler, jag testade med två stycken á 32 x 16 punkter, 10 mm mellan pixlarna och varje pixel består av en röd, en grön och en blå LED. Data skickas in synkront, alltså Data till pinnar (RGB för övre och undre halvan) och sedan skaka klockan. När alla data i skanningsraden är överförd skakar man på strobe och data visas. Såklart är modulerna med tätning och gjorda för att bygga stora ytor av, vi pratar dessa arena-videoskärmar...
Jag hade ett helvete med att få PWM-funktionen att fungera, Renesas må vara bra på att göra bra och ganska billiga kretsar - men de är inte lika bra på datablad! Jag fick det dock att fungera, därmed kan jag ställa intensiteten på dessa LED-moduler. Just de moduler jag "leker" med är lite "billiga", det finns inte drivkretsar för alla LED, man måste skanna 4 rader. Men en timer-interrupt löste detta och att välja bildminne, klocka ut 128 bytes data, styra radräkningen och allt för en rads uppdatering tar 252µs - och jag har inte trimmat programmet.
Just detta att byta rad gav lite ghosting och jag insåg att jag skulle bli tvunget att styra PWM-delen också för att släppa detta. Men nej! Jag kom på att Renesas har vald ett lite konstigt sätt att styra vad varje pinne gör. Det finns ett register för om en portpinne ska vara in eller ut, inget konstigt i det.
Sedan ska man välja om portpinnen ska vara portpinne eller om den ska användas till den alternativa funktion.
Sedan måste man välja vilken alternativ funktion den ska ha (jupp, ett register per portpinne!) och då börjar det bli lite tråkigt att skriva. Dock är databladet rimligt tydligt på den punkt.
Men det gav mig lösningen på ghost-problemet! Jag satte portpinnens output-register till '1' (= display av) och precis innan skanningen byter rad byter jag portpinnen från alternativ funktion till portpinne, detta växlar pinnens signal från PWM (med lysintensiteten) till "display av", sedan läggs rätt radnummer in, data latchas ut till drivstegen och portpinnen återställs till att fungera som PWM-utgång. Resultat: totalt ghost-fri!
Nu trilskas det lite med sändning av UART-data. Jag vill ha en interruptstyrd buffring av sändning av data men jag måste kolla lite mer på hur jag ska styra enable & disable av interrupten, det finns ett par möjligheter och jag ska hitta den rätta. Som det är nu hakar det upp sig ibland och jag är tveksam till om jag har programfel, samma teknik har jag använd på en del andra processorer utan problem - men med RX'en finns det fler olika möjligheter att disabla & enabla interrupten och jag har någon känsla av att jag använder fel typ.
Men jag har hittat en Application Note med ett exempel som jag ska lusläsa.
Jag hittade även ett par bortkastade LED-moduler. Ett var en monokrom som hade blivit brutalt påkörd (satt i ett höjdvarningsdisplay) och det var knäckt. Men drivkretsarna fanns kvar, alltså fram med varmluftpistolen och ta dom med hem, jag har sedan tidigare ett antal trasiga plattor som jag ska laga och nu har jag reservdelar.
Andra plattan var en 16 x 16 RGB med pixelavstånd om 12mm. Felet på den är att ett par gröna LED lyser svagt på en punkt. Ska testa att byta drivkrets vid tillfälle men just nu använder jag den för att testa lite grejer. Jag testade att kräma på med alla LED i alla 16 x 16 punkter tända samtidig (fast det blir bara 16 x 8 då displayen multiplexas i två halvor). Min nätdel kan bara ge 3A så den gick i knä vid 56% intensitet... Och ja, det ger ljus!
Det är kul att leka!
På jobbet har vi ju LED-moduler, jag testade med två stycken á 32 x 16 punkter, 10 mm mellan pixlarna och varje pixel består av en röd, en grön och en blå LED. Data skickas in synkront, alltså Data till pinnar (RGB för övre och undre halvan) och sedan skaka klockan. När alla data i skanningsraden är överförd skakar man på strobe och data visas. Såklart är modulerna med tätning och gjorda för att bygga stora ytor av, vi pratar dessa arena-videoskärmar...
Jag hade ett helvete med att få PWM-funktionen att fungera, Renesas må vara bra på att göra bra och ganska billiga kretsar - men de är inte lika bra på datablad! Jag fick det dock att fungera, därmed kan jag ställa intensiteten på dessa LED-moduler. Just de moduler jag "leker" med är lite "billiga", det finns inte drivkretsar för alla LED, man måste skanna 4 rader. Men en timer-interrupt löste detta och att välja bildminne, klocka ut 128 bytes data, styra radräkningen och allt för en rads uppdatering tar 252µs - och jag har inte trimmat programmet.
Just detta att byta rad gav lite ghosting och jag insåg att jag skulle bli tvunget att styra PWM-delen också för att släppa detta. Men nej! Jag kom på att Renesas har vald ett lite konstigt sätt att styra vad varje pinne gör. Det finns ett register för om en portpinne ska vara in eller ut, inget konstigt i det.
Sedan ska man välja om portpinnen ska vara portpinne eller om den ska användas till den alternativa funktion.
Sedan måste man välja vilken alternativ funktion den ska ha (jupp, ett register per portpinne!) och då börjar det bli lite tråkigt att skriva. Dock är databladet rimligt tydligt på den punkt.
Men det gav mig lösningen på ghost-problemet! Jag satte portpinnens output-register till '1' (= display av) och precis innan skanningen byter rad byter jag portpinnen från alternativ funktion till portpinne, detta växlar pinnens signal från PWM (med lysintensiteten) till "display av", sedan läggs rätt radnummer in, data latchas ut till drivstegen och portpinnen återställs till att fungera som PWM-utgång. Resultat: totalt ghost-fri!
Nu trilskas det lite med sändning av UART-data. Jag vill ha en interruptstyrd buffring av sändning av data men jag måste kolla lite mer på hur jag ska styra enable & disable av interrupten, det finns ett par möjligheter och jag ska hitta den rätta. Som det är nu hakar det upp sig ibland och jag är tveksam till om jag har programfel, samma teknik har jag använd på en del andra processorer utan problem - men med RX'en finns det fler olika möjligheter att disabla & enabla interrupten och jag har någon känsla av att jag använder fel typ.
Men jag har hittat en Application Note med ett exempel som jag ska lusläsa.
Jag hittade även ett par bortkastade LED-moduler. Ett var en monokrom som hade blivit brutalt påkörd (satt i ett höjdvarningsdisplay) och det var knäckt. Men drivkretsarna fanns kvar, alltså fram med varmluftpistolen och ta dom med hem, jag har sedan tidigare ett antal trasiga plattor som jag ska laga och nu har jag reservdelar.
Andra plattan var en 16 x 16 RGB med pixelavstånd om 12mm. Felet på den är att ett par gröna LED lyser svagt på en punkt. Ska testa att byta drivkrets vid tillfälle men just nu använder jag den för att testa lite grejer. Jag testade att kräma på med alla LED i alla 16 x 16 punkter tända samtidig (fast det blir bara 16 x 8 då displayen multiplexas i två halvor). Min nätdel kan bara ge 3A så den gick i knä vid 56% intensitet... Och ja, det ger ljus!
Det är kul att leka!
Re: Renesas RX210, kul men tröttande!
Då så, lite statusrapport:
A) Interruptstyrd seriell sändning fungerar bra! Men Renesas är lite konstiga där: det saknas en bit som man kan kolla huruvida UART'ens sändregister är ledigt eller inte! Jag har dock löst detta och det var inget svårt när jag väl hade gjort det.
Men det man sänder ska ju petas i sänd-buffern och det var största problemet ett tag. Det är numera löst:
För att sända ett tecken (en byte) på serieporten kallar jag alltså Send_Serial_Byte(). För att skriva ut en sträng/text använder jag Send_Serial_Buffer() som bara skickar tecken efter tecken.
Och varför då så besvärligt? Helt enkelt för att spara tid! Kör man 9600n81 tar varje byte 10 bits tid att sända, alltså 960 tecken/sekund. Ganska bra hastighet - men om µC'n tuggar på med den interna klocka på 50MHz blir det 52083 instruktioner som, utan interruptstyrd sändning och buffring, kastas bort... per tecken! Det overhead som hela interruptgrejen ger tjänar jag enkelt hem i hastighet.
Skulle jag försöka överfylla buffern kommer den att stanna upp och vänta till det blir plats att peta i varje tecken, samtidig sätts flaggan (Ser1.Tx.Overflow) så att man kan kolla det om det behövs. Den flagga nollas bara vid initieringen.
Principen för denna buffring har jag använd genom många år på många olika processorer - men alla andra har haft en flagga som indikerar om sänd-registret är redo att ta emot ny byte eller inte och just på denna µC fattas det tydligen.
B) PWM är inte tydligt beskrivit i databladet. Det förklaras att man kan sätta startvillkor men vad som ska hända sedan är en lita tuffare nöt att få veta, jag gissade till slut och fattade.
Stötestenen var värdet som skrivs i MTU2.TIOR.BYTE. I databladet anges bara låga nibblens funktion men jag testade fram att den höga nibbel avgör vad som händer sedan när rätt räknavärde uppnås.
För att ställa PWM-värdet:
För tillfället jobbar jag på att bygga ett PONG-spel på 2 st moduler med 32 * 16 RGB-pixlar, jag har redan full funktion på scanningen, displayminnet, pixel-ritning, linje-ritning osv. så nu är det själva PONG-reglerna med poängräkning som gäller. Man kommer att styra paddlarna med var sin potentiometer, då kan jag testa den inbyggda AD-omvandlaren (12 bit) och få den att fungera.
C) En systemtimer är alltid bra att ha!
Om variabeln "Main_Normal" ställs till icke-noll i main-loop kommer det att bli en dubbel-blink vilket gör att jag kan se om main-loop har hängt sig. Utan den blir det enkelblink.
A) Interruptstyrd seriell sändning fungerar bra! Men Renesas är lite konstiga där: det saknas en bit som man kan kolla huruvida UART'ens sändregister är ledigt eller inte! Jag har dock löst detta och det var inget svårt när jag väl hade gjort det.
Kod: Markera allt
Lite definitioner som kan abstrahera från hårdvaran på ett mer lättläst sätt:
#define SER1_Tx_Pin PORT2.PODR.BIT.B6
#define SER1_Tx_Pin_Dir PORT2.PDR.BIT.B6
#define SER1_Rx_Pin PORT3.PIDR.BIT.B0
#define SER1_Rx_Pin_Dir PORT3.PDR.BIT.B0
Först en struktur som håller lite buffer osv. till serieporten. Läget är helt vanlig asynk.
struct
{
struct
{
char Buffer[500];
volatile _UINT In;
volatile _UINT Out;
volatile _UINT Busy;
volatile _UBYTE Overflow;
} Tx;
struct
{
char Buffer[500];
volatile _UINT In;
} Rx;
} Ser1;
Sedan ska skiten initieras:
void Initiate_Ser_1(void)
{
_UINT Ctr;
SER1_Rx_Pin_Dir = false; // Set SER1 Rx direction as input
SER1_Tx_Pin_Dir = true; // Set SER1 Tx direction as output
SER1_Tx_Pin = true; // Set SER1 Tx start position ('1')
Ser1.Tx.In = 0; // Set to initial state
Ser1.Tx.Out = 0; // Set to initial state
Ser1.Tx.Busy = false; // Set to initial state
Ser1.Rx.In = 0; // Start position
Ser1.Rx.Buffer[0] = false; // Just for the sake of nothing
Ser1.Tx.Overflow = false; // Unmark it for starter
SYSTEM.PRCR.WORD = 0xA502; // Open the lock
MSTP(SCI1) = 0; // Power up SCI1
SYSTEM.PRCR.WORD = 0xA500; // Lock up again
SCI1.SCR.BYTE = 0x00; // Shut off all settings
SCI1.SCR.BYTE = 0x00; // Shut off all settings
SCI1.SMR.BYTE = 0x00; // Async, 8n1, PCLKB : 1
SCI1.SCMR.BYTE = 0xF2; // Not Smart Card Interface mode
SCI1.SEMR.BYTE = 0x00; // No noise filter, Async base = 16 clk
SCI1.SIMR1.BYTE = 0x00; // To enable the writing of SCR.RE & TE
MPC.PWPR.BYTE = 0x00; // Start allowing writing
MPC.PWPR.BYTE = 0x40; // Allow writing to MPC-registers
MPC.P26PFS.BYTE = 0x0A; // Select TX1D on P26
MPC.P30PFS.BYTE = 0x0A; // Select RXD1 on P30
MPC.PWPR.BYTE = 0x80; // Shut down writing to MPC-registers
SCI1.BRR = ((PCLK / BAUD_RATE) / 32) - 1;
for(Ctr = 0; Ctr <= (CPU_CLK / 2) / BAUD_RATE; Ctr++); /* 1bit+ time wait */
SCI1.SCR.BYTE = 0x30; // Enable Tx & Rx, stops most writings also
SCI1.SCR.BYTE = 0xF0; // Enable RXI
PORT2.PMR.BIT.B6 = 1; // Use SER1 Tx as peripheral function
PORT3.PMR.BIT.B0 = 1; // Use SER1 Rx as peripheral function
IPR(SCI1, ) = 1; // Interrupt priority to lowest active
IR(SCI1,RXI1) = false; // Clear any residual interrupt
IR(SCI1,TXI1) = false; // Clear any residual interrupt
IR(SCI1,ERI1) = false; // Clear any residual interrupt
IR(SCI1,TEI1) = false; // Clear any residual interrupt
IEN(SCI1,RXI1) = true; // Enable Rx Interrupt to exist
IEN(SCI1,TXI1) = true; // Enable Tx Interrupt to exist
IEN(SCI1,ERI1) = true; // Enable Rx error Interrupt to work - or not
IEN(SCI1,TEI1) = false; // Enable Interrupt to work - or not
}
Sedan lite interrupts:
#pragma interrupt SCI1_Tx_ISR(vect=VECT(SCI1,TXI1))
void SCI1_Tx_ISR(void) // Ger en interrupt när den börjar sända nästa tecken - om interrupt är enablad
{
if(Ser1.Tx.Busy)
{
SCI1.TDR = Ser1.Tx.Buffer[Ser1.Tx.Out]; // Slam out the next byte to send
if(++Ser1.Tx.Out >= sizeof(Ser1.Tx.Buffer)) Ser1.Tx.Out = 0; // Update Out-index, circular buffer
if(Ser1.Tx.In == Ser1.Tx.Out)
{ // They are same, end further transmission
Ser1.Tx.Busy = false; // Set to done
IEN(SCI1,TXI1) = false; // Stop further interrupts as of now
}
}
}
#pragma interrupt SCI1_Rx_ISR(vect=VECT(SCI1,RXI1))
void SCI1_Rx_ISR(void)
{
// Recieve interrupt (if enabled)
_UBYTE Incoming;
Incoming = SCI1.RDR; // A read empties the Rx-buffer and removes the interrupt
if(Ser1.Rx.In < sizeof(Ser1.Rx.Buffer) - 1)
{ // Room exists, put in buffer
Ser1.Rx.Buffer[Ser1.Rx.In++] = Incoming;
}
}
#pragma interrupt SCI1_ERI_ISR(vect=VECT(SCI1,ERI1))
void SCI1_ERI_ISR(void)
{ // Rx error interrupt
SCI1.SSR.BYTE = (SCI1.SSR.BYTE & 0xC6) | 0xC0; // Clear Rx error
}
#pragma interrupt SCI1_TEI_ISR(vect=VECT(SCI1,TEI1))
void SCI1_TEI_ISR(void)
{
// Transmit ended interrupt. Usefull with RS485 communication
IR(SCI1,TEI1) = 0; // Acknowledge interrupt
}
Kod: Markera allt
void Send_Serial_Byte(_UBYTE Data)
{
volatile _UINT Next;
if(SCI1.SSR.BIT.TEND || (IR(SCI1,TXI1) && !Ser1.Tx.Busy)) // OK, room exists, slam it out
{
IR(SCI1,TXI1) = 0; // Clear possibel pending interrupt
SCI1.TDR = Data; // Just dunk it out, room exists!
}
else
{
// Use overrun protection
Next = Ser1.Tx.In + 1; // Check if overrun is imminent
if(Next >= sizeof(Ser1.Tx.Buffer)) Next = 0; // Circular buffer, remember?
while(Next == Ser1.Tx.Out) Ser1.Tx.Overflow = true; // Mark that overflow was threatning while waiting
// Overrun protection done, now buffer the datas
IEN(SCI1,TXI1) = false; // No interrupts just now
Ser1.Tx.Busy = true; // Mark as using buffering mode
Ser1.Tx.Buffer[Ser1.Tx.In] = Data; // Put data into buffer
Ser1.Tx.In = Next; // Already calculated, reuse that
IEN(SCI1,TXI1) = true; // Allow interrupts to come
}
}
void Send_Serial_Buffer(_UBYTE* Data)
{
while(*Data)
{
Send_Serial_Byte(*(Data++));
}
}
Och varför då så besvärligt? Helt enkelt för att spara tid! Kör man 9600n81 tar varje byte 10 bits tid att sända, alltså 960 tecken/sekund. Ganska bra hastighet - men om µC'n tuggar på med den interna klocka på 50MHz blir det 52083 instruktioner som, utan interruptstyrd sändning och buffring, kastas bort... per tecken! Det overhead som hela interruptgrejen ger tjänar jag enkelt hem i hastighet.
Skulle jag försöka överfylla buffern kommer den att stanna upp och vänta till det blir plats att peta i varje tecken, samtidig sätts flaggan (Ser1.Tx.Overflow) så att man kan kolla det om det behövs. Den flagga nollas bara vid initieringen.
Principen för denna buffring har jag använd genom många år på många olika processorer - men alla andra har haft en flagga som indikerar om sänd-registret är redo att ta emot ny byte eller inte och just på denna µC fattas det tydligen.
B) PWM är inte tydligt beskrivit i databladet. Det förklaras att man kan sätta startvillkor men vad som ska hända sedan är en lita tuffare nöt att få veta, jag gissade till slut och fattade.
Kod: Markera allt
Först abstrahera lite:
#define Display_Pin_13 PORTB.PODR.BIT.B5 /* Pin 55, MTIOC2A, cable pin 13 */
#define Display_Pin_13_F PORTB.PMR.BIT.B5 /* The mode bit */
#define DISPLAY_PWM_STEPS 100 /* 0-100% */
void Initiate_Display_PWM(void)
{
SYSTEM.PRCR.WORD = 0xA502; // Open protection
MSTP(MTU2) = 0; // MTU2 module stop state cancelled
SYSTEM.PRCR.WORD = 0xA500; // Lock it again!
MPC.PWPR.BIT.B0WI = 0; // Enable writing PFSWE bit
MPC.PWPR.BIT.PFSWE = 1; // Enable writing PFS register
MPC.PB5PFS.BYTE = 1; // Use PB5 as MTIOC2A, no interrupt used
MPC.PWPR.BIT.PFSWE = 0; // Disable writing PFS register
MPC.PWPR.BIT.B0WI = 1; // Disable writing PFSWE bit
Display_Pin_13_F = 1; // Set port pin alternative function
Display_Pin_13 = 1; // Set för blanking purpose in scanning
// Now the port pin should be prepared to use
MTU2.TCR.BYTE = 0x20; // PCLK/1, Count on rising edge, TCNT cleared @ TGDA-match
MTU2.TMDR.BYTE = 0x02; // PWM mode 1, TGRA-TGRD operates normally
MTU2.TIOR.BYTE = 0x12; // Initial low, High on Compare Match
MTU2.TGRA = DISPLAY_PWM_STEPS * DISPLAY_PWM_RESOLUTION; // PWM Cycle time
MTU2.TGRB = DISPLAY_PWM_STEPS * (DISPLAY_PWM_RESOLUTION - Display.Light); // PWM compare register
MTU.TSTR.BYTE = 0x04; // Let MTU2 run
}
För att ställa PWM-värdet:
Kod: Markera allt
void Display_Set_Light(_UINT Value)
{ // This routine controls the intensity on teh display. '0'= LIGHT ON! '1' = Display off!
if(Value > DISPLAY_PWM_RESOLUTION) Value = DISPLAY_PWM_RESOLUTION;
MTU2.TGRB = (DISPLAY_PWM_RESOLUTION - Value) * DISPLAY_PWM_STEPS;
}
C) En systemtimer är alltid bra att ha!
Kod: Markera allt
void Initiate_System_Timer(void)
{
Timer_Tick = 0;
Hour = 0;
Minute = 0;
Second = 0;
Second_Update = 0;
Prescaler = 0;
Delay_Counter = 0;
SYSTEM.PRCR.WORD = 0xA502;
MSTP(CMT0) = 0; // Timer module stop state cancelled
SYSTEM.PRCR.WORD = 0xA500; // Lock up again!
CMT.CMSTR0.BIT.STR0 = 0; // Stop timer
CMT0.CMCR.WORD = 0x0042; // Enable compare interrupt & set PCLK:128
CMT0.CMCNT = 0x0000; // Clear the count
CMT0.CMCOR = (PCLK / 128) / TIME_TICK; // Should give 100Hz a.k.a. 10ms
IPR(CMT0,CMI0) = 2; // Interrupt priority = 2
IEN(CMT0,CMI0) = 1; // Enable interrupts
CMT.CMSTR0.WORD = 0x0001;
}
#pragma interrupt CMT0_ISR (vect=VECT(CMT0,CMI0))
void CMT0_ISR(void) // System timer interrupt
{
Timer_Tick++; // Just a 10ms timer for ...well some... use
if(++Prescaler >= 100) // One second gone
{
Prescaler = 0;
Second_Update++;
if(++Second >= 60) {Second = 0; if(++Minute >= 60) {Minute = 0; Hour++;}}
}
if(Delay_Counter) Delay_Counter--;
#define DOUBLE_BLINK_OFFSET 10 /* Eq. 0,1 sec */
#if true
// Hey man, a blinking blue LED is cool!
switch(Prescaler)
{
case 0:
LED_Blue = true;
break;
case 1:
LED_Blue = false;
break;
#if DOUBLE_BLINK_OFFSET
case DOUBLE_BLINK_OFFSET:
if(Main_Normal) LED_Blue = true;
Main_Normal = false;
break;
case DOUBLE_BLINK_OFFSET + 1:
LED_Blue = false;
break;
#endif // DOUBLE_BLINK_OFFSET
}
#endif
}
Re: Renesas RX210, kul men tröttande!
Den här processorn har alltså ingen hårdvaru FIFO heller? Verkar vara standard för Renesas att inte ha det... Iofs inget problem i ditt fall med 50MHz och 9600bps. Du har antagligen DMA grejs på den där som kan hängas på serieporten också, ifall du inte vill reagera på varje enskillt tecken.
Jag kör 125 kbps på en 20 MHz Renesas utan hårdvaru FIFO och där måste man hela tiden passa på att inte hålla interrupten avstängda för länge så att man tappar tecken i kommunikationen.
Har jobbat med en ARM7 processor som hade 16 byte Tx och Rx FIFO. Betydligt lugnare med kommunikations interrupt där. Processorn kan då istället syssla med det verkliga arbetet.
Jag kör 125 kbps på en 20 MHz Renesas utan hårdvaru FIFO och där måste man hela tiden passa på att inte hålla interrupten avstängda för länge så att man tappar tecken i kommunikationen.
Har jobbat med en ARM7 processor som hade 16 byte Tx och Rx FIFO. Betydligt lugnare med kommunikations interrupt där. Processorn kan då istället syssla med det verkliga arbetet.
Re: Renesas RX210, kul men tröttande!
Nja... 1 stegs FIFO är inte mycket att skryta med faktisk.
Å andra sidan har man 15 interruptprioriteter att jobba med och man kan välja en interruptvektor som "snabb respons". 125kbps ger vid synkron överföring ändå 3200 instruktioner vid 50MHz CPU-klocka vilket är högsta frekvensen på den interna oscillator.
Är det asynkron överföring ger det ändå 4000 instruktioner vilket borde vara rikligt med tid.
Men är det hastighet som gäller kan det vara dags att fundera på att använda DMA-funktionaliteten som finns, det kräver dock att man vet storleken på blocket som ska tas emot eller sändas.
Å andra sidan har man 15 interruptprioriteter att jobba med och man kan välja en interruptvektor som "snabb respons". 125kbps ger vid synkron överföring ändå 3200 instruktioner vid 50MHz CPU-klocka vilket är högsta frekvensen på den interna oscillator.
Är det asynkron överföring ger det ändå 4000 instruktioner vilket borde vara rikligt med tid.
Men är det hastighet som gäller kan det vara dags att fundera på att använda DMA-funktionaliteten som finns, det kräver dock att man vet storleken på blocket som ska tas emot eller sändas.
Re: Renesas RX210, kul men tröttande!
Hur är det med möjligheterna att trigga så att en DMA skickar in nästa tecken istället för att en interruptrutin sköter det?
Re: Renesas RX210, kul men tröttande!
Problemet är inte att hinna serva kommunikationen, om kommunikation var det enda processorn behöver göra. Problem uppstår i mitt fall om någon annan aktivitet behöver stänga av interrupten i mer än 80 us, då tappar kommunikationen tecken och det leder till omsändningar. Eller rättare sagt, allt måste byggas så att interrupten inte behöver stängas av nån längre stund. T.ex. för att få till rätt väntetider till en simpel DS18s20 fick jag bygga en timerstyrd schedulerare.
Vad gäller DMA hade CC2430 processorn intelligent sådan. Den kunde t.ex. tolka första inkommande byte som längd på blocket. Testade aldrig denna funktion dock, men det borde vara möjligt att bygga meddelande sändning och mottagning som nästan helt jobbade i bakgrunden utan hjälp av interruptrutiner.
Vad gäller DMA hade CC2430 processorn intelligent sådan. Den kunde t.ex. tolka första inkommande byte som längd på blocket. Testade aldrig denna funktion dock, men det borde vara möjligt att bygga meddelande sändning och mottagning som nästan helt jobbade i bakgrunden utan hjälp av interruptrutiner.
Re: Renesas RX210, kul men tröttande!
Jo, 80µs är inte lång tid... Vid 20MHz blir det bara 1600 CPU-steg.
Jag kollade just databladet och RX'en kan detta med DMA på serieport 5.
Jag kollade just databladet och RX'en kan detta med DMA på serieport 5.