Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2014:pixel-light

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
2014:pixel-light [2015/01/16 21:54]
Pavel Kostelník
2014:pixel-light [2015/01/19 01:44] (aktuální)
Pavel Kostelník
Řádek 65: Řádek 65:
 __task void init (void) ​ __task void init (void) ​
 { {
- // create tasks: +   // create tasks: 
- t_blink = os_tsk_create(blink,​ 0); +      t_blink = os_tsk_create(blink,​ 0); 
- t_uart_tx = os_tsk_create(uart_tx,​ 0);  +      t_uart_tx = os_tsk_create(uart_tx,​ 0);  
- t_interpreter = os_tsk_create(interpreter,​ 0); +      t_interpreter = os_tsk_create(interpreter,​ 0); 
- t_spi247 = os_tsk_create(spi247,​ 0); +      t_spi247 = os_tsk_create(spi247,​ 0); 
- t_spi787 = os_tsk_create(spi787,​ 0); +      t_spi787 = os_tsk_create(spi787,​ 0); 
- t_dc247 = os_tsk_create(dc247,​ 0); +      t_dc247 = os_tsk_create(dc247,​ 0);
  
- // init semaphores:​ +   // init semaphores:​ 
- os_sem_init (&​Semspi247,​ 0); +      os_sem_init (&​Semspi247,​ 0); 
- os_sem_init (&​Semspi787,​ 0); +      os_sem_init (&​Semspi787,​ 0); 
- os_sem_init (&​Semdc247,​ 0);+      os_sem_init (&​Semdc247,​ 0);
   
- // init mutexes +   // init mutexes 
- os_mut_init(&​Mutspi247);​ +      os_mut_init(&​Mutspi247);​ 
- os_mut_init(&​Mutspi787);​ +      os_mut_init(&​Mutspi787);​ 
- os_mut_init(&​Mutuart_tx);​+      os_mut_init(&​Mutuart_tx);​
   
- //delete itself: +   // delete itself: 
- os_tsk_delete_self ();+      os_tsk_delete_self ();
 } }
 //​------------------------- TASK: init -- (End) ---------------------------------- //​------------------------- TASK: init -- (End) ----------------------------------
 </​code>​ </​code>​
 +
  
 === TASK: blink === === TASK: blink ===
Řádek 94: Řádek 95:
 //​-------------------------- TASK: blink -- (Begin) --------------------------------- //​-------------------------- TASK: blink -- (Begin) ---------------------------------
 // Blinking with LED D5  // Blinking with LED D5
- __task void blink (void)+__task void blink (void)
 { {
- while(1) +   while(1) 
- +   ​
- LED_off(5);​ //​ turn off LED5 +      LED_off(5);​ //​ turn off LED5 
- os_dly_wait (500); ​             // wait for 500 ms +      os_dly_wait (500); ​             // wait for 500 ms 
- LED_on(5);​ //​ turn on LED5 +      LED_on(5);​ //​ turn on LED5 
- os_dly_wait (500); ​             // wait for 500 ms +      os_dly_wait (500); ​             // wait for 500 ms 
- }+   ​}
 } }
 //​-------------------------- TASK: blink -- (End) ---------------------------------- //​-------------------------- TASK: blink -- (End) ----------------------------------
 </​code>​ </​code>​
 +
  
 === TASK: interpreter,​ spi787, spi247, dc247 === === TASK: interpreter,​ spi787, spi247, dc247 ===
 Task interpreter přebírá přijatá data po lince UART z počítače a dále je třídí na základě požadované operace, případně danou operaci sám provede. Například pokud je požadována operace komunikace po SPI s obvodem zdroje, task interpreter pošle data do příslušného bufferu a zašle semafor tasku spi787, kterého tím odblokuje, a task spi787 vykoná příkaz, který mu byl předán příslušným bufferem. Po vykonání příkazu task spi787 odešle výsledná data do počítače přes UART linku tím, že přepošle data tasku uart_tx, který se postará o jejich korektní odeslání. Task interpreter přebírá přijatá data po lince UART z počítače a dále je třídí na základě požadované operace, případně danou operaci sám provede. Například pokud je požadována operace komunikace po SPI s obvodem zdroje, task interpreter pošle data do příslušného bufferu a zašle semafor tasku spi787, kterého tím odblokuje, a task spi787 vykoná příkaz, který mu byl předán příslušným bufferem. Po vykonání příkazu task spi787 odešle výsledná data do počítače přes UART linku tím, že přepošle data tasku uart_tx, který se postará o jejich korektní odeslání.
