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

[LPC2148]uruchomienie ramu USB DMA

rusala 14 Wrz 2009 12:39 1538 14
  • #1 14 Wrz 2009 12:39
    rusala
    Poziom 22  

    Witam. Mam problem z uruchomieniem dodatkowych 8KB RAMu w LPC2148. Zrobilem juz stosowne przerobki w linkerze plus czyszczenie sekcji tego ramu tak jak sekcji bss w startupie. Kompilator sekcje widzi i wszystko jest niby Ok oprocz tego, ze zadne zmienne nie zapisuja swojej wartosci. Problem w tym ze ow RAM trzeba wlaczyc. Po przeszukaniu kilku przykladow z NXP stwierdzam, ze nigdzie nie napisano wprost jak to zrobic gdyz wszystkie przykladu opieraja sie czesciowo o "pomoc" ze strony srodowiska w jakim zostaly napisane lub fragment kodu opiera sie o definicje, ktore sa w plikach, ktorych nie udostepniono itp. itd.

    Dlatego bardzo prosze osoby, ktore juz to przerabialy o krotka zwiezla odpowiedz jak ten #$%^& RAM wlaczyc.

    0 14
  • #2 14 Wrz 2009 12:50
    Freddie Chopin
    Specjalista - Mikrokontrolery

    LPC214x User Manual > Chapter 14: USB device controller > 10. USB device controller initialization:

    Cytat:
    1. Turn on USB PCLK in PCONP register.


    ?

    4\/3!!

    0
  • #3 14 Wrz 2009 12:54
    rusala
    Poziom 22  

    no popatrz w moim manualu takiego zdania niema ;-) Ale jest cos zdajsie przy power control zaraz obadam

    OK dorzucilem do PCONP jedynke na bicie 31 i wyglada, ze dziala. Ale w moim zekomo najnowszym manualu jest na ten temat tyle: PUSB USB power/clock control bit.

    0
  • Pomocny post
    #4 14 Wrz 2009 13:15
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Jaką masz wersję? U mnie na pierwszej stronie:

    Cytat:
    UM10139
    Volume 1: LPC214x User Manual
    Rev. 02 — 25 July 2006 User manual LPC214x


    4\/3!!

    0
  • #5 14 Wrz 2009 13:25
    markosik20
    Poziom 33  

    Możesz wrzucić tutaj ten skrypt linkera.

    0
  • #6 14 Wrz 2009 13:25
    rusala
    Poziom 22  

    ja mam z 2005 ale na stronie NXP w dokumentacji procka jest tylko ta. Moze w domu mam nowsza ciekawe az sprawdze pozniej.

    A teraz mam inne ciekawe zjawisko. jak uzywam tablicy zadeklarowanej w tej przestrzeni do instrukcji IAP to dziala dobrze przy odczycie z pamieci kodu a przy zapisie juz nie. Czyzby nie dzialalo przy wylaczonej PLLce ?

    0
  • #7 14 Wrz 2009 13:32
    Freddie Chopin
    Specjalista - Mikrokontrolery

    @markosik:

    Taki skrypt to coś w stylu:

    Code:

    /******************************************************************************
    * file: ext_demo.ld
    * last change: 2009-09-14
    *
    * chip: STM32F103VB
    * compiler: arm-none-eabi-gcc 4.3.3
    *
    * description:
    * linker script for STM32F103VB chip (128kB Flash, 20kB SRAM) and demo of
    * additional section of 8k at 0x40000000
    ******************************************************************************/

    SEARCH_DIR(.);

    /*
    +=============================================================================+
    | format configurations
    +=============================================================================+
    */

    OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm");
    OUTPUT_ARCH(arm);

    /*
    +=============================================================================+
    | stacks sizes
    +=============================================================================+
    */

    __main_stack_size = 1024;
    __process_stack_size = 1024;

    PROVIDE(__main_stack_size = __main_stack_size);
    PROVIDE(__process_stack_size = __process_stack_size);

    /*
    +=============================================================================+
    | available memories definitions
    +=============================================================================+
    */

    MEMORY
    {
       rom (rx)   : org = 0x08000000, len = 128k
       ram (rwx)   : org = 0x20000000, len = 20k
       xxx_memory (rwx) : org = 0x40000000, len = 8k
    }

    __rom_start = ORIGIN(rom);
    __rom_size = LENGTH(rom);
    __rom_end = __rom_start + __rom_size;

    __ram_start = ORIGIN(ram);
    __ram_size = LENGTH(ram);
    __ram_end = __ram_start + __ram_size;

    __xxx_memory_start = ORIGIN(xxx_memory);
    __xxx_memory_size = LENGTH(xxx_memory);
    __xxx_memory_end = __xxx_memory_start + __xxx_memory_size;

    PROVIDE(__rom_start = __rom_start);
    PROVIDE(__rom_size = __rom_size);
    PROVIDE(__rom_end = __rom_end);

    PROVIDE(__ram_start = __ram_start);
    PROVIDE(__ram_size = __ram_size);
    PROVIDE(__ram_end = __ram_end);

    PROVIDE(__xxx_memory_start = __xxx_memory_start);
    PROVIDE(__xxx_memory_size = __xxx_memory_size);
    PROVIDE(__xxx_memory_end = __xxx_memory_end);

    /*
    +=============================================================================+
    | entry point
    +=============================================================================+




    */

    ENTRY(Reset_Handler);

    /*
    +=============================================================================+
    | put data in sections
    +=============================================================================+
    */

    SECTIONS
    {
       .text :
       {
          __text_start = .;
          PROVIDE(__text_start = __text_start);

          KEEP(*(.vectors));
          *(.text .text.* .gnu.linkonce.t.*);
          *(.glue_7t) *(.glue_7);
          *(.rodata .rodata.* .gnu.linkonce.r.*);
          *(.ARM.extab* .gnu.linkonce.armextab.*);
          *(.gcc_except_table);
          *(.eh_frame_hdr);
          *(.eh_frame);
          . = ALIGN(4);
          KEEP(*(.init));
          . = ALIGN(4);
          __preinit_array_start = .;
          KEEP(*(.preinit_array));
          __preinit_array_end = .;
          . = ALIGN(4);
          __init_array_start = .;
          KEEP(*(SORT(.init_array.*)));
          KEEP(*(.init_array));
          __init_array_end = .;
          . = ALIGN(4);
          KEEP(*(.fini));
          . = ALIGN(4);
          __fini_array_start = .;
          KEEP(*(.fini_array));
          KEEP(*(SORT(.fini_array.*)));
          __fini_array_end = .;

          __text_end = .;
          PROVIDE(__text_end = __text_end);
       } > rom AT > rom

       .ctors :
       {
          __ctors_start = .;
          PROVIDE(__ctors_start = __ctors_start);

          KEEP(*(SORT(.ctors.*)));
          KEEP(*(.ctors));
          . = ALIGN(4);

          __ctors_end = .;
          PROVIDE(__ctors_end = __ctors_end);
       } > rom AT > rom

       .dtors :
       {
          __dtors_start = .;
          PROVIDE(__dtors_start = __dtors_start);

          KEEP(*(SORT(.dtors.*)));
          KEEP(*(.dtors));
          . = ALIGN(4);

          __dtors_end = .;
          PROVIDE(__dtors_end = __dtors_end);
       } > rom AT > rom

       .ARM.exidx :
       {
          __exidx_start = .;
          PROVIDE(__exidx_start = __exidx_start);

          *(.ARM.exidx* .gnu.linkonce.armexidx.*);
          . = ALIGN(4);

          __exidx_end = .;
          PROVIDE(__exidx_end = __exidx_end);
       } > rom AT > rom

       .data :
       {
          __data_init_start = LOADADDR (.data);
          PROVIDE(__data_init_start = __data_init_start);
          __data_start = .;
          PROVIDE(__data_start = __data_start);

          *(.data);
          . = ALIGN(4);
          *(.data.*);
          . = ALIGN(4);
          *(.gnu.linkonce.d*);
          . = ALIGN(4);
          SORT(CONSTRUCTORS);
          . = ALIGN(4);

          __data_end = .;
          PROVIDE(__data_end = __data_end);
       } > ram AT > rom
       
       .xxx_data :
       {
          __xxx_data_init_start = LOADADDR (.xxx_data);
          PROVIDE(__xxx_data_init_start = __xxx_data_init_start);
          __xxx_data_start = .;
          PROVIDE(__xxx_data_start = __xxx_data_start);

          *(.xxx_data);
          . = ALIGN(4);
          *(.xxx_data.*);
          . = ALIGN(4);

          __xxx_data_end = .;
          PROVIDE(__xxx_data_end = __xxx_data_end);
       } > xxx_memory AT > rom

       .bss :
       {
          __bss_start = .;
          PROVIDE(__bss_start = __bss_start);

          *(.bss);
          . = ALIGN(4);
          *(.bss.*);
          . = ALIGN(4);
          *(.gnu.linkonce.b*);
          . = ALIGN(4);
          *(COMMON);
          . = ALIGN(4);

          __bss_end = .;
          PROVIDE(__bss_end = __bss_end);
       } > ram AT > ram
       
       .xxx_bss :
       {
          __xxx_bss_start = .;
          PROVIDE(__xxx_bss_start = __xxx_bss_start);

          *(.xxx_bss);
          . = ALIGN(4);
          *(.xxx_bss.*);
          . = ALIGN(4);

          __xxx_bss_end = .;
          PROVIDE(__xxx_bss_end = __xxx_bss_end);
       } > xxx_memory AT > xxx_memory

       .stack :
       {
          __stack_start = .;
          PROVIDE(__stack_start = __stack_start);

          __main_stack_start = .;
          PROVIDE(__main_stack_start = __main_stack_start);
          . += __main_stack_size;
          . = ALIGN(4);
          __main_stack_end = .;
          PROVIDE(__main_stack_end = __main_stack_end);

          __process_stack_start = .;
          PROVIDE(__process_stack_start = __process_stack_start);
          . += __process_stack_size;
          . = ALIGN(4);
          __process_stack_end = .;
          PROVIDE(__process_stack_end = __process_stack_end);

          __stack_end = .;
          PROVIDE(__stack_end = __stack_end);
       } > ram AT > ram

       __heap_start = .;
       PROVIDE(__heap_start = __heap_start);
       __heap_end = __ram_end;
       PROVIDE(__heap_end = __heap_end);

       .stab             0 (NOLOAD) : { *(.stab) }
       .stabstr          0 (NOLOAD) : { *(.stabstr) }
       /* DWARF debug sections.
       * Symbols in the DWARF debugging sections are relative to the beginning
       * of the section so we begin them at 0. */
       /* DWARF 1 */
       .debug            0 : { *(.debug) }
       .line            0 : { *(.line) }
       /* GNU DWARF 1 extensions */
       .debug_srcinfo      0 : { *(.debug_srcinfo) }
       .debug_sfnames      0 : { *(.debug_sfnames) }
       /* DWARF 1.1 and DWARF 2 */
       .debug_aranges      0 : { *(.debug_aranges) }
       .debug_pubnames      0 : { *(.debug_pubnames) }
       /* DWARF 2 */
       .debug_info         0 : { *(.debug_info .gnu.linkonce.wi.*) }
       .debug_abbrev      0 : { *(.debug_abbrev) }
       .debug_line         0 : { *(.debug_line) }
       .debug_frame      0 : { *(.debug_frame) }
       .debug_str         0 : { *(.debug_str) }
       .debug_loc         0 : { *(.debug_loc) }
       .debug_macinfo      0 : { *(.debug_macinfo) }
       /* SGI/MIPS DWARF 2 extensions */
       .debug_weaknames   0 : { *(.debug_weaknames) }
       .debug_funcnames   0 : { *(.debug_funcnames) }
       .debug_typenames   0 : { *(.debug_typenames) }
       .debug_varnames      0 : { *(.debug_varnames) }

       .note.gnu.arm.ident   0 : { KEEP(*(.note.gnu.arm.ident)) }
       .ARM.attributes      0 : { KEEP(*(.ARM.attributes)) }
       /DISCARD/            : { *(.note.GNU-stack) }
    }

    PROVIDE(__text_size = __text_end - __text_start);
    PROVIDE(__ctors_size = __ctors_end - __ctors_start);
    PROVIDE(__dtors_size = __dtors_end - __dtors_start);
    PROVIDE(__exidx_size = __exidx_end - __exidx_start);
    PROVIDE(__data_size = __data_end - __data_start);
    PROVIDE(__xxx_data_size = __xxx_data_end - __xxx_data_start);
    PROVIDE(__bss_size = __bss_end - __bss_start);
    PROVIDE(__xxx_bss_size = __xxx_bss_end - __xxx_bss_start);
    PROVIDE(__stack_size = __stack_end - __stack_start);
    PROVIDE(__heap_size = __heap_end - __heap_start);

    /******************************************************************************
    * END OF FILE
    ******************************************************************************/


    @rusala - przy IAP może być po prostu blokada szyny APB, z której korzysta RAM USB.

    4\/3!!

    0
  • #8 14 Wrz 2009 13:36
    rusala
    Poziom 22  

    no dobra ale jakby tak bylo to czemu odczyt dziala? narazie to mi wystarczy bo zapis bedzie rzadko i w tym czasie moge uzyc tablicy z normalnego RAMu. Ale troche to dziwne.

    0
  • #9 14 Wrz 2009 13:38
    Freddie Chopin
    Specjalista - Mikrokontrolery

    eee... ale jaki odczyt i jaki zapis dokładnie?

    Może być też tak, że funkcje IAP wewnętrznie coś mieszają z ustawieniami PLL...

    4\/3!!

    0
  • #10 14 Wrz 2009 13:44
    markosik20
    Poziom 33  

    Dzięki Freddie...reasumując żeby zadeklarować taką zmienną w tym "dodatkowym" RAM'ie należałoby użyć atrybutu __xxx_data ??

    Coś jak

    Code:
    unsigned char data __attribute__ ((__xxx_data)); 

    0
  • #11 14 Wrz 2009 14:10
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Trochę inaczej. Musisz wymusić ręczne umieszczenie w wybranej sekcji:

    uint32_t variable __attribute__ ((section(".xxx_data")));

    Pamiętaj o kropce przed xxx_data, bo tak się ta sekcja nazywa:

    -> *(.xxx_data);

    Pamiętaj też o tym, że .xxx_data musisz zainicjalizować w startupie (kopiować z FLASH spod adresu __xxx_data_init_start do RAM __xxx_data_start), a sekcję .xxx_bss wyzerować. Oczywiście możesz tego nie robić, ale lepiej strzec się takich dziwnych błędów <: Nazwy są wybrane arbitalnie, ale w definicji sekcji .xxx_data są mechanizmy umozliwiające takie akcje - chodzi o funkcję LOADADDR ()

    4\/3!!

    0
  • #12 14 Wrz 2009 14:35
    markosik20
    Poziom 33  

    Freddie Chopin napisał:
    Pamiętaj też o tym, że .xxx_data musisz zainicjalizować w startupie (kopiować z FLASH spod adresu __xxx_data_init_start do RAM __xxx_data_start), a sekcję .xxx_bss wyzerować.


    Rozumiem że to jest obowiązkowe wtedy jak zadeklarowane zmienne mają przypisane "na dzień dobry" jakieś wartości ?

    0
  • #13 14 Wrz 2009 14:44
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Zasadniczo właśnie o to chodzi, że jeśli zmiennym przypiszesz wartości początkowe, to musisz dokonać inicjalizacji. Jeśli zmienne wartości początkowej nie mają, to standard zakłada, że powinny być równe zero, niemniej jednak nie jest to obowiązek. Gorzej jeśli kiedyś będziesz chciał wykorzystać to "założenie" zapominając o tym, że tego nie możesz zrobić <: Błędy mogą być dziwne, więc lepiej to zrobić [;

    Na szybko można nawet na początku main() uruchomić taki kod:

    Code:

    extern uint32_t __xxx_data_init_start;
    extern uint32_t __xxx_data_start;
    extern uint32_t __xxx_data_end;
    uint32_t *src;
    uint32_t *dest;
    uint32_t *end;

    src = &__xxx_data_init_start;
    dest = &__xxx_data_start;
    end = &__xxx_data_end;

    while(dest < end)
    *dest++ = *src++;


    (powinno działać <: )

    Analogicznie dla .xxx_bss tyle że zerujesz.

    Lepiej jednak zrobić to w startupie - zawsze to pewniej. Wystarczy skopiować kod odpowiedzialny za "normalne" .data i .bss i zmienić tylko zakresy.

    4\/3!!

    0
  • #14 14 Wrz 2009 14:56
    rusala
    Poziom 22  

    co do PLL to musi on byc wylaczony podczas zapisu (odczytu nie) do pamieci kodu i tak tez robia u mnie funkcje IAP. Moze to tez miec ewentualnie jakis zwiazek z MAMem. Taki zapis wyglada mniejwiecej tak (troche posklejalem kawalki kodu z kilku roznych funkcji):

    Code:
    U0TER = 0x00;   // zablokuj transmisje UART0
    
       U1TER = 0x00;   // zablokuj transmisje UART1

       iapCCLK  = FOSC/1000;                            // Clock Frequency in kHz
       // iapCCLK  = (1049*(clk >> 10)) >> 10;            // Approximate (no Library Code)
       
       // disable VIC/FIQ
       SysState.oldfiq = disableFIQ();
       SysState.oldirq = disableIRQ();
       // set MAMMAP flash   
       MEMMAP = MEMMAP_FLASH;
       // MAM off
       MAMCR =  MAMCR_OFF;
         // disable PLL
       PLLCON = 0x00;
       PLLFEED = 0xAA;                       // Make it happen.  These two updates
       PLLFEED = 0x55;                       // MUST occur in sequence.

    n = 22;   // dla LPC2148 sektory nie sa rowne !!!
       
       IAP.cmd    = 50;       // Prepare Sector for Write
       IAP.par[0] = n;        // Start Sector
       IAP.par[1] = n;        // End Sector
       IAP_Exec (&IAP);       // Execute IAP Command
       if (IAP.stat) return (IAP.stat+100); // Command Failed
       
       IAP.cmd    = 51;       // Copy RAM to Flash
       IAP.par[0] = adr;      // Destination Flash Address
       IAP.par[1] = (unsigned int)buf; // Source RAM Address
       IAP.par[2] = sz;       // Page Size
       IAP.par[3] = iapCCLK;  // CCLK in kHz
       IAP_Exec(&IAP);        // Execute IAP Command

    PLLCFG = PLLCFG_MSEL | PLLCFG_PSEL;
       // enable PLL
       PLLCON = PLLCON_PLLE;
       PLLFEED = 0xAA;                       // Make it happen.  These two updates
       PLLFEED = 0x55;                       // MUST occur in sequence.
       // wait for PLL lock
       while (!(PLLSTAT & PLLSTAT_LOCK))
          continue;
       // enable & connect PLL
       PLLCON = PLLCON_PLLE | PLLCON_PLLC;
       PLLFEED = 0xAA;                       // Make it happen.  These two updates
       PLLFEED = 0x55;                       // MUST occur in sequence.   
       // setup & enable the MAM
       MAMTIM = MAMTIM_CYCLES;
       MAMCR = MAMCR_FULL;
       // set the interrupt controller defaults
       #if defined(RAM_RUN)
       #warning RAM_RUN untested in iap.c
       #elif defined(ROM_RUN)
       MEMMAP = MEMMAP_FLASH;                // map interrupt vectors space into FLASH
       #else
       #error RUN_MODE not defined!
       #endif
       // restore FIC/IRQ
       restoreIRQ(SysState.oldirq);
       restoreFIQ(SysState.oldfiq);
       
       U0TER = 0x80;   // odblokuj transmisje UART0
       U1TER = 0x80;   // odblokuj transmisje UART1


    To tak jezeli kogos to bardziej interesuje ;-)

    0
  • #15 14 Wrz 2009 14:57
    markosik20
    Poziom 33  

    Freddie Chopin napisał:
    Błędy mogą być dziwne, więc lepiej to zrobić [;


    Dobrych nawyków nigdy za mało :wink:. Dzisiaj to przetestuję. Pięknie dziękuję.

    0