exponenta event banner

Отладка кода TLC

tlcdebug Обзор учебного пособия

Цель: Введение в отладчик TLC. Вы узнаете, как установить точки останова и ознакомиться с командами отладчика TLC.

Папка: matlabroot/toolbox/rtw/rtwdemos/tlctutorial/tlcdebug (открыто)

Можно вызвать отладчик TLC при каждом вызове процесса построения. В этом учебном пособии он используется для обнаружения ошибки в .tlc файл для модели с именем simple_log. Ошибка приводит к тому, что генерируемый код, выводимый из автономной версии модели, отличается от результата моделирования. В учебном пособии описаны следующие шаги.

  1. Начало работы - запуск модели и проверка выходных данных

  2. Создание и выполнение кода из модели - сравнение скомпилированных результатов с исходными выходными данными

  3. Запуск отладчика и использование его команд - действия, которые можно выполнить с отладчиком

  4. Отладка timesN.tlc - Узнайте, что пошло не так

  5. Исправление ошибок и проверка - простые способы исправления ошибок и проверки исправлений

Начало

  1. Копировать файлы из tlctutorial/tlcdebug в текущий рабочий каталог.

  2. В окне команд MATLAB ® создайте файл MEX для функции S:

    mex timesN.c

    Это позволяет избежать выбора версии, поставляемой с программным обеспечением Simulink ® .

    Примечание

    Ошибка может возникнуть, если вы ранее не запускали mex -setup.

  3. Открытие модели simple_log. Модель выглядит так.

  4. На панели Импорт/экспорт данных (Data Import/Export) диалогового окна Параметры конфигурации (Configuration Parameters) установите флажок Время и вывод (Time and Output). Это приводит к регистрации переменных модели в рабочей области MATLAB.

  5. Запустите модель. На вкладке Моделирование (Simulation) щелкните Выполнить (Run). Переменные tout и yout появится в рабочей области MATLAB.

  6. Двойной щелчок yout на панели Рабочая область (Workspace) окна команды MATLAB (MATLAB Command Window). Редактор переменных отображает выходные данные массива 6x1 из simple_log. Дисплей выглядит следующим образом:

    Столбец 1 содержит дискретный импульсный выход для шести временных шагов (3s и 0s), собираемый в порту out1.

Затем создается автономная версия simple_log. Он выполняется и сравнивается с выводом Simulink, показанным выше.

Примечание

Для целей этого упражнения в TLC-файле были предоставлены: timesN.tlc, содержит ошибку. Эта версия должна находиться в той же папке, что и используемая модель.

Создание и выполнение кода из модели

  1. Нажмите Ctrl + B.

    Генератор кода создает, компилирует и связывает исходный код C. В окне команд MATLAB отображается ход построения, которое завершается следующими сообщениями:

    ### Created executable: simple_log.exe  
    ### Successful completion of build procedure 
        for model: simple_log
  2. Запуск автономной модели, только что созданной с помощью ввода

    !simple_log

    Это приводит к появлению сообщений

    ** starting the model **
    ** created simple_log.mat **
  3. Проверьте результаты, поместив переменные в рабочую область. На панели «Текущая папка» дважды щелкните simple_log.matзатем дважды щелкните rt_yout (автономная версия переменной yout) на панели Рабочая область (Workspace).

    Выдержать сравнение rt_yout с yout. Вы замечаете различия? Можете ли вы предположить, что вызвало значения в rt_yout чтобы измениться?

    Посмотрите на созданный код C, который TLC поместил в папку сборки (simple_log_grt_rtw) помогает выявить проблему.

  4. Править simple_log.c и посмотрите на его MdlOutputs , которая должна выглядеть следующим образом:

    /* Model output function */
    static void simple_log_output(void)
    {
      /* DiscretePulseGenerator: '<Root>/Discrete Pulse Generator' */
      simple_log_B.DiscretePulseGenerator = (simple_log_DW.clockTickCounter < 1.0) &&
        (simple_log_DW.clockTickCounter >= 0) ? 1.0 : 0.0;
      if (simple_log_DW.clockTickCounter >= 2.0 - 1.0) {
        simple_log_DW.clockTickCounter = 0;
      } else {
        simple_log_DW.clockTickCounter++;
      }
    
      /* End of DiscretePulseGenerator: '<Root>/Discrete Pulse Generator' */
    
      /* S-Function (timesN): '<Root>/Gain1st' incorporates:
       *  Outport: '<Root>/Out1'
       */
      /* S-Function Block: <Root>/Gain1st */
      /* Multiply input by 3.0 */
      simple_log_Y.Out1 = simple_log_B.DiscretePulseGenerator * 1;
    }
    

Обратите внимание на линию около конца:

simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1;
Как неправильный продукт был назначен выходу, когда он должен был получить переменную, которая чередуется между 3.0 и 0.0? Используйте отладчик, чтобы узнать.

