Перейти к содержанию
    

vitek101

Участник
  • Постов

    39
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные vitek101


  1. Выяснил, что переполнение происходит из-за того, что в какой-то момент перестает вызываться задача, которая должна эту очередь читать. Всего задач у меня 8, пробовал уменьшать до 3-х задач и 5 КБ памяти данных, изменял размеры стеков, приоритеты задач - не помогает.

  2. На XMEGA128 использую очередь сообщений. В общем работает хорошо, но при большой нагрузке (много данных по УАРТам) переполняется очередь сообщений для задачи. Прерывания все при этом работают. Сообщения для других задач иногда отсылаются, иногда нет. Пробовал при переполнении вызывать OSQFlush - эффекта нет. Как быть?

    П.С. памяти данных использую 7600 байт из 8КБ. Может что-то из-за этого?

  3. Пробую завести ЦАП от таймера. Если таймер срабатывает чаще, чем раз в полторы милисекунды, прекращается обработка OSQPost. В отладчике смотрю - постоянно срабатывают прерывания, а до задачи, в которую передается сообщение - не попадаю :help: Кто-нибудь сталкивался с таким?

     

    :08: косячек у себя нашел :) можно закрывать тему...

  4. Подскажите, пожалуйста... Область памяти, которая называется таблицей приложения. В даташите написано, что если не хранить в ней данные, то ее можно использовать под приложение. Так вот, как узнать, использую ли я ее для хранения данных? Другими словами, чтоб хранить в ней данные надо это каким-то особенным образом объявить? А если я этого не знаю, то я ее и не использую? И если я правильно понимаю все вышесказанное, то приложение можно расширить до 136КБ? А из бутлоадера эта область доступна?

     

    Или эта таблица входит в 128КБ памяти программ?

  5. проблема решилась :biggrin: Я сделал чтоб все прерывания были одного уровня приоритета (низкого) и включил круговую систему Робина - и все исчезло. Теперь работают все уарты, таймеры (железные) и все на больших скоростях и при целой толпе данных :08:

    а вот этот предел, его вообще в принципе нельзя превышать?

  6. Здравствуйте. Извините, что вмешался :biggrin:

    Я тоже делаю ДМА для УАРТа, сделал по примеру из 185 поста. Настроил так:

        DMA_ConfigDoubleBuffering(DMA_DBUFMODE_DISABLED_gc);
        DMA_SetPriority(DMA_PRIMODE_RR0123_gc);
        DMA_SetupBlock(&DMA.CH0,
                        &bbb,
                        DMA_CH_SRCRELOAD_NONE_gc,
                        DMA_CH_SRCDIR_INC_gc,
                        &USARTF0.DATA,
                        DMA_CH_DESTRELOAD_NONE_gc,
                        DMA_CH_DESTDIR_FIXED_gc,
                        len,
                        DMA_CH_BURSTLEN_1BYTE_gc,
                        0,
                        false);
        DMA_SetTriggerSource(&DMA.CH0,DMA_CH_TRIGSRC_USARTF0_DRE_gc);
        DMA_EnableSingleShot(&DMA.CH0);
        DMA_SetIntLevel(&DMA.CH0, DMA_CH_TRNINTLVL_HI_gc, DMA_CH_ERRINTLVL_HI_gc);
        
        DMA_Enable();
        DMA_EnableChannel(&DMA.CH0);

    bbb - обычный массив

    len - длина массива

    Проблема в том, что правильно передаются только три байта, дальше всякий мусор. Пробовал изменять все параметры (перезагрузка адреса, декремент, длина блока, даблбуффер, ...) - то же самое.

    В чем может быть дело? :05:

     

    Разобрался. Почему-то такая штука была при локально объявленном буфере. Объявил глобально и все прошло :twak:

  7. Флаг прерываний получилось сбросить перезапуском прерываний УАРТа и очисткой буферов. После этого все прерывания срабатывают, но не обрабатываются сообщения OSQPost - процедура вываливается тут

     

        if (pevent->OSEventType != OS_EVENT_TYPE_Q) {      /* Validate event block type                    */
            return (OS_ERR_EVENT_TYPE);
        }

     

    Похоже проблема изначально возникает из-за операционки. Мне кажется в один прекрасный момент не срабатывает выход из прерывания или переключение контекста, или что там еще может быть (я в дебрях uCOSа не силен).

     

    Может есть у кого какие-нибудь мысли? Помогите!!! Пожалуйста!! :help:

  8. Создал эту тему сначала в операционных системах, но может тут кто знает...

     

    IAR 5.20, XMEGA128. В программе крутятся 8 потоков, задействованы 8 УАРТов (средний уровень прерываний), 8 таймеров (высокий уровень) и 2 И2Ц (средний). Очень часто при большом потоке информаци зависает прерывание одного из УАРТов. В регистре PMIC стоит флаг обработки прерывания среднего уровня. Можно ли как-нибудь программно сбросить этот флаг (по даташиту вроде нельзя). Прерывания высокого уровня при этом работают. И еще, программа уже занимает 105КБ памяти, а всего в камне 128. Может из-за этого что-нибудь валиться?

  9. IAR 5.20, XMEGA128. В программе крутятся 8 потоков, задействованы 8 УАРТов (средний уровень прерываний), 8 таймеров (высокий уровень) и 2 И2Ц (средний). Очень часто при большом потоке информаци зависает прерывание одного из УАРТов. В регистре PMIC стоит флаг обработки прерывания среднего уровня. Можно ли как-нибудь программно сбросить этот флаг (по даташиту вроде нельзя). Да, идлтаск при этом крутится, и работают прерывания высокого уровня. И еще, программа уже занимает 105КБ памяти, а всего в камне 128. Может из-за этого что-нибудь валиться?

  10. Почему может постоянно забиваться CSTACK?

    Читаю загрузчиком программу из FRAM, пишу ее во флеш страницами по 512 байт, когда дохожу до последней страницы выдается сообщение, что CSTACK забит на 98 процентов и все перестает работать (меняются многие переменные на кривые значения).

    Пробовал менять размер стека, все время забивается на 98 процентов. От размера загружаемой программы не зависит... :laughing:

    Да, загрузчик сделал отдельным проектом

     

    Снимаю вопрос. Одно условие прорустил :biggrin:

  11. Поставил. Стартует он откуда надо. У XMega только одна область для загрузчика, 8 Кб.

     

    Что-то не получается у меня отключить стандартную библиотеку. Если ее выкинуть, вылезает толпа разных ошибок.

    А если взять и в стандартном STARTUPе заменить строки

     RSEG    CODE:CODE:NOROOT(1)

    на

     RSEG    BOОT_ENTRY:CODE:NOROOT(1)

    Может так сработает?

     

    И main на boot

     

    Работает!!! :08:

    В общем поменял CODE на BOOT_ENTRY, а main оставил. Теперь следующая картина:

    Стартует с загрузчика, но без STARTUPа. Праметр bytesToRead так и не работает (см. первый пост). Но попробовал опять убрать address и все заработало. Стартап появляет в отладчике в начале основной программы.

    Непонятно вылезут дальше косяки какие-нибудь или нет, т.к. проблема с address так и не решена.

    Спасибо за помощь! :a14:

     

    Теперь стартап такой:

    ;----------------------------------------------------------------------------
    ; Set up the INTVEC segment with a reset vector
    ;----------------------------------------------------------------------------
            MODULE    ?RESET
    
        COMMON  INTVEC:CODE:ROOT(1); Align at an even address
    
            EXTERN  ?C_STARTUP
            PUBLIC  __program_start
            PUBLIC  ?RESET
    
        ORG $0
    __program_start:
    ?RESET:
        XJMP    ?C_STARTUP
    
            ENDMOD
    
    ;----------------------------------------------------------------------------
    ; Forward declarations of segments used in initialization
    ;----------------------------------------------------------------------------
        RSEG    CSTACK:DATA:NOROOT(0)
        RSEG    RSTACK:DATA:NOROOT(0)
    
    ;----------------------------------------------------------------------------
    ; Perform C initialization
    ;----------------------------------------------------------------------------
        MODULE  ?C_STARTUP
    
        EXTERN  __low_level_init
        EXTERN  __segment_init
    #ifdef _ECLIB_ECPP
        EXTERN  __call_ctors
    #endif /* _ECLIB_ECPP */
        EXTERN  main
        EXTERN  exit
        EXTERN  _exit
    
    ;----------------------------------------------------------------------------
    ; If the return address stack is located in external SRAM, make sure that
    ; you have uncommented the correct code in __low_level_init!!!
    ;----------------------------------------------------------------------------
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
        PUBLIC  ?C_STARTUP
        PUBLIC  __RESTART
        EXTERN ?RESET
    
    __RESTART:
    ?C_STARTUP:
    #if A90_POINTER_REG_SIZE > 2
        PUBLIC  ?zero_reg_initialization
    
    ?zero_reg_initialization:
        CLR R15
        OUT RAMPD,R15
    #endif
    
        REQUIRE ?SETUP_STACK
        REQUIRE ?RESET
    
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
        PUBLIC  __RSTACK_in_external_ram
    
    __RSTACK_in_external_ram:
        LDI     R16,0xC0
        OUT     0x35,R16   ;Enable the external SRAM with a wait state
    
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
        PUBLIC  __RSTACK_in_external_ram_new_way
        EXTERN  __?XMCRA
    
    __RSTACK_in_external_ram_new_way:
        LDI     R16,0x8C       ;SRE=1,SRL2=0,SRL1=0,SRL0=0,SRW11=1,SRW10=1,SRW01=0,SRW00=0
        STS     __?XMCRA,R16   ;Enable the external SRAM with maximum wait state.
    
    ;----------------------------------------------------------------------------
    ; Set up the CSTACK and RSTACK pointers.
    ;----------------------------------------------------------------------------
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
    ?SETUP_STACK:
       ;; Return address stack (RSTACK)
        LDI R16,LOW(SFE(RSTACK)-1)
        OUT 0x3D,R16
    #if A90_POINTER_REG_SIZE > 1
        LDI R16,HIGH(SFE(RSTACK)-1)
        OUT 0x3E,R16
    #endif
    
       ;; Data stack (CSTACK)
        LDI Y0,LOW(SFE(CSTACK))
    #if A90_POINTER_REG_SIZE > 1
    #if MEMORY_MODEL == TINY_MEMORY_MODEL
        LDI Y1,0
    #else
        LDI Y1,HIGH(SFE(CSTACK))
    #endif
    #if A90_POINTER_REG_SIZE > 2
        LDI Z0,HWRD(SFB(CSTACK))
        OUT     RAMPY,Z0
    #endif
    #endif
    
    #if A90_POINTER_REG_SIZE > 2
    ; Nothing here, the things previously here has been done earlier.
    #else
        REQUIRE ?call_low_level_init
    
    ;----------------------------------------------------------------------------
    ; Clear R15 so that it can be used as zero register by the code generator.
    ; The compiler will emit a "REQUIRE ?zero_reg_initialization" statement if
    ; this optimization has been enabled.
    ;----------------------------------------------------------------------------
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
        PUBLIC  ?zero_reg_initialization
    
    ?zero_reg_initialization:
        CLR R15
    
    ;----------------------------------------------------------------------------
    ; Call __low_level_init to do low level initializatons. Modify the supplied
    ; __low_level_init module to add your own initialization code or to
    ; remove segment initialization (by returning 0).
    ;----------------------------------------------------------------------------
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
    #endif
        PUBLIC  ?call_low_level_init
    
    ?call_low_level_init:
        XCALL   __low_level_init
    
        REQUIRE ?cstartup_call_main
    
    ;----------------------------------------------------------------------------
    ; Call __segment_init to initialize segments.
    ;----------------------------------------------------------------------------
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
        PUBLIC  ?need_segment_init
    
    ?need_segment_init:
        TST P0
        BREQ    ?skip_segment_init
        XCALL   __segment_init
    ?skip_segment_init:
    
    ;----------------------------------------------------------------------------
    ;   Call the constructors of all global objects. This code will only
    ;   be used if any EC++ modules defines global objects that need to
    ;   have its constructor called before main.
    ;----------------------------------------------------------------------------
    #ifdef _ECLIB_ECPP
        RSEG    DIFUNCT:CODE:NOROOT(0)
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
    
        PUBLIC  ?call_ctors
    
    ?call_ctors:
    #ifdef __HAS_ELPM__
        LDI P0,LOW(SFB(DIFUNCT))
        LDI P1,LOW(SFB(DIFUNCT) >> 8)
        LDI P2,SFB(DIFUNCT) >> 16
    
        LDI Q0,LOW(SFE(DIFUNCT))
        LDI Q1,LOW(SFE(DIFUNCT) >> 8)
        LDI Q2,SFE(DIFUNCT) >> 16
    #else
        LDI P0,LOW(SFB(DIFUNCT))
        LDI P1,SFB(DIFUNCT) >> 8
    
        LDI P2,LOW(SFE(DIFUNCT))
        LDI P3,SFE(DIFUNCT) >> 8
    #endif
    
        XCALL   __call_ctors
    #endif /* _ECLIB_ECPP */
    
    ;----------------------------------------------------------------------------
    ;   Call main
    ;----------------------------------------------------------------------------
        RSEG    BOOT_ENTRY:CODE:NOROOT(1)
    
        PUBLIC  ?cstartup_call_main
    
    ?cstartup_call_main:
        XCALL   main
        XCALL   exit
        XJMP    _exit
    
        END
    
    ;----------------------------------------------------------------------------
    ;

  12. А можно заменить

              lda   Z, SFB(NEAR_Z)

    на

              LD[b]A[/b]   ZL,LOW(SF[b]B[/b](NEAR_Z)-1)
              LD[b]A[/b]   ZH,HIGH(SF[b]B[/b](NEAR_Z)-1)

    ?

    illegal effective address убрались :)

     

    Спросил, а потом увидел ответ :)

     

    Вроде собрал, правда только первую часть (без инициализации переменных. Там ругается invalid syntax на строки с макросом).

    Только он теперь говорит undefined external "boot" referred in cstatup :wacko:

     

     

     

    Все, запустил. Но в отладчике нашего стартапа не видно и все не работает по-старому...

  13. Сделал так:

    EXTERN boot
            RSEG   CSTACK:DATA:NOROOT(0)
            RSEG   RSTACK:DATA:NOROOT(0)
            RSEG   BOOT_ENTRY:CODE:ROOT(1)
    
              LDI   R17,LOW(SFE(RSTACK)-1)
              OUT   SPL,R17
              LDI   R17,HIGH(SFE(RSTACK)-1)
              OUT   SPH,R17
              
              LDI   YL,LOW(SFE(CSTACK)-1)                                  // тут ругается: illegal effective address
              LDI   YH,HIGH(SFE(CSTACK)-1)                                // тут ругается: illegal effective address
    //NEAR_Z initialization
            RSEG   BOOT_ENTRY:CODE:NOROOT(1)                      // тут заменил STARUPCODE на BOOT_ENTRY
    PUBLIC `?<Segment init: NEAR_Z>`
    `?<Segment init: NEAR_Z>`:
              lda   Z, SFB(NEAR_Z)                                                // тут ругается: bad instruction
              lda   X, SIZEOF(NEAR_Z)                                           // тут ругается: bad instruction
              clr   r16
    filloop:
              st    Z+, r16
              sbiw XL, 1                                                                // тут ругается: illegal effective address
              brne filloop
    
    //NEAR_I initialization
            RSEG   BOOT_ENTRY:CODE:NOROOT(1)                      // тут заменил STARUPCODE на BOOT_ENTRY
    PUBLIC `?<Segment init: NEAR_I>`
    `?<Segment init: NEAR_I>`:
              lda   Z, SFB(NEAR_ID)                                           // тут ругается: bad instruction
              lda   Y, SFB(NEAR_I)                                           // тут ругается: bad instruction
              lda   X, SIZEOF(NEAR_I)                                           // тут ругается: bad instruction
              
    moveloop:
              lpm r0, Z+
              st Y+, r0
              sbiw XL, 1                                                                // тут ругается: illegal effective address
              brne moveloop
    
            RSEG   BOOT_ENTRY:CODE:ROOT(1)
              rjmp boot
                                                                                            // тут ругается unexpected end of file encountered

     

    Это все вставил вместо содержимого стандартного CSTARTUP. Что делаю не так?

  14. На всякий случай прошу прощения за возможно глупый вопрос :rolleyes:

    А BOOTENTRY (в строке RSEG BOOTENTRY:CODE:ROOT(1)) это то же, что и BOOT_ENTY в вашем первом посте?

    И че вообще с этим кодом надо сделать? Его надо впихнуть в CSTARTUP, который я взял из avr\src\lib и подключил к своему проекту?

  15. А я тут и использую полинг. С прерываниями я так и не разобрался (вроде как надо вторую таблицу создавать, а как ее создавать х.з. :laughing: ).

    А про startup можно поподробнее? Че как инициализировать? Просто я в общем язык и структуру понимаю, а в такие дебри еще не лазил. Надо взять готовый стартап и изменить его или свой новый создавать?

    За сегменты спасибо :)

  16. Написал загрузчик для XMega128, IAR5.20. Переделал его из примера Атмела 1605.

    Загрузчик расположен в одном проекте с основным приложением в секции #ifdef. По сбросу стартует загрузчик и проверяет наличие программы в FRAM, если есть заливает ее во флеш.

    Определил сегмент в XCL:

     

    -D_..X_FLASH_HUGE_END=21FFF

    -D_..X_BOOTSEC_SIZE=2000

    -Z(CODE)BOOT_SEGMENT=(_..X_FLASH_HUGE_END-_..X_BOOTSEC_SIZE+1)-_..X_FLASH_HUGE_END

     

    Сам загрузчик:

    #pragma segment = "BOOT_SEGMENT"
    #pragma location="BOOT_SEGMENT"
    
    #include <eeprom_driver.h>
    #include <sp_driver.h>
    #include <defines.h>
    
    #define BOOT_F_CPU             2000000UL
    
    ........ // определение типов и констант для I2C
    
    boot_TWI_Master_t  twiMaster;   // структура для работы с I2C
    uint8_t boot_sBuf[32];
    
    // объявление функций для I2C
    __root bool boot_TWI_MasterWriteRead(boot_TWI_Master_t *twi,
                             uint8_t address,
                             uint8_t *writeData,
                             uint8_t bytesToWrite,
                             uint8_t bytesToRead) @ "BOOT_SEGMENT";
    __root void boot_TWI_MasterInterruptHandler(boot_TWI_Master_t *twi) @ "BOOT_SEGMENT";
    
    .........
    
    
    __root void boot(void) @ "BOOT_SEGMENT"; // тело загрузчика
    __root void GoToApplication(void) @ "BOOT_SEGMENT"; // переход в приложение
    
    __root void boot(void) @ "BOOT_SEGMENT"
    {
      boot_TWI_MasterInit(&twiMaster,                   // инициализирую I2C
                     &TWIF,
                     TWI_MASTER_INTLVL_HI_gc,
                     BOOT_TWI_BAUDSETTING);
      
      PMIC.CTRL |= PMIC_HILVLEN_bm;
      
      boot_sBuf[0] = 0x00;                                   // читаю из FRAM 6 байтов
      boot_sBuf[1] = 0x40;
      boot_TWI_MasterWriteRead(&twiMaster,
                          0xA0,
                          &boot_sBuf[0],
                          2,
                          6);
    
      while (twiMaster.status != boot_TWIM_STATUS_READY)      // пишу и читаю пока надо
      {
        if ((TWIF.MASTER.STATUS & 0xCC) != 0x00)
        {
          boot_TWI_MasterInterruptHandler(&twiMaster);
        }
      }
      
      // в зависимости от результата что-то делаю
      ............
      
      GoToApplication();
        
    }
    
    __root void GoToApplication(void) @ "BOOT_SEGMENT"
    {
      cli();
      PMIC.CTRL = 0;
      SP_WaitForSPM();
      SP_LockSPM();
      EIND = 0x00;
      void (*funcptr)( void ) = 0x0000;         // Set up function pointer to RESET vector.
      funcptr();                                // Jump to Reset vector 0x0000 in Application Section.
    }
    
    __root bool boot_TWI_MasterWriteRead(boot_TWI_Master_t *twi,
                             uint8_t address,
                             uint8_t *writeData,
                             uint8_t bytesToWrite,
                             uint8_t bytesToRead) @ "BOOT_SEGMENT"
    {
        /*Parameter sanity check. */
        if (bytesToWrite > boot_TWIM_WRITE_BUFFER_SIZE) {
            return false;
        }
        if (bytesToRead > boot_TWIM_READ_BUFFER_SIZE) {
            return false;
        }
    
                ..........................
    }

     

    Загрузчик стартует как надо, переход в тело работает.

    Теперь собственно в чем проблема:

    Инициализация I2C проходит нормально, регистры принимают нужное значение.

    При вызове boot_TWI_MasterWriteRead(...) смотрю в отладчике, а там параметр bytesToRead всегда равен 0. Пробовал убрать параметр address, тогда bytesToRead передается как надо. Т.е получается не может передать большое количество параметров. Но дальше все равно не работает чтение из FRAM. Пробовал вставлять этот кусок в основное тело приложения, там все работает хорошо.

    Мне кажется или что-то со стеком при работе в области загрузчика или не знаю.

     

    Помогите пожалуйста :help:

     

     

    И еще: может проблема быть связана с __root, #pragma и т.д.? Может чего-то не хватает? Просто я в них не особо шарю... :laughing:

  17. Этот бутлоадер специфичен для конкретной платы, он будет грузить программу из FRAM, предварительно загруженную основной программой. Т.е. для нового приложения все равно придется переделывать, а скопировать кусок кода и вставить в другое место не трудно.

  18. Он прыгает по адресу 0х0000, а потом сразу на следующую за funcptr() строку. Может это быть из-за того, что в памяти находится только загрузчик, а программы самой нет?

    Все-таки я склоняюсь к объединению загрузчика с программой в один проект и отключению его если надо по #ifdef. Так хоть что-то работает Вернее все работает, кроме прерываний... Вот сейчас копаю, как создать вторую таблицу прерываний :smile3046:

×
×
  • Создать...