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

tlcdebug Обзор руководства

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

<reservedrangesplaceholder1> <reservedrangesplaceholder0> / toolbox/rtw/rtwdemos/tlctutorial/tlcdebug (открыто)

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

  1. Getting Started - Запустите модель и осмотрите выход

  2. Generate and Run Code from the Model - Сравнение скомпилированных результатов с исходным выходом

  3. Start the Debugger and Use Its Commands - Вещи, которые вы можете сделать с отладчиком

  4. <reservedrangesplaceholder1> <reservedrangesplaceholder0> - Узнайте, что пошло не так

  5. Fix the Bug and Verify - простые способы исправить ошибки и проверить исправления

Начало

  1. Скопируйте файлы из tlctutorial/tlcdebug к вашей текущей рабочей директории.

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

    mex timesN.c

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

    Примечание

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

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

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

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

  6. Дважды кликните yout на панели Workspace Командного окна MATLAB. Редактор переменных отображает выходы массива 6x1 из simple_log. Выглядит отображение следующим образом:

    Столбец 1 содержит дискретный импульсный выход для шести временных шагов (3с и 0с), собранных в порту 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. Просмотр результатов путем размещения переменных в рабочей рабочей области. На панели Current Folder дважды кликните мышью 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. Выберите панель Configuration Parameters > Code Generation и выберите опции Retain .rtw file и Start TLC debugger when generating code. Нажмите OK.

    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, выполните оставшийся код, чтобы закончить процесс сборки, затем создайте 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Как и раньше. Теперь значения в первом столбце должны совпадать.

Похожие темы