-Ukázka jednoho tasku je uvedena zde: 
- 
-<code c>  
-//​------------------------- TASK: spi247 -- (Begin) -------------------------------- 
-// SPI communication with pixel light 
-__task void spi247 (void) 
-{    
- while(1) 
- { 
- os_sem_wait(&​Semspi247,​ 0xFFFF); ​            // wait for data (driven by semaphore) 
- SPI247_ReadBuff = (SPI247_ReadBuff+1) & (BUFFERSPISIZE - 1); 
- os_mut_wait(&​Mutspi247,​ 0xFFFF); ​       // wait for mutex 
- SPI_SendFrame((SPI247_Buffer[SPI247_ReadBuff][0] & 0x07), 0, SPI247_Buffer[SPI247_ReadBuff][1],​ SPI247_Buffer[SPI247_ReadBuff][2],​ 
- SPI247_Buffer[SPI247_ReadBuff][3],​ SPI247_Buffer[SPI247_ReadBuff][4]);​ //​ send SPI frame  
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until first SPI frame is received  
- SPI_RcvData = LPC_SSP2->​DR;​  ​        // received SPI frame  
- SPI_RcvData = SPI_RcvData ​ << 16; // shift first received SPI frame (higher)  
- while ((LPC_SSP2->​SR & 0x4)== 0x0){}  ​ // wait until second SPI frame is received ​ 
- SPI_RcvData = SPI_RcvData + (LPC_SSP2->​DR & 0x0000FFFF);​ // add lower received SPI frame 
-  
- os_mut_wait(&​Mutuart_tx,​ 0xFFFF); // wait for mutex 
- UART_SendFrame (0x01);​  ​               // send identification frame to PC 
- UART_SendFrame (SPI247_Buffer[SPI247_ReadBuff][0]);​ //​ send target device 
- UART_SendFrame (SPI_RcvData&​0xFF);​  ​   // send 1. byte (lowest) 
- UART_SendFrame ((SPI_RcvData >> 8)&​0xFF);​ //​ send 2. byte 
- UART_SendFrame ((SPI_RcvData >> 16)&​0xFF);​  ​  // send 3. byte 
- UART_SendFrame ((SPI_RcvData >> 24)&​0xFF);​  ​  // send 4. byte (highest) 
- os_mut_release(&​Mutuart_tx);​  ​         // release mutex  
-  
- SPI_SendFrame((SPI247_Buffer[SPI247_ReadBuff][0] & 0x07), 0, (SPI247_Buffer[SPI247_ReadBuff][1] & 0xF0) + 0x0F, 0, 0, 0); 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){}  ​ // wait until first SPI frame is received  
- SPI_RcvData = LPC_SSP2->​DR;​  ​ // received SPI frame  
- SPI_RcvData = SPI_RcvData ​ << 16; // shift first received SPI frame (higher)  
- while ((LPC_SSP2->​SR & 0x4)== 0x0){}  ​  // wait until second SPI frame is received ​ 
- SPI_RcvData = SPI_RcvData + (LPC_SSP2->​DR & 0x0000FFFF);​ // add lower received SPI frame 
-  
- if (((SPI247_Buffer[SPI247_ReadBuff][1]&​0x0F) < 12)) 
- { 
- if(((SPI_RcvData&​0xFF) == SPI247_Buffer[SPI247_ReadBuff][2]) && (((SPI_RcvData>>​8)&​0xFF) == SPI247_Buffer[SPI247_ReadBuff][3]) && ​ 
- (((SPI_RcvData>>​16)&​0xFF) == SPI247_Buffer[SPI247_ReadBuff][4])) 
- temp++; 
- }  
-  
- if((SPI247_Buffer[SPI247_ReadBuff][1] & 0x0F) == 0x0C) // write to control register? 
- { 
- if ((SPI247_Buffer[SPI247_ReadBuff][2] & 0x05) == 0x05) // write to MAPENA? 
- { 
- while ((SPI_RcvData&​0x05) == 5) // wait for MAPENA 
- { 
- SPI_SendFrame((SPI247_Buffer[SPI247_ReadBuff][0] & 0x07), 0, SPI247_Buffer[SPI247_ReadBuff][1],​ SPI247_Buffer[SPI247_ReadBuff][2],​ 
- SPI247_Buffer[SPI247_ReadBuff][3],​ SPI247_Buffer[SPI247_ReadBuff][4]);​ // send SPI frame 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){}  ​    // wait until first SPI frame is received  
- SPI_RcvData = LPC_SSP2->​DR;​  ​    // received SPI frame  
- SPI_RcvData = SPI_RcvData ​ << 16; // shift first received SPI frame (higher)  
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} ​   // wait until second SPI frame is received ​ 
- SPI_RcvData = SPI_RcvData + (LPC_SSP2->​DR & 0x0000FFFF);​ // add lower received SPI frame 
-  
- } 
- } 
- } 
- os_mut_release(&​Mutspi247);​ //​ release mutex 
- } // end of while(1) 
-} 
-//​------------------------- TASK: spi247 -- (End) ---------------------------------- 
-</​code>​ 
  
 === TASK: wb, dz, bl === === TASK: wb, dz, bl ===
