Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: OKI-H5003 (ARM7)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
xoen
В общем проблема заключается в следующем: тупо нужно выставлять то низкий, то высокий уровень на 103 ноге микроконтроллера.

// на С
GPPOE_bit.GPPOE0 = 1;
GPPOE_bit.GPPOE0 = 0;
GPPOE_bit.GPPOE0 = 1;
GPPOE_bit.GPPOE0 = 0;
.........

// либо на асме после компиляции IAR-ом
GPPOE_bit.GPPOE0 = 1;
0000093C E59F0128 LDR R0, [PC, #+296] ; [0xA6C] =_A_GPPOE (0xB7A01080)
00000940 E1D010B0 LDRH R1, [R0, #+0]
00000944 E3811001 ORR R1, R1, #0x1
00000948 E1C010B0 STRH R1, [R0, #+0]
GPPOE_bit.GPPOE0 = 0;
0000094C E3A010FE MOV R1, #0xFE
00000950 E3811CFF ORR R1, R1, #0xFF00
00000954 E1D020B0 LDRH R2, [R0, #+0]
00000958 E0012002 AND R2, R1, R2
0000095C E1C020B0 STRH R2, [R0, #+0]
GPPOE_bit.GPPOE0 = 1;
00000960 E1D020B0 LDRH R2, [R0, #+0]
00000964 E3822001 ORR R2, R2, #0x1
00000968 E1C020B0 STRH R2, [R0, #+0]
GPPOE_bit.GPPOE0 = 0;
0000096C E1D020B0 LDRH R2, [R0, #+0]
00000970 E0012002 AND R2, R1, R2
00000974 E1C020B0 STRH R2, [R0, #+0]
.....

В итоге получается, что на каждый период приходится по 6-ть инструкций. Контроллер работает на частоте 60MHz, следовательно 6-ть инструкций должны выполнится за время (1/60*10^6)*6=10^(-7) секунд, т.е. 0,1 микросекунда или 10 МегаГерц. В итоге же, при запуске программы и подключения осцилографа к данному выводу, частота составляет 250 КГц (4 мксек). Не могу понять в чем причина. Может кто-нибудь знает, помогите пожалуйста разобраться.
Leen
А как это делается? Обрамление какое-нибудь есть? типа while(1) или чего-то в этом духе?
xoen
Конкретно это выглядит так (короче считываю строку длиной в 2048 байт в память)

//Enables use of extended keywords
#pragma language=extended

#include <inarm.h>
#include <arm_interrupt.h>

#include "ioml67q5003.h"

#include "system.h"
#include "types.h"
#include "led.h"
#include "ADC.h"
#include "uart.h"
#include "SRAM.h"
#include "DRAM.h"
#include "IRQ.h"
#include "watchdog.h"
#include "Commands.h"
#include "IRQ_Functions.h"

bool Irq_Flag = false;
bool Irq_Flag_Ver = false;
bool Irq_Flag_Hor = false;
bool scan_frame_flag = false;
bool ver_sync_irq = false;
bool hor_sync_irq = false;

int v_mode_x = 2048;
int v_mode_y = 1536;

int ver_delay = 1;
int hor_delay = 1;
long addr = 0;

int V_mode_y;

#pragma location=0xC0000000
__no_init char DRAM_buff [0x800000];


void Delay(int time);
void InitDevices();
void InitDRAM_buff();
void ReadLine(long address);
unsigned int install_handler (unsigned int *vector, unsigned int function);


void InitDevices()
{
InitFreq();
SysInit();

InitLED();
InitADC();
InitUART();
InitSRAM();
InitDRAM();
InitInterrupt();
InitWatchDog();
}

// IRQ handler
#pragma vector = 0x18
__irq __arm void irqHandler(void)
{
// UART request
if(IRQ_bit.IRQ9){
SelectMode();
ExtIRQ_Ack();
}

// vertical synchronization
if(IRQA_bit.IRQ26 && Irq_Flag && Irq_Flag_Ver){
Irq_Flag_Ver = false;

if (scan_frame_flag && ver_sync_irq){
ver_sync_irq = false;
hor_sync_irq = true;
V_mode_y = v_mode_y;
}
Delay(ver_delay);

ExtIRQ_Ack();
}

// horizontal synhronization
if(IRQA_bit.IRQ22 && Irq_Flag && Irq_Flag_Hor){
//if(GPPIE_bit.GPPIE5 != 1){ // while ver_synh is high do not make hor_synh interrupt
Irq_Flag_Hor = false;

if (scan_frame_flag && hor_sync_irq){
Delay(hor_delay);
ADC_Refresh(); // clear output of ADC

ReadLine(addr); // read line of data from REM display (line length is equal 2048 bytes)
addr += 2048;

V_mode_y -= 1; // read 1 line from REM displey
// if there was read all lines
if (V_mode_y == 0){
hor_sync_irq = false;
scan_frame_flag = false;
Irq_Flag = false;
TransmitByte(Ready); // acknowlegmenting of picture saving in DRAMemory
}
}
ExtIRQ_Ack();
//}
}
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma optimize=s 2
void main()
{
InitDevices(); // init all perepherial deviseces

install_handler(irqvec, (unsigned int)irqHandler);
__enable_interrupt();

LedOn(); // switch on LED

TransmitByte(Ack); // reset or start acknowledgement
AddLedOn(); // Switch on additional LED
InitDRAM_buff(); // inititialization external DARM buffer
AddLedOff(); // Switch off additional LED
TransmitByte(Ready); // reset or start acknowledgement

// main cycle
while(1){
Irq_Flag_Hor = true;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


// install interrupt vector
unsigned int install_handler (unsigned int *vector, unsigned int function)
{
unsigned int vec, old_vec;

vec = ((function - (unsigned int)vector - 8) >> 2);

old_vec = *vector;
vec |= 0xea000000; /* add opcode for B instruction */
*vector = vec;

old_vec &= ~0xea000000;
old_vec = ( old_vec << 2 ) + (unsigned int)vector + 8;

return(old_vec);
}

// make delay (time variable does not equal zero)
void Delay(int time){
while(--time != 0);
}

// initialization external DRAM
void InitDRAM_buff()
{
unsigned long i;

for(i=0; i<0x800000; i+=1){
DRAM_buff[i]='#';
}
}

// reading of one line from REM displey with length = 2048 bytes and save it to DRAM
void ReadLine(long address){
GPPOE_bit.GPPOE0 = 1;
GPPOE_bit.GPPOE0 = 0;
DRAM_buff[address + 0 ] = GPPIB;
GPPOE_bit.GPPOE0 = 1;
GPPOE_bit.GPPOE0 = 0;
DRAM_buff[address + 1 ] = GPPIB;
GPPOE_bit.GPPOE0 = 1;
GPPOE_bit.GPPOE0 = 0;
DRAM_buff[address + 2 ] = GPPIB;
....
DRAM_buff[address + 2048 ] = GPPIB;
}


Причем, если программа не прошита во flash контроллера, а запускается через отладочный кабель (Wiggler), то скороть выполнения возрастает в 10 раз ohmy.gif

Может быть проблема в конфигурационном файле для записи во флэш память?

//*************************************************************************
// Read-only segments mapped to ROM.
//*************************************************************************

//************************************************
// Address range for reset and exception
// vectors (INTVEC).
// The vector area is 32 bytes,
// an additional 32 bytes is allocated for the
// constant table used by ldr PC in cstartup.s79.
//************************************************

-Z(CODE)INTVEC=0-3F

//************************************************
// Startup code and exception routines (ICODE).
//************************************************

-Z(CODE)ICODE,DIFUNCT=40-7FFFF
-Z(CODE)SWITAB=40-7FFFF

//************************************************
// Code segments may be placed anywhere.
//************************************************

-Z(CODE)CODE=40-7FFFF

//************************************************
// Original ROM location for __ramfunc code copied
// to and executed from RAM.
//************************************************

-Z(CONST)CODE_ID=40-7FFFF

//************************************************
// Various constants and initializers.
//************************************************

-Z(CONST)INITTAB,DATA_ID,DATA_C=40-7FFFF
-Z(CONST)CHECKSUM=40-7FFFF

//*************************************************************************
// Read/write segments mapped to RAM.
//*************************************************************************

//************************************************
// Data segments.
//************************************************

-Z(DATA)DATA_I,DATA_Z,DATA_N=50000000-50007FFF

//************************************************
// __ramfunc code copied to and executed from RAM.
//************************************************

-Z(DATA)CODE_I=50000000-50007FFF

//************************************************
// ICCARM produces code for __ramfunc functions in
// CODE_I segments. The -Q XLINK command line
// option redirects XLINK to emit the code in the
// CODE_ID segment instead, but to keep symbol and
// debug information associated with the CODE_I
// segment, where the code will execute.
//************************************************

-QCODE_I=CODE_ID

//*************************************************************************
// Stack and heap segments.
//*************************************************************************

-Z(DATA)CSTACK+2000=50000000-50007FFF
-Z(DATA)IRQ_STACK+100=50000000-50007FFF
-Z(DATA)HEAP+8000=50000000-50007FFF


Для Wiggler-а у меня вот такой файл

//************************************************
// Inform the linker about the CPU family used.
//************************************************

-carm

//*************************************************************************
// Segment placement - General information
//
// All numbers in the segment placement command lines below are interpreted
// as hexadecimal unless they are immediately preceded by a '.', which
// denotes decimal notation.
//
// When specifying the segment placement using the -P instead of the -Z
// option, the linker is free to split each segment into its segment parts
// and randomly place these parts within the given ranges in order to
// achieve a more efficient memory usage. One disadvantage, however, is
// that it is not possible to find the start or end address (using
// the assembler operators .sfb./.sfe.) of a segment which has been split
// and reformed.
//
// When generating an output file which is to be used for programming
// external ROM/Flash devices, the -M linker option is very useful
// (see xlink.pdf for details).
//*************************************************************************


//*************************************************************************
// Read-only segments mapped to ROM.
//*************************************************************************

-DROMSTART=50000040
-DROMEND=50004000

//************************************************
// Address range for reset and exception
// vectors (INTVEC).
// The vector area is 32 bytes,
// an additional 32 bytes is allocated for the
// constant table used by ldr PC in cstartup.s79.
//************************************************

-Z(CODE)INTVEC=50000000-5000003F

//************************************************
// Startup code and exception routines (ICODE).
//************************************************

-Z(CODE)ICODE,DIFUNCT=ROMSTART-ROMEND
-Z(CODE)SWITAB=ROMSTART-ROMEND

//************************************************
// Code segments may be placed anywhere.
//************************************************

-Z(CODE)CODE=ROMSTART-ROMEND

//************************************************
// Original ROM location for __ramfunc code copied
// to and executed from RAM.
//************************************************

-Z(CONST)CODE_ID=ROMSTART-ROMEND

//************************************************
// Various constants and initializers.
//************************************************

-Z(CONST)INITTAB,DATA_ID,DATA_C=ROMSTART-ROMEND
-Z(CONST)CHECKSUM=ROMSTART-ROMEND

//*************************************************************************
// Read/write segments mapped to RAM.
//*************************************************************************

-DRAMSTART=50004000
-DRAMEND=50007FFF

//************************************************
// Data segments.
//************************************************

-Z(DATA)DATA_I,DATA_Z,DATA_N=RAMSTART-RAMEND

//************************************************
// __ramfunc code copied to and executed from RAM.
//************************************************

-Z(DATA)CODE_I=RAMSTART-RAMEND

//************************************************
// ICCARM produces code for __ramfunc functions in
// CODE_I segments. The -Q XLINK command line
// option redirects XLINK to emit the code in the
// CODE_ID segment instead, but to keep symbol and
// debug information associated with the CODE_I
// segment, where the code will execute.
//************************************************

-QCODE_I=CODE_ID

//*************************************************************************
// Stack and heap segments.
//*************************************************************************

-D_CSTACK_SIZE=2000
// -D_SVC_STACK_SIZE=10
-D_IRQ_STACK_SIZE=100
-D_HEAP_SIZE=8000

-Z(DATA)CSTACK+_CSTACK_SIZE=RAMSTART-RAMEND
// -Z(DATA)SVC_STACK+_SVC_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)IRQ_STACK+_IRQ_STACK_SIZE,HEAP+_HEAP_SIZE=RAMSTART-RAMEND
xoen
Не знаю мож кому и пригодится, вообщем я решил свою траблу: весь тупик был в том что программа полностью выполнялась из флэш, а не из RAM. Но это легко исправимо - перед функцией, которая должна выполняться из RAM нужно просто поставить директиву __ramfunc и все начнет работать очень быстро!
Leen
Ну, первое, что бросается в глаза:
Цитата
Причем, если программа не прошита во flash контроллера, а запускается через отладочный кабель (Wiggler), то скороть выполнения возрастает в 10 раз

Т.е. при работе из внутренней СРАМ получаем быстродействие в 4 раза ниже расчетного. При работе с флешки - в 40. Так? Возможно, при чтении памятей контроллер памяти вставляет не предусмотренные при расчете задержки (обычно они настраиваются в startup.s). Хотя в 40 раз???
Нет ли возможности, что контроллер уходит в прерывание с постоянной частотй, которая случайно совпала с частотой записи в порт? Можно ли на время работы функции запрещать прерывания?
Довольно банально, но, может, просто генератор настроен не на ту частоту? (Хотя это не объясняет 1).
Я бы попробовал так:
- запретил бы на время функции все без исключения прерывания (ну или те, которые не жалко);
- слинковать все в ОЗУ (внешнее, внутреннее), загрузить дебагером и посмотреть - может, во внешней раме будет еще одна частотаsmile.gif;
- прошел бы по шагам инициализацию генератора, ручками считая, что получается и сравнивая результат с тем, чего хочу;
- еще вариант - загрузить все в симулятор и посмотреть времена и трассу функций.
xoen
Мне тоже это бросилось в глаза, особенно когда запускал дебаггер и все работало на порядок быстрей, но строчка из конфига для линкера

//************************************************
// __ramfunc code copied to and executed from RAM.
//************************************************

-Z(DATA)CODE_I=50000000-50007FF

натолкнуло меня на неверную мысль, о том, что написанный мною код после запуска контроллера будет копироваться из флэш в СРАМ и выполняться оттуда. Про то что нужно перед функцией ставить __ramfunc, чтобы она загружалась с СРАМа я и не догадывался.

- На счет того чтобы запустить программу с внешней памяти: интересный вариант - туда можно будет запихнуть вообще весь код!

- А по поводу отключения прерываний: так оно и было, я тестировал все без прерываний, просто сам пример кода выложил как есть

- Говоря о настройках частоты работы контроллера, то там все правильно, и уже много раз проверено, ведь от частоты ядра и CCLK и HCLK, завиясят такие параметры как например скорость передачи по UART, а он у меня работает правильно - притом пользуюсь максимальной скоростью передачи в 921600

- А во сколько раз быстрее или медленнее выполняется код из разных типов памяти я скажу позже, когда сделаю замеры частоты на осцилографе, который сейчас у меня не под рукой smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.