Запуск отладчика и использование его команд

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

  1. Настройте среду отладки TLC и запустите для создания приложения:

    1. Выберите панель Параметры конфигурации > Создание кода и выберите параметры Сохранить файл .rtw и Запустить отладчик TLC при создании кода. Нажмите кнопку ОК.

    2. Создайте модель.

      Процесс построения описывается в окне команд MATLAB. Построение останавливается на timesN.tlc и отображает командную строку:

      TLC-DEBUG>
  2. Напечатать help для вывода списка команд отладчика TLC. Вот некоторые вещи, которые вы можете сделать в отладчике.

    • Просмотр и запрос различных объектов в области TLC.

      TLC-DEBUG> whos CompiledModel
      TLC-DEBUG> print CompiledModel.NumSystems
      TLC-DEBUG> print TYPE(CompiledModel.NumSystems)
    • Изучите операторы в текущем контексте.

      TLC-DEBUG> list
      TLC-DEBUG> list 10,40
    • Перейдите к следующей строке кода.

      TLC-DEBUG> next
    • Шаг в функцию.

      TLC-DEBUG> step
    • Назначение переменной постоянного значения, например, входного сигнала %<u>.

      TLC-DEBUG> assign u = 5.0
    • Задайте точку останова, где вы находитесь или в какой-либо другой части кода.

      TLC-DEBUG> break timesN.tlc:10
    • Выполнять до следующей точки останова.

      TLC-DEBUG> continue
    • Очистить установленные точки останова.

      TLC-DEBUG> clear 1
      TLC-DEBUG> clear all
  3. Если вы пробовали команды TLC debugger, выполните оставшийся код для завершения процесса сборки, а затем создайте simple_log снова. Построение останавливается на timesN.tlc и отображает командную строку:

    TLC-DEBUG>

Отладка timesN.tlc

Теперь посмотрите вокруг, чтобы узнать, что не так с кодом:

  1. Установка точки останова в строке 20 timesN.tlc.

    TLC-DEBUG> break timesN.tlc:20
  2. Проинструктируйте отладчик TLC перейти к точке останова.

    TLC-DEBUG> continue

    TLC обрабатывает ввод, сообщает о своем прогрессе, переходит к строке 20 в timesN.tlc, отображает строку и останавливается.

    ### Loading TLC function libraries
    ...
    ### Initial pass through model to cache user defined code
    .
    ### Caching model source code
    .
    Breakpoint 1
    00020:   %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
  3. Используйте whos для просмотра переменных в текущей области.

    TLC-DEBUG> whos
    Variables within: <BLOCK_LOCAL>
    gain                           Real
    rollVars                       Vector
    block                          Resolved
    system                         Resolved
  4. Проверьте переменные с помощью команды print (имена чувствительны к регистру).

    TLC-DEBUG> print gain
    3.0
    
    TLC-DEBUG> print rollVars
    [U, Y]
  5. Выполните один шаг.

    TLC-DEBUG> step
    00021:     %<LibBlockOutputSignal(0, "", lcv, idx)> = \
  6. Поскольку это встроенная функция, продвигайтесь через next команда.

    TLC-DEBUG> next
    .
    00022:     %<LibBlockInputSignal(0, "", lcv, idx)> * 1;

    Это источник оператора C, ответственного за ошибочный вывод константы, simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1;.

  7. Откажитесь от сборки, выйдя из отладчика TLC. Напечатать

    TLC-DEBUG> quit

    Отображается сообщение об ошибке, показывающее, что построение остановлено с помощью отладчика TLC quit команда. Закройте окно ошибок.

Исправление ошибки и проверка

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

%function Outputs(block, system) Output
   %assign gain =SFcnParamSettings.myGain
  /* %<Type> Block: %<Name> */
  %%
  /* Multiply input by %<gain> */
  %assign rollVars = ["U", "Y"]
  %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
    %<LibBlockOutputSignal(0, "", lcv, idx)> = \
    %<LibBlockInputSignal(0, "", lcv, idx)> * 1;
  %endroll

%endfunction

%% [EOF] timesN.tlc
  1. Чтобы исправить ошибку кодирования, отредактируйте timesN.tlc. Линия

    %<LibBlockInputSignal(0, "", lcv, idx)> * 1;
    умножает вычисленный входной сигнал на 1. Изменение строки на
    %<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>;

    Сохранить timesN.tlc.

  2. Создайте автономную модель еще раз. Завершить построение путем ввода continue на каждом TLC-DEBUG> подсказка.

  3. Выполнение автономной модели путем ввода

    !simple_log
    Новая версия simple_log.mat создается с его выводом.

  4. Груз simple_log.mat и сравнить переменную рабочей области rt_yout с yout, как и раньше. Теперь значения в первом столбце должны соответствовать.

Связанные темы