-Dále software obsahuje tři dočasné tasky, které se vytváří a mažou dynamicky v případě, že je daný efekt potřeba. Například pokud přijde z počítače povel pro efekt Dark Zone, task interpreter vytvoří nový task dz, který se už sám stará o odesílání příslušných dat do SPI periferie. Task s efektem se maže opět příkazem z počítače. V jednu chvíli je možné mít spuštěných i více kopií stejného tasku, které obsluhují různé obvody integrovaného budiče.+Dále software obsahuje tři dočasné tasky, které se vytváří a mažou dynamicky v případě, že je daný efekt potřeba. Konkrétně jsou implementovány funkce Wiping Blinker, Dark Zone a Bending Light. Například pokud přijde z počítače povel pro efekt Dark Zone, task interpreter vytvoří nový task dz, který se už sám stará o odesílání příslušných dat do SPI periferie. Task s efektem se maže opět příkazem z počítače. V jednu chvíli je možné mít spuštěných i více kopií stejného tasku, které obsluhují různé obvody integrovaného budiče.
 Ukázka jednoho tasku je uvedena zde: Ukázka jednoho tasku je uvedena zde:
 <code c> <code c>
Řádek 183: Řádek 120:
 __task void wb (void) __task void wb (void)
 { {
- uint8_t target = newtarget;​ //​ target device +   uint8_t target = newtarget;​ //​ target device 
- float wb_dt = 0; // time difference+   ​float wb_dt = 0; // time difference
   
- while(1) +   while(1) 
- +   ​
- wb_dt = (float)(wb_stop[target] - wb_start[target])/​12.0;​ +      wb_dt = (float)(wb_stop[target] - wb_start[target])/​12.0;​
   
- if (wb_counter[target] >= wb_per[target]) //​ counter overflow +      ​if (wb_counter[target] >= wb_per[target]) //​ counter overflow 
- wb_counter[target] = 0; +         ​wb_counter[target] = 0; 
- else +      else 
- wb_counter[target]++;​ // increment counter+         ​wb_counter[target]++;​ // increment counter
   
   
- if (wb_counter[target] < wb_start[target]) //​ all LEDs OFF +      ​if (wb_counter[target] < wb_start[target]) //​ all LEDs OFF 
- +      
- for (i=0; i<12; i++) +         ​for (i=0; i<12; i++) 
- +         ​
- DCs[i] = 1023; +            DCs[i] = 1023; 
- +         ​
- j=0; +         ​j=0; 
- +      
- else if (wb_counter[target] < wb_stop[target]) //​all LEDs dimmed +      else if (wb_counter[target] < wb_stop[target]) //​all LEDs dimmed 
- {  +      {  
- for (i=0; i<12; i++) +         ​for (i=0; i<12; i++) 
- +         ​
- if (wb_counter[target] < (wb_start[target] + i*wb_dt)) +            if (wb_counter[target] < (wb_start[target] + i*wb_dt)) 
- DCs[i] = 1023; +               ​DCs[i] = 1023; 
- else if (wb_counter[target] < (wb_start[target] + (i+1)*wb_dt)) +            else if (wb_counter[target] < (wb_start[target] + (i+1)*wb_dt)) 
- DCs[i] = (wb_start[target] + (i+1)*wb_dt - wb_counter[target])/​wb_dt*1023;​ +               ​DCs[i] = (wb_start[target] + (i+1)*wb_dt - wb_counter[target])/​wb_dt*1023;​ 
- else  +            else  
- DCs[i] = 0; +               ​DCs[i] = 0; 
- }  +         ​}  
- +      
- else // all LEDs ON +      else // all LEDs ON 
- +      
- for (i=0; i<12; i++) +         ​for (i=0; i<12; i++) 
- +         ​
- DCs[i] = 0; +            DCs[i] = 0; 
- +         ​
- }+      }
   
- dimming(DCs,​ LEDcount, ON, OFF, TR, lastLevel[target]);​ //​ ON, OFF, TR values computation using Dimming algorithm+      ​dimming(DCs,​ LEDcount, ON, OFF, TR, lastLevel[target]);​ //​ ON, OFF, TR values computation using Dimming algorithm
   
- os_mut_wait(&​Mutspi247,​ 0xFFFF);​ //​ wait for mutex+      ​os_mut_wait(&​Mutspi247,​ 0xFFFF);​ //​ wait for mutex
   
- SPI_SendFrame(target + 3, 1, 0xCF, 0, 0, 0); // send SPI frame to pixel light+      ​SPI_SendFrame(target + 3, 1, 0xCF, 0, 0, 0); // send SPI frame to pixel light
   
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received  +      ​while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received  
- SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data +      SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received  +      while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received  
- SPI_RcvData += LPC_SSP2->​DR;​ // sum received data +      SPI_RcvData += LPC_SSP2->​DR;​ // sum received data
   
- SPI_SendFrame(target + 3, 1, 0xCC, ((SPI_RcvData)&​(0xFB)),​ (SPI_RcvData>>​8)&​0xFF,​ (SPI_RcvData>>​16)&​0xFF);​  +      ​SPI_SendFrame(target + 3, 1, 0xCC, ((SPI_RcvData)&​(0xFB)),​ (SPI_RcvData>>​8)&​0xFF,​ (SPI_RcvData>>​16)&​0xFF);​  
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received +      while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data +      SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received +      while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- SPI_RcvData += LPC_SSP2->​DR;​ // sum received data +      SPI_RcvData += LPC_SSP2->​DR;​ // sum received data
   
