Elektroda.pl
Elektroda.pl
X
CControls
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

PIC32mx150f128b - program U_Tube z książki Exploring Pic32

PeterBernard314 16 Maj 2013 18:44 3300 11
  • #1 16 Maj 2013 18:44
    PeterBernard314
    Poziom 15  

    Witam, przenoszę program, jak w temacie, pierwotnie uruchomiony na pic32mx360f512. Jak narazie nie rozwiązałem następujących problemów:

    a) nie potrafię spowodować aby SPI1 startował z impulsem wyzwalającym w trybie framed slave mode. Pin wejścia SS1 przydzielony, impulsy na pinie widoczne na oscyloskopie, a transmisji przez SPI brak.

    b)Łańcuchowanie aktywności DMA sprawia wrażenie jakoby oba DMA 0 i 1 startowały równocześnie, a nie zerowy startował jako następca pierwszego.

    Code:


    #pragma config POSCMOD=XT, FNOSC=PRIPLL, FSOSCEN=OFF, IESO=OFF
    #pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_16, FPLLODIV=DIV_1 //64MHz
    #pragma config FWDTEN=OFF//, FPBDIV=DIV_2//, JTAGEN=OFF //, ICESEL=ICS_PGx1

    #include <p32xxxx.h>
    #include <plib.h>
    #include <math.h>

    Void Initialize (void){

        ANSELA = 0;
        ANSELB = 0; //all ports digital
        TRISA = 0x00;
        TRISB = 0x00;//84;//84-dodatkowe wymuszenie pinów jako wejscia
        LATA = 0;
        LATB = 0;// */
        // fist stop dma and ISRs
        SYSKEY = 0x12345678; // ensure syskey is locked
        SYSKEY = 0xAA996655; // Write Key1 to SYSKEY
        SYSKEY = 0x556699AA; // Write Key2 to SYSKEY
        // Composite Video Out
        SS1R  = 4; //RPB7 = SS1 input
        RPB8R = 3; //RPB8 = SDO1
        RPB9R = 5; //RPB9 = OC3
        // SD MC
        RPA1R = 4; //RPA1 = SDO2
        SDI2R = 4; //RPB2 = SDI2 // B15 = SCK2
        // Audio PWM
        RPB4R = 5; // OC1
        RPB5R = 5; // OC2
        // Relock the SYSKEY
        SYSKEY = 0x0; // Write any value other than Key1 or Key2

    } // initialize

    #define VRES 200 // desired vertical resolution
    #define HRES 256//256 // desired horizontal resolution pixel
    //#define DOUBLE_BUFFER // comment if single buffering required

    #define LINE_N 312 // number of lines in PAL frame
    #define LINE_T 4096 // 4096Tpb clock in a line (64us)

    // count the number of remaining black lines top+bottom
    #define VSYNC_N 3 // V sync lines
    #define VBLANK_N (LINE_N -VRES -VSYNC_N)
    #define PREEQ_N VBLANK_N/2 // preeq + bottom blank
    #define POSTEQ_N VBLANK_N -PREEQ_N // posteq + top blank
    // definition of the vertical sync state machine
    #define SV_PREEQ 0
    #define SV_SYNC 1
    #define SV_POSTEQ 2
    #define SV_LINE 3
    // timing for composite video horizontal state machine
    #define PIX_T 8 // Tpb clock per pixel
    #define HSYNC_T 300// 180 //300 // Tpb clock width horizontal pulse
    #define BPORCH_T 660//340 //666 // Tpb clock width back porch





    #define Home() { cx=0; cy=0;}
    #define Clrscr() { clearScreen(); Home();}
    #define AT( x, y) { cx = (x); cy =(y);}

    int VMap1[ VRES*(HRES / 32)]; // image buffer
    #ifdef DOUBLE_BUFFER
    int VMap2[ VRES*(HRES / 32)]; // second image buffer
    #endif

    int *VA = VMap1; // pointer to the Active VMap
    #ifdef DOUBLE_BUFFER
    int *VH = VMap2;
    #else
    int *VH = VMap1;
    #endif

    volatile int *VPtr;
    volatile short VCount;
    volatile short VState;
    // next state table
    short VS[4] = {SV_SYNC, SV_POSTEQ, SV_LINE, SV_PREEQ};
    // next counter table
    short int VC[4] = {VSYNC_N, POSTEQ_N, VRES, PREEQ_N};
    int zero[2] = {0x0f0f,0xf0f0};//{0xAA, 0x55};//{0,0}; //

    short cx, cy; //  <=========== dostawilem

    void __ISR(_TIMER_3_VECTOR, ipl7SOFT) T3Interrupt(void)
    {// advance the state machine
        if (--VCount == 0) {
            VCount = VC[ VState & 3];
            VState = VS[ VState & 3];   }
        // vertical state machine
        switch (VState) {
            case SV_SYNC: // 1
                // vertical sync pulse
                OC3R = LINE_T - HSYNC_T - BPORCH_T;
                break;
            case SV_POSTEQ: // 2
                // horizontal sync pulse
                OC3R = HSYNC_T;
                break;
            case SV_PREEQ: // 0
                // prepare for the new frame
                VPtr = VA;
                break;
            default:
            case SV_LINE: // 3
                // preload of the SPI waiting for SS (Synch high)
           SPI1BUF = 0;//xAA559911;
                // update the DMA0 source address and enable it
                DCH0SSA = KVA_TO_PA((void*) VPtr);
      // DmaChnSetTxfer(0, (void*) VPtr, (void *) & SPI1BUF, HRES / 8, 4, 4);
                VPtr += HRES / 32;
                DmaChnEnable(1);
                break;
        } //switch
        // clear the interrupt flag
        mT3ClearIntFlag();
    } // T3Interrupt

    void initVideo(void) {
    // 1. init the SPI1 select framed slave mode to synch SPI with OC3
        SpiChnOpen (1, SPICON_ON | SPICON_MSTEN | SPICON_MODE32, PIX_T);
                  //| SPICON_FRMEN | SPICON_FRMSYNC | SPICON_FRMPOL, PIX_T);
    // 2. make SS1 a digital input // allready in initialize
    // 3. init OC3 in single pulse, continuous mode
        OpenOC3 (OC_ON | OC_TIMER3_SRC | OC_CONTINUE_PULSE, 0, HSYNC_T);
    // 4. Timer3 on, prescaler 1:1, internal clock, period
        OpenTimer3 (T3_ON | T3_PS_1_1 | T3_SOURCE_INT, LINE_T - 1);
    // 5. init the vertical sync state machine
        VState = SV_LINE;
        VCount = 1;
    // 6. init the active and hidden screens pointers
        VA = VMap1;
    #ifdef DOUBLE_BUFFER
        VH = VMap2;
    #else
        VH = VA;
    #endif
    // 7. DMA 1 configuration back porch extension
        DmaChnOpen (1, 1, DMA_OPEN_DEFAULT);
        DmaChnSetEventControl(1, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_SPI1_TX_IRQ));
        DmaChnSetTxfer(1, (void*) zero, (void *) & SPI1BUF, 8, 4, 4);
    // 8. DMA 0 configuration image serialization
        DmaChnOpen (0, 0, DMA_OPEN_DEFAULT);
        DmaChnSetEventControl(0, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_SPI1_TX_IRQ));
        DmaChnSetTxfer(0, (void*) VPtr, (void *) & SPI1BUF, HRES / 8, 4, 4);
    // chain DMA0 to completion of DMA1 transfer
        DmaChnSetControl(0, DMA_CTL_CHAIN_EN | DMA_CTL_CHAIN_DIR);
    // 9. Enable Timer3 Interrupts
    // set the priority level 7 to use shadow register set
    mT3SetIntPriority( 7);
    mT3IntEnable( 1);
    } // initVideo



    W powyższym programie procesor jest przetaktowany do 64MHz, ale opisane problemy nie ustępują dla taktowania dopuszczonego specyfikacją, ani gdy Fpb=Fck/2.

    Pozdrawiam i poszę o poradę :)

    0 11
  • CControls
  • #2 16 Maj 2013 20:13
    94075
    Użytkownik usunął konto  
  • #3 16 Maj 2013 21:20
    PeterBernard314
    Poziom 15  

    Komentarz w trzecim wierszu cytatu jest mojego autorstwa i jest to wytrych-obejście, który spowodował, że SPI transmituje od razu po wejsciu w przerwanie T3 bez czekania na zakończenie impulsu synchronizacji poziomej generowanego przez OC3; przepraszam za nie skomentowanie tego faktu. Gdy uruchomię framed slave mode, tak jak jest w oryginale, SPI nie jest inicjowane przez wysoki stan wyjścia OC3. Kolejna ciekawostka: samo zadeklarowanie remapable pinu na SS1input nie przełącza tego pinu jako wejście. Pin jest cyfrowy wyjściowy zgodnie z deklaracjami w initialize. Wiem to z tąd, że pin ten zwiera impulsy za rezystorem łączącym OC3 z SS1 - sprawdzone oscyloskopem. Dopiero zadeklarowanie pinu jako wejscia cyfrowego: TRISB = 0x0084;// PB7 & PB2 jako wejścia, powoduje że pin ten nie zwiera i impulsy na nodze SS1 widzę na oscylu. W specyfikacji proca napisano, że uaktywnienie peryferii jest nadrzędne ponad deklarację jako pinu cyfrowego typu gpio. Skoro tak to SPI przełączy funkje pinu z GPIO na SS1 dopiero gdy SPI zostanie uaktywnione przez zapis wartości do portu wyjścia, ale w programie zakładamy że to SPI ma się uaktywnić dopiero po otrzymaniu impulsu z pinu SS1 w trybie framed slave z czego wnioskuję, że taka kombinacja jest w serii mx1xx2xx niewykonalna poprzez fakt ze pin SS1 przejdzie w funkcjonowanie jako przynależny do SPI odpiero po zainicjowaniu transmisji przez SPI. To akurat nie jest problem, gdyż początek treści linii mogę regulować ilością przesyłanych 0x0000 za początkiem impulsu synchronizacji poziomej.

    Jednoczesny start obu transmisji DMA wnioskuję po wygenerowanym obrazie. Jak widzisz w moim kodzie wektor zero, który powinien w istocie przechowywać wartości 0,0 wypełniłem 0f0f,f0f0, gdyż na początku zmagania się z tym programem badałem oscylem co i gdzie się pojawi; na tamtym etapie monitor tv nic jeszcze nie pokazywał. Po uruchomieniu SPI na siłę co powyżej opisałem, wartości f0f0 pokazują mi na ekranie gdzie kończy się transmisja z wektora zero realizowana przez DMA1 i zaraz za nią zaczyna się transmisja treści linii obrazu realizowana przez DMA0. I właśnie w tym momencie widzę, że w treści linii brakuje mi 64 pierwszych bitów, z tąd wnioskuję, że DMA0 zjada mi dwa pierwsze słowa tak jakby startował równocześnie z DMA1. Ja nie twierdzę, że tak jest na 100%, gdyż błąd może tkwić gdzie indziej.

    Przed chwilą sprawdziłem że brakuje pierwszych 32 bitów treści linii, a nie 64-ech które omyłkowo odczytałem jeszcze z oscyloskopu.
    Procesor jest podkręcony na 64MHz co przekracza 50MHz specyfikacje, lecz opisane problemy występują takoż przy 48MHz oraz Fpb=Fck/2.

    0
  • #4 17 Maj 2013 01:42
    94075
    Użytkownik usunął konto  
  • CControls
  • #5 17 Maj 2013 08:33
    PeterBernard314
    Poziom 15  

    Witaj, tak właśnie chciałem skonfigurować, lecz zbiór pinów możliwych do przydzielenia jako wyjście OC3 nie ma części wspólnej ze zbiorem pinów możliwych do przydzielenia jako wejście SS1, z tąd rezystor między nimi.

    Tylko pary funkcji pinów wybranych z czterech poniższych grup umożliwiają bezpośrednie połączenie digital out => digital In:

    {u1tx,u2rts,ss1,oc1,c2out} => [A0,B3,B4,B15,B7,C7,C0,C5] => {int4,t2ck,ic4,ss1,refclk1}
    {sdo1, sdo2, oc2, c3out} => [A1,B5,B1,B11,B8,A8,C8,A9] => {int3,t3ck,ic3,u1cts,u2rx,sdi1}
    {sdo1,sdo2,oc4,oc5,refclk0} => [A2,B6,A4,B13,B2,C6,C1,C3] => {int2,t4ck,ic1,ic5,u1rx,u2cts,sdi2,ocfb}
    {u1rts,u2tx,ss2,oc3,c1out} => [A3,B14,B0,B10,B9,C2,C4] => {int1,t5ck,ic2,ss2,ocfa}

    Teraz patrze, że SS2 jest w tej samej grupie co OC3 więc może zamienie na SPI2. Ale to nie jest problem, najbardziej zależy mi na odnalezieniu przyczyny znikania pierwszych 32 bitów treści linii

    Cytat:
    A na mnie autor książki sprawia wrażenie bardziej kompetentnego.
    I zdania nie zmienię dopóki nie opiszesz skąd to Twoje wrażenie.

    Ja nie kwestionuję kompetencji autora książki, zmagam się jednakowoż z problemami przeniesienia kodu pierwotnie uruchomionego na 360f512, gdzie zakładam, że wszystko działało perfecto & picobello.

    W środowisku Mplab-X 1.70 z XC 1.21 kompilator czepiał się do oryginalnego kodu. Po wyczyszczeniu, symulator pokazywał prawidłowe działanie na procu 340f256h. Po zmianie na 150f128 kompilator stwierdził szereg niezgodności pinologicznych co było oczywiste, po korekcie, w symulatorze program się zawieszał na nieokreślonym adresie, a bedugowanie na procku wywalało sie do obsługi przerwania exception handlera. przyczyną okazał się brak opcji SOFT w deklaracji: void __ISR(_TIMER_3_VECTOR, ipl7SOFT) T3Interrupt(void). Po tej zmianie V-state machine ruszyła bezbłędnie.

    Jak widać małe pice32 niosą szereg wyzwań z przeośnością. Będę próbował na serii MX3xx, czy oryginał zadziała bez problemu.


    Piotr

    0
  • #6 20 Maj 2013 08:51
    94075
    Użytkownik usunął konto  
  • #7 20 Maj 2013 13:24
    PeterBernard314
    Poziom 15  

    Witaj, uruchamiam selektywnie, przetestowałem dodatkowe bity konfigurujące w SPI1CON i SPI1CON2,ale nie wszystkie dopuszczalne kombinacje :) W ani jednej sytuacji SPI nie ruszył od impulsu framed sync. Pewnym tropem jest fakt, że samo włączenie framed sync w SPICONF nie przełącza zadeklarowanego remapable pinu z GPIOout na SS1in. Dopiero zadeklarowanie tego pinu w TRISB jako GPIO input, powoduje że nie zwiera podawanych impulsów. Na razie odpuściłem debugowanie tej funkcji gdyż ten sam efekt można osiągnąć wysyłając więcej zerowych bitów od początku H-syncu. Natomiast gubienie pierwszego sława transmisji DMA0 jest znacznie bardziej denerwujące.

    0
  • #8 20 Maj 2013 14:39
    94075
    Użytkownik usunął konto  
  • #9 20 Maj 2013 15:12
    PeterBernard314
    Poziom 15  

    Ok,zrozumiałem, a właściwie dopiero teraz skojarzyłem ze schematem blokowym gpio pinu, co nie zmienia faktu, że transmisja spi nadal nie startuje po impulsie podanym na zadeklarowany ss1 z gpio jako input w trybie framed sync.

    0
  • #10 23 Maj 2013 10:31
    PeterBernard314
    Poziom 15  

    Brak pierwszego słowa transmisji dma rozwiązałem następująco:
    Wiersz: DCH0SSA = KVA_TO_PA((void*) VPtr );
    Zmiana: DCH0SSA = KVA_TO_PA((void*) ( VPtr - 1 ));

    Wiersz: DmaChnSetTxfer(0, (void*) VPtr, (void *) & SPI1BUF, HRES/8, 4, 4);
    Zmiana: DmaChnSetTxfer(0, (void*) VPtr, (void *) & SPI1BUF, ( 4 + HRES/8 ), 4, 4);

    Najprawdopodobniej dma w małych picach32 ma przesunięte o 1 adresowanie i liczenie, być może zamieniono post inc/dec na pre inc/dec albo odwrotnie. Przypuszczalnie też, Mchp mógł zmienić biblioteki. Oryginał był wszakże uruchamiany 3 lata temu. Gdy sprawdzę na 460f512 się okaże.

    Rozwiązanie znalazłem doświadczalnie zastanawiając się nad logiką problemu, bez wgłębiania się w DS.

    Problem framed sync jeszcze nierozwiązany choć dla tego programu to nie problem.

    Na poniższym schemacie SS1 steruje V-Synciem dla VGA, a nie framed sync input, choć w treści programu jeszcze jest zadeklarowany jako fr-sync-inp, co nie przeszkadza. Aby nie było wątpliwości, w trakcie wszystkich prób zmierzających do uruchomienia trybu framed sync, pin SS1 był połączony rezystorem k82 z pinem OC3. Trybu VGA jeszcze nie uruchomiłem, ani systemu plików ani PWM Audio.

    PIC32mx150f128b - program U_Tube z książki Exploring Pic32

    Poniżej działający U-Tube z fraktalem Mandelbrota, o rozdzielczości 256x200 na wyjściu composite Video (nie wytestowane podwójne buforowanie ekranu).

    Tutaj strona źródłowa.

    0
  • #11 24 Maj 2013 14:20
    94075
    Użytkownik usunął konto  
  • #12 24 Maj 2013 14:54
    PeterBernard314
    Poziom 15  

    Tak zlikwidowałem ten komentarz za którymś przeglądaniem kodu, i nic nie dało.
    A Jtag i tak był wyłączany tym:

    #ifndef PIC32_STARTER_KIT
    mJTAGPortEnable(0);
    #endif

    Na 460f512 oryginalny program skompilowany przez C32 v2.02, nie uruchamia modułu DMA. V-State Machine działa, pierwsza transmisja SPI wychodzi, po czym nie wychodzą dane z wektora zero, z czego wnioskuję, że dma1 nie odpala od przerwania SPI1TX. No i oczywiście nie wiem czemu :|

    0