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:40]
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í.
  
-<code c>  +=== TASK: wb, dz, bl === 
-//​------------------------- TASK: spi247 ​-- (Begin) -------------------------------- +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. 
-// SPI communication with pixel light +Ukázka jednoho tasku je uvedena zde: 
-__task void spi247 ​(void) +<code c> 
-{    +//-------------------------- TASK: wb -- (Begin) ​---------------------------------- 
- while(1) +// LED effect - Wiping blinker  
-+__task void wb (void) 
- os_sem_wait(&​Semspi247,​ 0xFFFF); ​            // wait for data (driven by semaphore) +{ 
- SPI247_ReadBuff ​(SPI247_ReadBuff+1) & (BUFFERSPISIZE - 1); +   ​uint8_t target ​newtarget; // target device 
- os_mut_wait(&​Mutspi247,​ 0xFFFF); ​       ​// wait for mutex +   float wb_dt = 0;  // time difference 
- 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(1) 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until first SPI frame is received  +   
- SPI_RcvData ​LPC_SSP2->​DR;​  ​        // received SPI frame  +      ​wb_dt ​= (float)(wb_stop[target] ​wb_start[target])/12.0;
- 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 +      if (wb_counter[target] >= wb_per[target]) // counter overflow 
- UART_SendFrame (0x01);                 ​// send identification frame to PC +         wb_counter[target] = 0; 
- UART_SendFrame ​(SPI247_Buffer[SPI247_ReadBuff][0]); // send target device +      else 
- UART_SendFrame ​(SPI_RcvData&​0xFF);     ​// send 1. byte (lowest+         ​wb_counter[target]++;​ // increment counter 
- 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+      if (wb_counter[target< wb_start[target]) // all LEDs OFF 
- os_mut_release(&​Mutuart_tx);           ​// release mutex +      { 
 +         ​for ​(i=0; i<12; i++) 
 +         { 
 +            DCs[i] = 1023; 
 +         } 
 +         ​j=0;​ 
 +      } 
 +      else if (wb_counter[target] < wb_stop[target]) //all LEDs dimmed 
 +      {  
 +         ​for ​(i=0; i<12; i++
 +         { 
 +            if (wb_counter[target] < (wb_start[target] + i*wb_dt)) 
 +               ​DCs[i] = 1023
 +            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; 
 +            else  
 +               ​DCs[i] = 0; 
 +         ​}  
 +      } 
 +      else // all LEDs ON 
 +      { 
 +         ​for ​(i=0; i<12; i++
 +         { 
 +            DCs[i] = 0; 
 +         } 
 +      } 
 +  
 +      dimming(DCs, LEDcount, ON, OFF, TR, lastLevel[target]); // ON, OFF, TR values computation using Dimming algorithm
   
- SPI_SendFrame((SPI247_Buffer[SPI247_ReadBuff][0] ​0x07)0, (SPI247_Buffer[SPI247_ReadBuff][1] & 0xF0) + 0x0F, 0, 0, 0); +      os_mut_wait(&Mutspi2470xFFFF); // wait for mutex
- 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)) +      SPI_SendFrame(target + 3, 1, 0xCF, 0, 0, 0); // send SPI frame to pixel light
-+
- 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? +      while ((LPC_SSP2->​SR ​0x4)== 0x0){} // wait until frame is received ​ 
- { +      ​SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ //​ shift received data 
- if ((SPI247_Buffer[SPI247_ReadBuff][2] ​0x05) == 0x05) // write to MAPENA? +      ​while ​((LPC_SSP2->​SR ​0x4)== 0x0){} // wait until frame is received ​ 
- { +      ​SPI_RcvData += LPC_SSP2->​DR;​ //​ sum received data  
- while ((SPI_RcvData&​0x05) == 5) // wait for MAPENA +  
- { +      SPI_SendFrame(target + 3, 1, 0xCC, ((SPI_RcvData)&​(0xFB)),​ (SPI_RcvData>>​8)&​0xFF,​ (SPI_RcvData>>​16)&​0xFF);​  
- SPI_SendFrame((SPI247_Buffer[SPI247_ReadBuff][0] & 0x07), 0SPI247_Buffer[SPI247_ReadBuff][1]SPI247_Buffer[SPI247_ReadBuff][2], +      ​while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- SPI247_Buffer[SPI247_ReadBuff][3], SPI247_Buffer[SPI247_ReadBuff][4]); // send SPI frame +      ​SPI_RcvData ​= (LPC_SSP2->​DR)<<​16;​ //​ shift received data 
- while ((LPC_SSP2->​SR & 0x4)== 0x0){}      // wait until first SPI frame is received ​  +      while ((LPC_SSP2->​SR ​0x4)== 0x0){} // wait until frame is received 
- SPI_RcvData = LPC_SSP2->​DR;​      // received ​SPI frame  +      ​SPI_RcvData += LPC_SSP2->​DR;​ //​ sum received data  
- SPI_RcvData ​= SPI_RcvData  ​<< 16;  // shift first received SPI frame (higher)  +  
- while ((LPC_SSP2->​SR & 0x4)== 0x0){} ​    // wait until second SPI frame is received  +      for(i=0; i<12; i++) // send ONOFF and TR values to pixel light 
- SPI_RcvData = SPI_RcvData + (LPC_SSP2->​DR ​& 0x0000FFFF); // add lower received ​SPI frame +      { 
-  +         ​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 
- } +         ​SPI_RcvData = (LPC_SSP2->​DR)<<​16;​ //​ shift received data 
- +         ​while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
- os_mut_release(&​Mutspi247);​ // release mutex +         ​SPI_RcvData ​+= LPC_SSP2->​DR;​ // sum received ​data  
- } // end of while(1)+      } 
 +  
 +      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 
 +      SPI_RcvData = (LPC_SSP2->​DR)<<16; // shift received ​data 
 +      while ((LPC_SSP2->​SR & 0x4)== 0x0){} // wait until frame is received 
 +      SPI_RcvData += LPC_SSP2->​DR;​ //​ sum received data  
 +  
 +      os_mut_release(&​Mutspi247);​ // release mutex 
 +  
 +      os_dly_wait(20);​ 
 +  
 +   } // end while(1)
 } }
-//​------------------------- TASK: spi247 ​-- (End) ----------------------------------+//--------------------------- TASK: wb -- (End) -----------------------------------
 </​code>​ </​code>​
  
-=== TASK: wb, dz, bl === + 
-Dále software obsahuje ​dočasné tasky, které ​se vytváří ​mažou dynamicky v případě, že je daný efekt potřebaNapříklad pokud přijde z počítače povel pro efekt Dark Zonetask interpreter vytvoří nový task dz, který se už sám stará o odesílání příslušných dat do SPI periferie. Task 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 taskukteré obsluhují různé obvody integrovaného budiče.+ 
 + 
 +==== 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 ​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 vyjmutokteré ale nemají vliv na fungování RTOS. Dále je v přiloženém balíku zveřejněno schéma desky 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, žaktuálně nastavená hodnota velikosti zásobníků 512 B je dostatečná
2014/pixel-light.1421440800.txt.gz · Poslední úprava: 2015/01/16 21:40 autor: Pavel Kostelník