Massa_bob 0 6 октября, 2010 Опубликовано 6 октября, 2010 · Жалоба В рабочем цикле происходит сравнение двух сигналов. Если один сигнал больше другого, то на выходе GPIOA0 = 0, GPIOA1 = 1; если меньше, то GPIOA0 = 1, GPIOA1 = 0. Сравнение происходит с введением коэффициентов усиления (множители с плавающей точкой) каждого сигнала. Переключение состояний порта - с учётом некоторого гистерезиса (с плавающей точкой). #define Ki = -1.5, // Коэффициент усиления по току #define Ku = 0.75, // Коэффициент усиления по напряжению #define Kgist = 0.25, // Гистерезис в компараторе char K = -1; float CompA_in1, // 1-й вход компаратора CompA_in2; // 2-й вход компаратора unsigned int Ua_ADC, Ia_ADC; while(1) { Ua_ADC = AdcRegs.ADCRESULT0 >> 6; // АЦП работает постоянно, на максимальной частоте без прерываний. В рабочем Ia_ADC = AdcRegs.ADCRESULT1 >> 6; // цикле текущие значения АЦП считываются в Ua_ADC и Ia_ADC. CompA_in1 = Ki * Ia_ADC; // Приведение сигналов (масштабирование) CompA_in2 = Ku * Ia_ADC; // перед подачей в компаратор. switch(K) // Компаратор с гистерезисом { case (1): {if (CompA_in1 > (CompA_in2 + Kgist)) K = -1; GpioDataRegs.GPACLEAR.bit.GPIOA0 = 1; GpioDataRegs.GPASET.bit.GPIOA1 = 1; break;} case (-1): {if (CompA_in1 <= (CompA_in2 - Kgist)) K = 1; GpioDataRegs.GPACLEAR.bit.GPIOA1 = 1; GpioDataRegs.GPASET.bit.GPIOA0 = 1; break;} } } Решая задачу “в лоб”, как приведено выше, я столкнулся с проблемой очень низкой частоты рабочего цикла. Эта проблема, судя по всему, заключается в неправильном распределении кода в памяти. В связи с этим возникли следующие вопросы: 1. Каким образом в файле компоновки F2812.cmd распределить память (RAM и FLASH) между секциями, чтобы получить наибольшую скорость этого рабочего цикла? 2. В дальнейшем в этом проекте будут создаваться функции, содержащие математические вычисления (фильтры, регуляторы). Необходимо, чтобы эти функции работали в RAM. Каким образом их следует описывать в исходнике кода и в файле компоновки F2812.cmd? Народ, подскажите, пожалуйста, как с этим бороться. __________TMS320F2812.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kamil_yaminov 1 6 октября, 2010 Опубликовано 6 октября, 2010 · Жалоба По поводу быстродействия: применяйте фиксированную точку - будет быстрее по сравнению с плавающей точкой. По поводу пункта 2 смотрите pragma CODE_SECTION Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Enthusiast 0 8 октября, 2010 Опубликовано 8 октября, 2010 · Жалоба Привет! Ниже я привожу исодник командного файла TMS320F2812, внутри которого код запускается из внутренней флэши, однако критичные ко времени исполнения функции исполняются из ОЗУ (rt_OneStep). MEMORY { PAGE 0: OTP: origin=0x3d7800, length=0x800 BEGINRAM: origin=0x3f8000, length=0x2 BEGINFLASH: origin=0x3f7ff6, length=0x2 CSM_PWL: origin=0x3f7ff8, length=0x8 RAMH0: origin=0x3f8002, length=0x1ffe BOOTROM: origin=0x3ff000, length=0xfc0 RESET: origin=0x3fffc0, length=0x2 VECTORS: origin=0x3fffc2, length=0x3e RAMM0M1: origin=0x0, length=0x800 FLASH: origin=0x3d8000, length=0x1fff6 ZONE6P: origin=0x100000, length=0x8000 PAGE 1: RAML0L1: origin=0x8000, length=0x2000 ZONE6D: origin=0x108000, length=0x8000 } SECTIONS { .vectors: load = 0x000000000 .text: > FLASH, PAGE = 0 .switch: > FLASH, PAGE = 0 .bss: > RAML0L1, PAGE = 1 .ebss: > RAML0L1, PAGE = 1 .far: > RAML0L1, PAGE = 1 .cinit: > FLASH, PAGE = 0 .pinit: > FLASH, PAGE = 0 .const: > FLASH, PAGE = 0 .econst: > FLASH, PAGE = 0 .reset: > RESET, PAGE = 0, TYPE = DSECT .data: > FLASH, PAGE = 0 .cio: > RAML0L1, PAGE = 1 .sysmem: > RAML0L1, PAGE = 1 .esysmem: > RAML0L1, PAGE = 1 .stack: > RAML0L1, PAGE = 1 .rtdx_text: > FLASH, PAGE = 0 .rtdx_data: > FLASH, PAGE = 0 codestart: > BEGINFLASH, PAGE = 0 IQmath: > FLASH, PAGE = 0 ramfuncs: LOAD = FLASH, RUN = RAMH0, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 IQmathTables: > BOOTROM, PAGE = 0, TYPE = NOLOAD } -l "C:\Program Files\MATLAB\R2009b\toolbox\idelink\extensions\ticcs\c2000\c281xPeripherals.cmd" А теперь часть исходного текста программы. Его я генерил из Матлаба автоматически. Нужные строки, которые необходимо вставлять ручками: 1. #pragma CODE_SECTION(rt_OneStep, "ramfuncs"); 2. MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart); /* * File: FeederProbeMskHard_main.c * * Real-Time Workshop code generated for Simulink model FeederProbeMskHard. * * Model version : 1.1147 * Real-Time Workshop file version : 7.4 (R2009b) 29-Jun-2009 * Real-Time Workshop file generated on : Tue Jun 29 16:14:39 2010 * TLC version : 7.4 (Jul 14 2009) * C/C++ source code generated on : Tue Jun 29 16:14:40 2010 * * Target selection: ccslink_ert.tlc * Embedded hardware selection: Texas Instruments->C2000 * Code generation objectives: Unspecified * Validation result: Not run */ #include "FeederProbeMskHard.h" #include "rtwtypes.h" #include "rt_nonfinite.h" #include "FeederProbeMskHard_private.h" #include "c2000_main.h" #include "DSP281x_Device.h" #include "DSP281x_Examples.h" #include <stdlib.h> #include <stdio.h> void init_board(void); void enable_interrupts(void); void config_schedulerTimer(void); void disable_interrupts(void); void idletask_num1(void); volatile int IsrOverrun = 0; static boolean_T OverrunFlag = 0; #pragma CODE_SECTION(rt_OneStep, "ramfuncs"); void rt_OneStep(void) { // Check for overrun. Protect OverrunFlag against // pre-emption if (OverrunFlag++) { IsrOverrun = 1; OverrunFlag--; return; } asm(" SETC INTM"); PieCtrlRegs.PIEIER1.all |= (1 << 6); asm(" CLRC INTM"); FeederProbeMskHard_step(); /* Get model outputs here */ asm(" SETC INTM"); PieCtrlRegs.PIEIER1.all &= ~(1 << 6); asm(" RPT #5 || NOP"); IFR &= 0xFFFE; PieCtrlRegs.PIEACK.all = 0x1; asm(" CLRC INTM"); OverrunFlag--; } // // Entry point into the code // void main(void) { volatile boolean_T noErr; MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart); init_board(); rtmSetErrorStatus(FeederProbeMskHard_M, 0); FeederProbeMskHard_initialize(1); config_schedulerTimer(); noErr = rtmGetErrorStatus(FeederProbeMskHard_M) == (NULL); enable_interrupts(); while (noErr ) { idletask_num1(); noErr = rtmGetErrorStatus(FeederProbeMskHard_M) == (NULL); } /* Disable rt_OneStep() here */ /* Terminate model */ FeederProbeMskHard_terminate(); disable_interrupts(); } /* * File trailer for Real-Time Workshop generated code. * * [EOF] */ А математику с дробными числами я делал тупо в лоб через float'ы. Микроконтроллер смолотил это на раз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Massa_bob 0 8 октября, 2010 Опубликовано 8 октября, 2010 · Жалоба Спасибо за помощь. =) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться