Jump to content

    

Алексей ВМ

Участник
  • Content Count

    125
  • Joined

  • Last visited

Posts posted by Алексей ВМ


  1. Это макросы. Насколько я понял, служебные функции вызываются при использовании параметров в вызове функции. Если тело функции HalFlashWriteRAM() использовать в функции UpdateFirmware(), то все работает отлично.

  2. Это и есть отдельная программа. Она копируется из ROM в SRAM и оттуда запускается, но при  этом происходит обращение к служебным функциям, например LCALL ?BANKED_ENTER_XDATA, которые находятся во флеше.

     

    #pragma default_function_attributes = @ "RAMCODE"
    void UpdateFirmware(void)
    {        
        buf[0] = 0xBE;
        buf[1] = 0xEF;
        buf[2] = 0xDE;
        buf[3] = 0xAD;  
        
    
        HalFlashWriteRAM(TEST_ADDR, buf, 1);
      
        LED_ON
          
        for(;;);
    }
    
    
    void HalFlashWriteRAM(uint16 addr, uint8 *buf, uint16 cnt)
    {        
        halDMADesc_t *ch = HAL_NV_DMA_GET_DESC();
        
        HAL_DMA_SET_SOURCE(ch, buf);
        HAL_DMA_SET_DEST(ch, &FWDATA);
        HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN);
        HAL_DMA_SET_LEN(ch, (cnt * HAL_FLASH_WORD_SIZE));
        HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE);
        HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE);
        HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_FLASH);
        HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_1);
        HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0);
        // The DMA is to be polled and shall not issue an IRQ upon completion.
        HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE);
        HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS);
        HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH);
        HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH);
        HAL_DMA_ARM_CH(HAL_NV_DMA_CH);
    
        FADDRL = (uint8)addr;
        FADDRH = (uint8)(addr >> 8);
        FCTL |= 0x02;         // Trigger the DMA writes.
        while (FCTL & 0x80);  // Wait until writing is done.
        
        //LED_ON
          
        //for(;;);
    }
    #pragma default_function_attributes =

    Например, вызов функции HalFlashWriteRAM(TEST_ADDR, buf, 1); порождает вызов LCALL ?BANKED_ENTER_XDATA

  3. Добрый день,

    Необходимо запускать все функции из SRAM, так как надо перезаписать флешь с кодом. Проблема в том, что функция, вызываемая из SRAM, обращается к служебным  функциям, сидящим во флеше. Как перенести все функции в SRAM?

     

     

     

  4. Добрый день!

    Имеется СС2541, в нем живут три проги - BIM, ImageA и ImageB. BIM находится в 0-м банке. Там же располагаются части ImageA и ImageB, которые должны находиться в root bank - INTVEC, NEAR_CODE, BANK_RELAYS и тп. ImageA грузит по BLE и шьет ImageB.

    Задача - перепрошить с помощью ImageB все три проги.

    Решение - ImageA грузит по BLE и шьет ImageBL, ImageBL все перепрошивает.  Все бы ничего, но непонятно, как перепрошивать 0-й банк, в котором находятся INTVEC, NEAR_CODE, а особенно BANK_RELAYS, загрузчиком из другого банка?

     

  5. 18 minutes ago, SSerge said:

    У меня так было когда в обработчике прерывания от DMA забывал сбросить запрос в регистрах DMA->LIFCR или DMA->HIFCR.

    TCIF сбрасываю. Если не сбрасывать, будет заходить в обработчик снова и снова по первой записи. Другие флаги не выставляются, то есть ошибок записи тоже нет.

  6. On 9/1/2019 at 1:42 PM, SSerge said:

    Не понял. А сколько должно быть? 

    Если в RCR загружено N-1, то update event возникает один раз на каждые N*(ARR+1) тиков таймера.

    Может быть оно так и должно быть?

     

    Вообще один раз, больше не возникает, запись в регистры ARR и RCR (через DMAR) перед этим прерыванием производится правильно. СС1 шлепают нормально, данные выводятся, UIF выставляется, но записи в регистры ARR и RCR не производится, прерывания от выполнения этой записи не возникает.

  7. Реализовал выдачу данных по событию capture/compare event.  Прерывание ТС записи DMA по update event  возникает только один раз, прерывание ТС записи DMA по capture/compare event генерируются нормально.

    Регистры CCR1 = 0, ARR и RCR содержат правильные значения. Как я понимаю update event возникает только один раз. В чем может быть причина?

     

  8. Quote

    A general purpose or an advanced timer (that's all of them except TIM6 and TIM7) can trigger a DMA transfer when the counter reaches the reload value (update event) and when the counter equals any of the compare values (capture/compare event).

    Немного модифицированное предложение ув. SSerge

     

    8 hours ago, SSerge said:

    Но это всё не важно. Важно - это смотреть в будущее на один период дальше чем сейчас (и обязательно с оптимизмом!).

     

    Регистры таймера ARR и RCR буферизованы и в них можно записать новые значения (для следующего периода) заблаговременно.

    Загрузка новых значений из буферных регистров в рабочие регистры произойдёт по событию update event. Сразу после update event можно грузить новые данные.

    Самое правильное это по update event запускать второй канал DMA, который за время текущего периода запишет в ARR и RCR данные для следующего. А потом по прерыванию от DMA готовить данные в буфере для следующих периодов.

    Только DMA должно писать в регистры таймера не напрямую, а используя регистры TIMx->DCR и TIMx->DMAR.

     

    Пины дергать не по update event, а по capture/compare event. Соответственно, update event возникает при окончании передачи всего пакета (68 импульсов), по нему производится DMA запись регистра ARR новым значение периода.

    Два обработчика прерываний -  один старый для формирования буфера передачи, новый для изменения периода таймера.

  9. 9 minutes ago, jcxz said:

    Cortex-M можно заставить работать в таком режиме, чтобы сразу после выхода из ISR CPU сразу уходил в сон. И просыпался только при входе в другое прерывание. Тогда он не будет мешать работе DMA. Всю работу будет делать только в ISR-ах.

    В проекте присутствует обработка довольно большого объема данных, прерывание с такой обработкой будет занимать  довольно значительное время...

     

     

     

    Немного не ясно с RCR:

     

    Each time the REP_CNT related downcounter reaches zero, an update event is generated

     

    Это какой-то особый update event, или он заведен на TIM1_UP?

     

    Дальше по тексту упоминается repetition update event U_RC:

    As REP_CNT is reloaded with REP value only at
    the repetition update event U_RC, any write to the TIMx_RCR register is not taken in
    account until the next repetition update event.

     

    но кроме этого отрывка нигде не находится поиском.

  10. 6 minutes ago, jcxz said:

    Учтите, что даже простое сохранение контекста на входе в ISR (и восстановление на выходе из него) займёт: 1/0.168*8 = 47.6 нс. Если это попадёт на время пересылки DMA по шине, то будет соответствующая задержка. FPU на вашем месте в этом проекте я вообще бы не использовал (компилил код для Cortex-M3).

    Если удастся менять период таймера аппаратно, то задержки до единиц мкс до входа в обработчик прерывания ни на что не влияют. За FPU благодарю, постараюсь избавиться от него.

  11. 3 minutes ago, jcxz said:

    Хммм.... странное условие.... Если так, то может ещё не всё потеряно. Вынести в отдельный регион памяти DMA-буфер, добиться от компилятора отсутствия длинных команд сохранения/восстановления в/из памяти в циклическом коде (чтобы не было постоянных циклических попаданий работ DMA на эти команды). Может и будет работать.....

    Уже работает. Но заказчик решил изменить возможности, отсюда все эти пляски с бубном...

  12. 3 minutes ago, jcxz said:

    Прокатит. Если МК выбирать соответствующий задаче. У XMC4700 например 32 отдельных таймера с ШИМ-ами, которые могут работать синхронно, генеря сигналы с точностью до 1 клока своей тактовой частоты (144МГц). И без всяких завязок на работу шины. 

    Частота  168 МГц .

    XMC4700 мы с Вами уже обсуждали в другой ветке. Если девайс будет развиваться, естественно, аппаратная часть будет изменена.

     

  13. 12 minutes ago, jcxz said:

    Ну да, ну да.... :biggrin:

    Задумайтесь немного: Вот пришло время DMA что-то отправить в GPIO чтобы изменить состояние пинов, а в этот момент CPU решил сохранить контекст FPU на стек, и стек оказался в той же памяти, из которой DMA выполняет пересылку в GPIO. Вопрос: сколько тактов будет ждать DMA освобождения шины при условии того что размер контекста FPU == 16 слов? А если сразу все 33 слова сохраняются? А если ещё целочисленный контекст туда-же - до кучи сохраняется? :dash2:

    Перерыв в несколько десятков или даже сотен мкс не критичен, главное, чтобы он был не чаще одного раза в неск сотен мс. Потери данных, я понимаю, не произойдет?

     

    8 minutes ago, Forger said:

    Текущую сборку останавливать, а на что успели спаять сделайте вторую плату и клейте ее сверху основной. Это нормально. Делать срочно новые правильные платы.

    Это в итоге гораздо дешевле, чем потом переделывать и возвращать груду уже готовых изделий и платить неустойку заказчику.

      

    Не вариант, заказчик за каждый цент удавится

  14. 7 minutes ago, jcxz said:

    Не будет у Вас с таким алгоритмом точности 50 нс. Никак. Так как это - МК. DMA здесь нельзя использовать для задания временных задержек. Потому что DMA использует шину. Соответственно - на время установления состояния на пинах будет влиять загрузка шины. К тому же приоритет доступа DMA-контроллера шины - как правило ниже чем у процессора, начнёт скажем процессор что-то читать активно по шины - DMA будет ждать. Сооветственно - все ваши времянки будут плавать.

    Уже сто раз это обсуждалось здесь и на других форумах....  :russian_ru:

    Ну или определите точность задания времянок. А то может Вам достаточно 50нс +-10нс. Тогда может ещё как-то кое-как и будет работать.

    Для формирования временных диаграмм сигналов использовать нужно соответствующую периферию, например ШИМ. 

    Точность +- 10 нс для наименьшего периода 50 нс, меньше не нужна. По сути, это параллельная шина с 10 сигналами, один из которых клок. ШИМ, к сожалению, здесь не прокатит...

    3 minutes ago, Forger said:

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

    Такое неоднократно видел в серийных изделия военного назначения, главное - правильный клей, лак и испытания )) 

    Платы уже вовсю клепают...

  15. По мелочи если только. Протокол в части добавления новых команд, но объем обмена данными небольшой. Основной функционал - выдача на пины сигналов. Есть ещё редкое- раз в неск секунд - чтение данных из SPI памяти и обработка этих данных, но логика обработки относительно простая.

  16. 8 minutes ago, mcheb said:

    Получается, надо выдавать данные с частотой 100 МГц. А это уже ПЛИС.

    Нет, минимальный период таймера 50 нс, период клока на пине - 100 нс - это 10 МГц. STM32F4 вполне справляется. Затык с переинициализацией таймера на ходу.

  17. 2 hours ago, jcxz said:

    Если будущие периоды таймера известны заранее, то естественно можно запустить второй канал DMA и писать через него новые значения в регистры периода таймера. И высокочастотные прерывания тогда не нужны от слова "совсем".

     

    PS: Мля - как всегда - условия задачи меняются на ходу на совершенно другие.... :russian_ru:

    Я наверно как-то коряво объясняю свою проблему.

    Надо выводить на пины  порта сигналы пачками разной длительности. В пачке 68 импульсов одинаковой длительности - клоки и дата, всего 10 сигналов, соответственно размер буферов DMA 68 слов. Период импульса формируется таймером, по которому с помощью DMA и выдаются данные на пины. Сущестует 4 периода импульса - 50 нс, 120 нс, 250 нс и 500 нс, то есть сначала выдаем пачку импульсов с периодом 50 нс, затем 120, 250, 500, затем опять 50.  Умножаем на 68 - получаем, что прерывания от DMA (TC) возникают, в зависимости от периода таймера, через 3.4 мкс, 8 мкс, 17 мкс и 34 мкс. Сейчас я меняю период таймера в обработчике прерывания DMA, в котором, помимо этого, формируется теневой буфер данных для отправки, всё это занимает порядка 2 мкс. Проблема в том, что когда я захожу в обработчик прерывания DMA, чтобы изменить период таймера, он уже выдает новую пачку данных с предыдущим периодом из-за латентности входа в обработчик. Тоже самое описано в стартовом посте, чуть лаконичнее.

    Что мне нужно - таймер отсчитал 68 раз с заданным периодом, и только после этого необходимо записать в него другое значение периода, лучше аппаратно. Advanced-control timers вроде как позволяют это сделать, у них есть RCR.

     

    Или можно на update event таймера повесить запись по DMA нового периода?

     

    Тогда все равно есть непонятные моменты

     

    Сейчас у меня для дерганья пинов используется DMA2 request Channel 6 Stream 5 - TIM1_UP. По есть по событию update TIM1 каждые 50, 120, 250 или 500 нс на порт выдается новая порция данных. Как сюда ещё вкрячить изменения периода?

     

  18. Прошу прощения, если я неполно описал проблему.

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

    Время между прерываниями - 68 циклов таймера, мин период таймера- 50 нс, получается 3.4 мкс. Вся обработка прерывания занимает 2 мкс.

    Приоритет у прерывания DMA наивысший.

     

    38 minutes ago, SSerge said:

    Важно - это смотреть в будущее на один период дальше чем сейчас (и обязательно с оптимизмом!).

    Регистры таймера ARR и RCR буферизованы и в них можно записать новые значения (для следующего периода) заблаговременно.

    Загрузка новых значений из буферных регистров в рабочие регистры произойдёт по событию update event. Сразу после update event можно грузить новые данные.

    Самое правильное это по update event запускать второй канал DMA, который за время текущего периода запишет в ARR и RCR данные для следующего. А потом по прерыванию от DMA готовить данные в буфере для следующих периодов.

    Только DMA должно писать в регистры таймера не напрямую, а используя регистры TIMx->DCR и TIMx->DMAR.

     

    Спасибо! Именно это я и хотел услышать - менять параметры таймера не в обработчике прерывания DMA, а по другому событию и в другом месте. Только немного непонятно - у меня таймер используется под DMA. О каком update event идет речь? Или имеется в виду, что можно использовать прерывания от этого же таймера? Так не получится, так как мне надо не каждое событие таймера использовать, а каждое 68.

    10 minutes ago, SSerge said:

    Есть ещё возможность ускориться заплатив за это размером буферов.

    Последовательность 50нс, 500нс, 50нс, 500нс превращается в 22 раза по 50нс, причём перезагрузку ARR и RCR придётся делать только один раз (а не 4), но в буфере первого DMA будет не 4 порции данных, а 22. И шины будут сильно загружены циклами DMA.

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