- for(i=0; i<12; i++) // send ON, OFF and TR values to pixel light +      ​for(i=0; i<12; i++) // send ON, OFF and TR values to pixel light 
- +      
- SPI_SendFrame(target + 3, 1, i + 0xC0, ((OFF[i]<<​4)+TR[i])&​0xFF,​ ((ON[i]<<​6)+(OFF[i]>>​4))&​0xFF,​ (ON[i]>>​2)&​0xFF); ​  +         ​SPI_SendFrame(target + 3, 1, i + 0xC0, ((OFF[i]<<​4)+TR[i])&​0xFF,​ ((ON[i]<<​6)+(OFF[i]>>​4))&​0xFF,​ (ON[i]>>​2)&​0xFF); ​  
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received +         ​while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data +         ​SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received +         ​while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- SPI_RcvData += LPC_SSP2->​DR;​ // sum received data  +         ​SPI_RcvData += LPC_SSP2->​DR;​ // sum received data  
- }+      }
   
- SPI_SendFrame(target + 3, 1, 0xCC, ((SPI_RcvData)&​0xFF)|(1<<​2),​ (SPI_RcvData>>​8)&​0xFF,​ (SPI_RcvData>>​16)&​0xFF);​ //​set MAPENA bit +      ​SPI_SendFrame(target + 3, 1, 0xCC, ((SPI_RcvData)&​0xFF)|(1<<​2),​ (SPI_RcvData>>​8)&​0xFF,​ (SPI_RcvData>>​16)&​0xFF);​ //​set MAPENA bit 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received +      while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data +      SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ // shift received data 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received +      while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- SPI_RcvData += LPC_SSP2->​DR;​ // sum received data +      SPI_RcvData += LPC_SSP2->​DR;​ // sum received data
   
- os_mut_release(&​Mutspi247);​ // release mutex+      ​os_mut_release(&​Mutspi247);​ // release mutex
   
- os_dly_wait(20);​+      ​os_dly_wait(20);​
   
- } // end while(1)+   } // end while(1)
 } }
 //​--------------------------- TASK: wb -- (End) ----------------------------------- //​--------------------------- TASK: wb -- (End) -----------------------------------
 </​code>​ </​code>​
 +
 +
 +
 +
 +==== Návrh na úpravy ====
 +Operační systém reálného času RTX je komplexní a velmi rozsáhlý nástroj, proto bez větších zkušeností je velký problém využít všechny jeho možnosti a vytvořit dobře optimalizovaný program. Taky proto byl kladen důraz na jednoduchost a využití pouze základních možností RTX, aby nedošlo k zamotání do různých funkcí a možností. Mezi další možnosti, které systém RTX podporuje, jsou mailboxy, signály a události, tak by jistě stálo za zvážení, zda by programu pomohly.
 +
 +===== Ukázka funkce =====
 + 
 +{{youtube>​keJ7lECmeH4?​medium}}
 +
 +===== Zdrojové soubory =====
 +Zdrojová data nejsou z důvodu ochrany duševního vlastnictví společnosti ON Semiconductor zcela zveřejněna. V rámci zdrojových souborů je možné najít nastavení RTX souborem RTX_Conf_CM.c. Dále jsou ve zdrojovém souboru main.c zveřejněny všechny tasky a jejich provázání,​ pouze pár menších částí bylo vyjmuto, které ale nemají vliv na fungování RTOS. Dále je v přiloženém balíku zveřejněno schéma desky s mikrokontrolérem. {{:​2014:​pixel-light:​mpoa_pixellight.zip|}}
 +
 +    ​
 +===== Závěr =====
 +Naprogramovaný software je plně funkční, což je možné vidět i na ukázkovém videu níže. Nastavené časové údaje u ukázkových funkcí odpovídají skutečnosti,​ a proto je možné tvrdit, že časování v RTOS funguje podle požadavků. V softwaru je navíc implementovaná kontrola přetečení zásobníků jednotlivých tasků. Při testování softwaru bylo ověřeno, že aktuálně nastavená hodnota velikosti zásobníků 512 B je dostatečná. ​
2014/pixel-light.1421441682.txt.gz · Poslední úprava: 2015/01/16 21:54 autor: Pavel Kostelník