Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7X256 и Keil Vision 3V3.20a
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Limp
Вот мой код:
Использую Keil Vision 3V3.20a



#include <AT91SAM7X256.H> /* AT91SAMT7X256 definitions */
#include <lib_AT91SAM7X256.h>
#include "Board.h"
#define WAIT_TIME AT91B_MCK

#define PIO_INTERRUPT_LEVEL 6

void pio_c_irq_handler (void) __irq
{
int dummy;

//* Read the output state
if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOB) & AT91B_LED2 ) == AT91B_LED2 )
{
AT91F_PIO_ClearOutput( AT91C_BASE_PIOB, AT91B_LED2);
}
else
{
AT91F_PIO_SetOutput( AT91C_BASE_PIOB, AT91B_LED2);
}

//* enable the next PIO IRQ

dummy =AT91C_BASE_PIOA->PIO_ISR;
//* suppress the compilation warning
dummy =dummy;
AT91C_BASE_AIC->AIC_EOICR=0x00;

//* while SW3 is push wait
// while ( (AT91F_PIO_GetInput(AT91C_BASE_PIOA) & AT91B_SW5 ) != AT91B_SW5 );

}


void delay ( void )
{
volatile unsigned int i ;

for ( i = 0 ;(i < WAIT_TIME/100 );i++ ) ;
}

//*----------------------------------------------------------------------------
//* Function Name : main
//* Object : Main interrupt function
//* Input Parameters : none
//* Output Parameters : TRUE
//*----------------------------------------------------------------------------
int main( void )
//* Begin
{
// unsigned int loop_count ;
AT91PS_AIC pAic;
//* Load System pAic Base address
pAic = AT91C_BASE_AIC;



//* Init
// loop_count = 0 ;
// First, enable the clock of the PIOB
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOB ) ;
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA ) ;

AT91F_PIO_CfgOutput( AT91C_BASE_PIOB, AT91B_LED_MASK ) ;
AT91F_PIO_CfgInput(AT91C_BASE_PIOA, AT91B_SW5 | AT91B_SW4);
AT91F_AIC_ConfigureIt ( pAic, AT91C_ID_PIOA, PIO_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);
AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,AT91B_SW4);
AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA);
AT91F_PIO_SetOutput( AT91C_BASE_PIOB, AT91B_LED_MASK ) ;



for (;;)
{
AT91F_PIO_ClearOutput( AT91C_BASE_PIOB, AT91B_LED1 );
delay () ;
AT91F_PIO_SetOutput( AT91C_BASE_PIOB, AT91B_LED1 );
delay () ;


}

//* End
}


Вот мой Startup:

// Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F

I_Bit EQU 0x80 /* when I bit is set, IRQ is disabled */
F_Bit EQU 0x40 /* when F bit is set, FIQ is disabled */


// Internal Memory Base Addresses
FLASH_BASE EQU 0x00100000
RAM_BASE EQU 0x00200000


/*
// <h> Stack Configuration (Stack Sizes in Bytes)
// <o0> Undefined Mode <0x0-0xFFFFFFFF:4>
// <o1> Supervisor Mode <0x0-0xFFFFFFFF:4>
// <o2> Abort Mode <0x0-0xFFFFFFFF:4>
// <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:4>
// <o4> Interrupt Mode <0x0-0xFFFFFFFF:4>
// <o5> User/System Mode <0x0-0xFFFFFFFF:4>
// </h>
*/
UND_Stack_Size EQU 0x00000004
SVC_Stack_Size EQU 0x00000004
ABT_Stack_Size EQU 0x00000004
FIQ_Stack_Size EQU 0x00000004
IRQ_Stack_Size EQU 0x00000080
USR_Stack_Size EQU 0x00000400

AREA STACK, DATA, READWRITE, ALIGN=2
DS (USR_Stack_Size+3)&~3 ; Stack for User/System Mode
DS (SVC_Stack_Size+3)&~3 ; Stack for Supervisor Mode
DS (IRQ_Stack_Size+3)&~3 ; Stack for Interrupt Mode
DS (FIQ_Stack_Size+3)&~3 ; Stack for Fast Interrupt Mode
DS (ABT_Stack_Size+3)&~3 ; Stack for Abort Mode
DS (UND_Stack_Size+3)&~3 ; Stack for Undefined Mode
Top_Stack:


// Embedded Flash Controller (EFC) definitions
EFC_BASE EQU 0xFFFFFF00 /* EFC Base Address */
EFC_FMR EQU 0x60 /* EFC_FMR Offset */

/*
// <e> Embedded Flash Controller (EFC)
// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
// <i> Number of Master Clock Cycles in 1us
// <o1.8..9> FWS: Flash Wait State
// <0=> Read: 1 cycle / Write: 2 cycles
// <1=> Read: 2 cycle / Write: 3 cycles
// <2=> Read: 3 cycle / Write: 4 cycles
// <3=> Read: 4 cycle / Write: 4 cycles
// </e>
*/
EFC_SETUP EQU 1
EFC_FMR_Val EQU 0x00320100


// Watchdog Timer (WDT) definitions
WDT_BASE EQU 0xFFFFFD40 /* WDT Base Address */
WDT_MR EQU 0x04 /* WDT_MR Offset */

/*
// <e> Watchdog Timer (WDT)
// <o1.0..11> WDV: Watchdog Counter Value <0-4095>
// <o1.16..27> WDD: Watchdog Delta Value <0-4095>
// <o1.12> WDFIEN: Watchdog Fault Interrupt Enable
// <o1.13> WDRSTEN: Watchdog Reset Enable
// <o1.14> WDRPROC: Watchdog Reset Processor
// <o1.28> WDDBGHLT: Watchdog Debug Halt
// <o1.29> WDIDLEHLT: Watchdog Idle Halt
// <o1.15> WDDIS: Watchdog Disable
// </e>
*/
WDT_SETUP EQU 1
WDT_MR_Val EQU 0x00008000


// Power Mangement Controller (PMC) definitions
PMC_BASE EQU 0xFFFFFC00 /* PMC Base Address */
PMC_MOR EQU 0x20 /* PMC_MOR Offset */
PMC_MCFR EQU 0x24 /* PMC_MCFR Offset */
PMC_PLLR EQU 0x2C /* PMC_PLLR Offset */
PMC_MCKR EQU 0x30 /* PMC_MCKR Offset */
PMC_SR EQU 0x68 /* PMC_SR Offset */
PMC_MOSCEN EQU (1<<0) /* Main Oscillator Enable */
PMC_OSCBYPASS EQU (1<<1) /* Main Oscillator Bypass */
PMC_OSCOUNT EQU (0xFF<<8) /* Main OScillator Start-up Time */
PMC_DIV EQU (0xFF<<0) /* PLL Divider */
PMC_PLLCOUNT EQU (0x3F<<8) /* PLL Lock Counter */
PMC_OUT EQU (0x03<<14) /* PLL Clock Frequency Range */
PMC_MUL EQU (0x7FF<<16) /* PLL Multiplier */
PMC_USBDIV EQU (0x03<<28) /* USB Clock Divider */
PMC_CSS EQU (3<<0) /* Clock Source Selection */
PMC_PRES EQU (7<<2) /* Prescaler Selection */
PMC_MOSCS EQU (1<<0) /* Main Oscillator Stable */
PMC_LOCK EQU (1<<2) /* PLL Lock Status */

/*
// <e> Power Mangement Controller (PMC)
// <h> Main Oscillator
// <o1.0> MOSCEN: Main Oscillator Enable
// <o1.1> OSCBYPASS: Oscillator Bypass
// <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255>
// </h>
// <h> Phase Locked Loop (PLL)
// <o2.0..7> DIV: PLL Divider <0-255>
// <o2.16..26> MUL: PLL Multiplier <0-2047>
// <i> PLL Output is multiplied by MUL+1
// <o2.14..15> OUT: PLL Clock Frequency Range
// <0=> 80..160MHz <1=> Reserved
// <2=> 150..220MHz <3=> Reserved
// <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63>
// <o2.28..29> USBDIV: USB Clock Divider
// <0=> None <1=> 2 <2=> 4 <3=> Reserved
// </h>
// <o3.0..1> CSS: Clock Source Selection
// <0=> Slow Clock
// <1=> Main Clock
// <2=> Reserved
// <3=> PLL Clock
// <o3.2..4> PRES: Prescaler
// <0=> None
// <1=> Clock / 2 <2=> Clock / 4
// <3=> Clock / 8 <4=> Clock / 16
// <5=> Clock / 32 <6=> Clock / 64
// <7=> Reserved
// </e>
*/
PMC_SETUP EQU 1
PMC_MOR_Val EQU 0x00000601
PMC_PLLR_Val EQU 0x00191C05
PMC_MCKR_Val EQU 0x00000007


$IF (RAM_INTVEC)
// Exception Vector Area in RAM
AREA VECTORS, DATA, AT RAM_BASE
DS 64
$ENDIF


// Startup Code must be linked at address which it expects to run.

$IF (RAM_MODE)
CODE_BASE EQU RAM_BASE
$ELSE
CODE_BASE EQU FLASH_BASE
$ENDIF

AREA STARTUPCODE, CODE, AT CODE_BASE
PUBLIC __startup

EXTERN CODE32 (?C?INIT)

__startup PROC CODE32

// Pre-defined interrupt handlers that may be directly
// overwritten by C interrupt functions
EXTERN CODE32 (Undef_Handler?A)
EXTERN CODE32 (SWI_Handler?A)
EXTERN CODE32 (PAbt_Handler?A)
EXTERN CODE32 (DAbt_Handler?A)
;EXTERN CODE32 (IRQ_Handler?A)
;EXTERN CODE32 (FIQ_Handler?A)

// Exception Vectors
// Mapped to Address 0.
// Absolute addressing mode must be used.

Vectors: LDR PC,Reset_Addr
LDR PC,Undef_Addr
LDR PC,SWI_Addr
LDR PC,PAbt_Addr
LDR PC,DAbt_Addr
NOP /* Reserved Vector */
; LDR PC,IRQ_Addr
LDR PC,[PC,#-0xF20] /* Vector From AIC_IVR */
; LDR PC,FIQ_Addr
LDR PC,[PC,#-0xF20] /* Vector From AIC_FVR */

Reset_Addr: DD Reset_Handler
Undef_Addr: DD Undef_Handler?A
SWI_Addr: DD SWI_Handler?A
PAbt_Addr: DD PAbt_Handler?A
DAbt_Addr: DD DAbt_Handler?A
DD 0 /* Reserved Address */
;IRQ_Addr: DD IRQ_Handler?A
IRQ_Addr: DD 0
;FIQ_Addr: DD FIQ_Handler?A
FIQ_Addr: DD 0


// Reset Handler

Reset_Handler:


// Setup EFC
IF (EFC_SETUP != 0)
LDR R0, =EFC_BASE
LDR R1, =EFC_FMR_Val
STR R1, [R0, #EFC_FMR]
ENDIF


// Setup WDT
IF (WDT_SETUP != 0)
LDR R0, =WDT_BASE
LDR R1, =WDT_MR_Val
STR R1, [R0, #WDT_MR]
ENDIF


// Setup PMC
IF (PMC_SETUP != 0)
LDR R0, =PMC_BASE

// Setup Main Oscillator
LDR R1, =PMC_MOR_Val
STR R1, [R0, #PMC_MOR]

// Wait until Main Oscillator is stablilized
IF ((PMC_MOR_Val & PMC_MOSCEN) != 0)
MOSCS_Loop: LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MOSCS
BEQ MOSCS_Loop
ENDIF

// Setup the PLL
IF ((PMC_PLLR_Val & PMC_MUL) != 0)
LDR R1, =PMC_PLLR_Val
STR R1, [R0, #PMC_PLLR]

// Wait until PLL is stabilized
PLL_Loop: LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_LOCK
BEQ PLL_Loop
ENDIF

// Select Clock
LDR R1, =PMC_MCKR_Val
STR R1, [R0, #PMC_MCKR]
ENDIF


// Copy Exception Vectors to Internal RAM

$IF (RAM_INTVEC)
ADR R8, Vectors ; Source
LDR R9, =RAM_BASE ; Destination
LDMIA R8!, {R0-R7} ; Load Vectors
STMIA R9!, {R0-R7} ; Store Vectors
LDMIA R8!, {R0-R7} ; Load Handler Addresses
STMIA R9!, {R0-R7} ; Store Handler Addresses
$ENDIF


// Remap on-chip RAM to address 0

MC_BASE EQU 0xFFFFFF00 /* MC Base Address */
MC_RCR EQU 0x00 /* MC_RCR Offset */

$IF (REMAP)
LDR R0, =MC_BASE
MOV R1, #1
STR R1, [R0, #MC_RCR] ; Remap
$ENDIF


// Setup Stack for each mode
LDR R0, =Top_Stack

// Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size

// Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size

// Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size

// Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size

// Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size

// Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_USR
MOV SP, R0

// Enter the C code
LDR R0,=?C?INIT
TST R0,#1 ; Bit-0 set: main is Thumb
LDREQ LR,=exit?A ; ARM Mode
LDRNE LR,=exit?T ; Thumb Mode
BX R0
ENDP

PUBLIC exit?A
exit?A PROC CODE32
B exit?A
ENDP

PUBLIC exit?T
exit?T PROC CODE16
B exit?T
ENDP

END


Компилирую, получаю hex-файл. С помощью HEX2BIN получаю бинарник. Гружу в плату AT91SAM7256-EK c помощью самбы. Стартую с 0x100000. Запускается. Мигает диодик. При нажатии джостика программа зависает, второй диод не загорается. В симуляторе (других отладчиков нет) все прекрасно работает. Прерывание отрабатывается и происходит возвращение в основной цикл. Почему не работает в железе? Пожалуйста, подскажите если кто знает.
aaarrr
Вы пытаетесь скопировать вектора прерываний в область ROM, что, естественно, не выходит. Сделайте Remap.

P.S. Пользуйтесь тегами [сode][/сode] - читать невозможно.
Limp
Цитата(aaarrr @ Mar 18 2008, 16:53) *
Вы пытаетесь скопировать вектора прерываний в область ROM, что, естественно, не выходит. Сделайте Remap.

P.S. Пользуйтесь тегами [сode][/сode] - читать невозможно.


Пожалуйста, можно подробнее? Где я пытаюсь скопировать вектор прерывания в область ROM и как сделать Remap. Я, знаете ли, только осваиваю технику и хочется быстро освоить.
aaarrr
Цитата(Limp @ Mar 18 2008, 17:01) *
Пожалуйста, можно подробнее? Где я пытаюсь скопировать вектор прерывания в область ROM и как сделать Remap. Я, знаете ли, только осваиваю технику и хочется быстро освоить.

Как выяснилось, даже не пытаетесь копировать smile.gif Вам нужно добавить строки:
Код
RAM_INTVEC    EQU 1
REMAP    EQU 1
в начале startup'а. После remap'а SRAM встанет по нулевому адресу, и вектора окажутся на своем месте.
Limp
Цитата(aaarrr @ Mar 18 2008, 17:10) *
Как выяснилось, даже не пытаетесь копировать smile.gif Вам нужно добавить строки:
Код
RAM_INTVEC    EQU 1
REMAP    EQU 1
в начале startup'а. После remap'а SRAM встанет по нулевому адресу, и вектора окажутся на своем месте.


Не знаю как Вас благодарить!!! Огромное СПАСИБО!!! Заработало!!!
Limp
У меня опять проблема.
Делаю на плате кнопочкой RESET. Программа перестает работать.
В изложенную выше программу в main() добавил функцию:
AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN |(0x4<<8) | (unsigned int)(0xA5<<24);
Или опять проблема с Startup? По идее программа после ресета должна заработать снова, ведь прерывания отрабатываются.
aaarrr
Цитата(Limp @ Mar 20 2008, 16:42) *
У меня опять проблема.

А GPNVM2 в Самбе запрограммировать не забыли?
Limp
Цитата(aaarrr @ Mar 20 2008, 16:52) *
А GPNVM2 в Самбе запрограммировать не забыли?

Забыл, потому что первый раз слышу о GPNVM2 в Самбе.
Намекните с чем ее едят?
aaarrr
Внизу есть окошко "scripts", в нем на первом месте стоит "Boot from Flash (GPNVM2)" - его и нужно выполнить. А так у Вас процессор стартует из ROM по сбросу.
Limp
Цитата(aaarrr @ Mar 20 2008, 17:33) *
Внизу есть окошко "scripts", в нем на первом месте стоит "Boot from Flash (GPNVM2)" - его и нужно выполнить. А так у Вас процессор стартует из ROM по сбросу.


И снова БОЛЬШОЕ Вам спасибо!!! Вы мне очень помогли!!!
В моей доке о SAMBA нет ни слова о "Boot from Flash (GPNVM2)".
Еще раз спасибо!!!
Но тут происходит интересный момент по сбросу программа сразу же вылетает в обработчик прерывания void pio_c_irq_handler (void) __irq. Очевидно по сбросу ловит перепад на PIOA.
aaarrr
Это вполне возможно. Прерывание лучше сбрасывать непосредственно перед разрешением.
Limp
Цитата(aaarrr @ Mar 21 2008, 11:31) *
Это вполне возможно. Прерывание лучше сбрасывать непосредственно перед разрешением.


Блогадарю Вас за поддержку. С этим я уже разобрался. Разбираюсь дальше. Думаю, что вопросы еще у меня возникнут и надеюсь, что Вы в дальнейшем мне поможите своими советами. Спасибо!
Limp
От чего так происходит?
Плата подключена к компу через DBGU. (AT91SAM7X256-EK)
Собственно обмен происходит, как из компа в плату так из платы в комп.
Но вот в основном цикле платы надо послать 4 байта подряд в комп:

AT91C_BASE_DBGU->DBGU_THR = 0x41;

while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))

AT91C_BASE_DBGU->DBGU_THR = 0x54;

while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))

AT91C_BASE_DBGU->DBGU_THR = 0x41;

while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))

AT91C_BASE_DBGU->DBGU_THR = 0x0D;


В компе принимается один или два байта. Два байта пропадают? Почему?
Когда после операторов while ставлю задержку, например, delay (), комп принимает все четыре байта.
Скорость передачи как для платы, так и для компа 115200.
При этом при передаче данных из компа в плату нескольких байт подряд проблем нет, прием данных производится в обработчике прерывания приемника DBGU.
В обработчике прерываний при передаче из платы в комп ни чего не делаю, просто вываливаюсь, предварительно произведя AT91C_BASE_AIC->AIC_EOICR=0x00;
ljerry
Цитата(Limp @ Mar 28 2008, 11:28) *
От чего так происходит?
Плата подключена к компу через DBGU. (AT91SAM7X256-EK)
Собственно обмен происходит, как из компа в плату так из платы в комп.
Но вот в основном цикле платы надо послать 4 байта подряд в комп:

AT91C_BASE_DBGU->DBGU_THR = 0x41;

while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))

AT91C_BASE_DBGU->DBGU_THR = 0x54;

while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))

AT91C_BASE_DBGU->DBGU_THR = 0x41;

while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))

AT91C_BASE_DBGU->DBGU_THR = 0x0D;


В компе принимается один или два байта. Два байта пропадают? Почему?
Когда после операторов while ставлю задержку, например, delay (), комп принимает все четыре байта.
Скорость передачи как для платы, так и для компа 115200.
При этом при передаче данных из компа в плату нескольких байт подряд проблем нет, прием данных производится в обработчике прерывания приемника DBGU.
В обработчике прерываний при передаче из платы в комп ни чего не делаю, просто вываливаюсь, предварительно произведя AT91C_BASE_AIC->AIC_EOICR=0x00;


После while(...) надо точку с запятой ставить smile.gif Вот так:
Код
  while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));


А то у Вас получается следующий код:

Код
AT91C_BASE_DBGU->DBGU_THR = 0x41;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
{
  AT91C_BASE_DBGU->DBGU_THR = 0x54;
}
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
{
  AT91C_BASE_DBGU->DBGU_THR = 0x41;
}
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
{
  AT91C_BASE_DBGU->DBGU_THR = 0x0D;
}

Удачи!
Limp
Цитата(ljerry @ Mar 28 2008, 11:39) *
После while(...) надо точку с запятой ставить smile.gif Вот так:
Код
  while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));


А то у Вас получается следующий код:

Код
AT91C_BASE_DBGU->DBGU_THR = 0x41;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
{
  AT91C_BASE_DBGU->DBGU_THR = 0x54;
}
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
{
  AT91C_BASE_DBGU->DBGU_THR = 0x41;
}
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
{
  AT91C_BASE_DBGU->DBGU_THR = 0x0D;
}

Удачи!


Надо же, как меня перемкнуло!!! Надо отвлекаться иногда....
СПАСИБО!!!
Limp
Опять проблема с DBGU.
Посылаю байт и тут же вывожу количество принятых байт.
Вот обработчик прерывания:

void Uart_dbgu_irq_handler()__irq
{
if ((pDBGU->DBGU_CSR & AT91C_US_RXRDY))
{
count_byte++;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = count_byte;
}
pDBGU->DBGU_CR = AT91C_US_RSTSTA;
AT91C_BASE_AIC->AIC_EOICR=0x00;
}
При передаче даже одного байта, происходит постоянный вызов обработчика прерывания, соответственно бесконечно плюсуется count_byte. То есть не происходит сброс прерывания, но я ведь это делаю AT91C_BASE_AIC->AIC_EOICR=0x00 или что-то нужно еще?
Кстати, в USART та же картина.
aaarrr
Нужно прочитать DBGU_RHR.
Limp
Цитата(aaarrr @ Mar 31 2008, 15:41) *
Нужно прочитать DBGU_RHR.


Да, действительно, затормозило.
Но вот от чего весь сыр бор:
void Uart_dbgu_irq_handler()__irq
{

if ((pDBGU->DBGU_CSR & AT91C_US_RXRDY)) /* Wait for Full Rx Buffer */
{
count_byte++;
if(count_byte<5)
{
zumer[0]=zumer[0]<<8 | pDBGU->DBGU_RHR;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = zumer[0];
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = count_byte;
}

}

pDBGU->DBGU_CR = AT91C_US_RSTSTA;
AT91C_BASE_AIC->AIC_EOICR=0x00;
}
Посылаю данные: d;4;5;6;7;8;9;a;b;c;d
Получаю назад такую картину:
D 1
4 2
5 3
6 4
7 0
8 1
9 2
A 3
B 4
C 0
D 1
Почему когда выполнится условие, count_byte сбрасывается в ноль и портит мне настроение. 07.gif
Для полной картины:
count_byte описан как глобальная unsigned char и обнуляется в main(), в самом начале и все, дальше бесконечный цикл.
в файле uart.c, где у меня обработчик прерываня пишу extern unsigned char count_byte.
aaarrr
Цитата(Limp @ Mar 31 2008, 16:13) *
Почему когда выполнится условие, count_byte сбрасывается в ноль и портит мне настроение. 07.gif

Потому что при count_byte >= 5 перестает считываться DBGU_RHR. Что происходит дальше, надеюсь, понятно.
Limp
Цитата(aaarrr @ Mar 31 2008, 16:19) *
Потому что при count_byte >= 5 перестает считываться DBGU_RHR. Что происходит дальше, надеюсь, понятно.


Понятно. Спасибо aaarrr.
Когда перестает считывать DBGU_RHR, постоянно влетает в обработчик и count_byte переполняется и обнуляется и т.д. Хреново. Как же все это затормозить?
aaarrr
Прерывание запретить, например. А чего Вы хотите добиться в конечном итоге?
Limp
Цитата(aaarrr @ Mar 31 2008, 16:39) *
Прерывание запретить, например. А чего Вы хотите добиться в конечном итоге?

Да в приципе почти уже добился своего. В обработике надо записать 8 байт, по 4 в два 32 разрядных слова, потом сравнить с требуемыми константами. Приблизительно так как показывал выше. Еще конкретнее это АТ команда от модема. Пробую всякие варианты, вот и возникают всякие непонятки. Дело в том, что может зациклиться если придет более 8 байт.

if(count_byte<5)
{
zumer[0]=zumer[0]<<8 | pDBGU->DBGU_RHR;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = zumer[0];
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = count_byte;
}
if(4<=count_byte && count_byte<9 )
{
zumer[1]=zumer[1]<<8 | pDBGU->DBGU_RHR;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = zumer[1];
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = count_byte;
}
if(zumer[0] == 0x0D0A5249 && zumer[1]== 0x4E470D0A)
.
.
.
Получаю
D 1
A 2
52 3
49 4 49 4 07.gif
4E 5
47 6
D 7
A 8

Спасибо aaarrr. Учту ваше замечание.
aaarrr
У Вас условия накладываются:
Цитата(Limp @ Mar 31 2008, 16:57) *
if(count_byte<5)
...
if(4<=count_byte && count_byte<9 )


Прием AT-команд лучше так не делать. Правильнее будет в прерывании записать строку в буфер, контроллируя конец строки по 0x0d 0x0a, а затем спокойно разобрать её в основной программе.
Limp
Цитата(aaarrr @ Mar 31 2008, 16:17) *
У Вас условия накладываются:
Прием AT-команд лучше так не делать. Правильнее будет в прерывании записать строку в буфер, контроллируя конец строки по 0x0d 0x0a, а затем спокойно разобрать её в основной программе.


Спасибо. Сделаю.
Limp
Всем доброго дня!
Прошу снова помощи.
Для обучения и отладки обмена по СОМ порту использовал плату AT91SAM7x-EK.
Использовал готовые примеры кода.
Обмен проходит нормально и собственно проблем нет. Но...
Наши разработчики сделали свое устройство на базе AT91SAM7x256 где заложили кварц с частотой 14745600. В плате AT91SAM7x-EK кварц с частотой, если не ошибаюсь, 18432000. Естественно, обмен по СОМ порту в доморощенном устройстве не выполняется.

Использую следующие для настройки скорости передачи данных.

#define BRD (MCK/16/BR) /* Baud Rate Divisor */
#define BR 115200 /* Baud Rate */
#define MCK 47923200 // MCK (PLLRC div by 2)
#define AT91B_MAIN_OSC 18432000 // Main Oscillator MAINCK

pUSART->US_BRGR = BRD; /* Baud Rate Divisor */

Теперь вопрос:
Откуда берется или как вычисляется значение #define MCK 47923200 ?

Пожалуйста, подскажите! help.gif
aaarrr
Цитата(Limp @ May 28 2008, 10:59) *
Откуда берется или как вычисляется значение #define MCK 47923200 ?

Смотрите настройку PLL, число приходит оттуда. После замены кварца на 14.745M значение MCK должно быть 38338560.
Limp
Цитата(aaarrr @ May 28 2008, 10:12) *
Смотрите настройку PLL, число приходит оттуда. После замены кварца на 14.745M значение MCK должно быть 38338560.


Уважаемый, aaarrr!
Посмотрел настройку своего PLL, она у меня производится в стартапе (см. самое мое первое сообщение).

Надо полагать, что МСК-> (18432000*(25+1)/5)/2=47923200.
Для другого кварца: МСК-> (14745600*(25+1)/5)/2=38338560.

Не пойму, почему выбирается именно MUL=25, а DIV=5 ?
К сожалению установив #define MCK 38338560 и #define AT91B_MAIN_OSC 14745600 обмен так и не заработал.
aaarrr
Цитата(Limp @ May 28 2008, 14:40) *
Не пойму, почему выбирается именно MUL=25, а DIV=5 ?

Выбрали, подгоняя выходную частоту к 48.0МГц.

Цитата(Limp @ May 28 2008, 14:40) *
К сожалению установив #define MCK 38338560 и #define AT91B_MAIN_OSC 14745600 обмен так и не заработал.

Правильно не заработал: делитель для скорости 115200 чуть-чуть не дотягивает до 21 (20.8), если при его вычислении не используется округления, то получится очень большая ошибка.
Limp
Цитата(aaarrr @ May 28 2008, 13:53) *
Выбрали, подгоняя выходную частоту к 48.0МГц.
Правильно не заработал: делитель для скорости 115200 чуть-чуть не дотягивает до 21 (20.8), если при его вычислении не используется округления, то получится очень большая ошибка.


Прошу прощения за свою тупость smile.gif , но можно чуть подробнее о "делитель для скорости 115200 чуть-чуть не дотягивает до 21 (20.8), если при его вычислении не используется округления, то получится очень большая ошибка" ?
aaarrr
Очень просто все:
Код
#define BRD (MCK/16/BR) /* Baud Rate Divisor */

Даст BRD=20 из-за отсутствия округления - (int)20.8=20.

Для того, чтобы избежать этой неприятности, сделайте так:
Код
#define BRD ((MCK + BR * 8)/16/BR)
Limp
Цитата(aaarrr @ May 28 2008, 14:52) *
Очень просто все:
Код
#define BRD (MCK/16/BR) /* Baud Rate Divisor */

Даст BRD=20 из-за отсутствия округления - (int)20.8=20.

Для того, чтобы избежать этой неприятности, сделайте так:
Код
#define BRD ((MCK + BR * 8)/16/BR)


Дало 21.3 Но увы! Не заработало. Процессор виснет, когда посылаю ему команду.
aaarrr
Если виснет, то это во всяком случае со скоростью UART'а никак не связано.
Limp
Цитата(aaarrr @ May 28 2008, 15:14) *
Если виснет, то это во всяком случае со скоростью UART'а никак не связано.


Дело в том, что в основном цикле мигает диод. Т.е. программа загружается и запускается. Посылка байта от ПЭВМ обрабатывается по прерыванию USART. Те команды которые я посылаю отработаны на плате AT91SAM7X-EK и проц ни когда не зависал. Тут я уверен на 100%. А вот на доморощенной диод перестает мигать как только посылаю команду.
aaarrr
Странно как-то. А программы, за исключением делителя UART, одинаковые?
Limp
Цитата(aaarrr @ May 28 2008, 15:50) *
Странно как-то. А программы, за исключением делителя UART, одинаковые?


Один к одному.

Было:
#define AT91B_MAIN_OSC 18432000 // Main Oscillator MAINCK
#define AT91B_MCK ((18432000*73/14)/2) // Output PLL Clock
#define MCK 47923200 // MCK (PLLRC div by 2)

#define BRD (MCK/16/BR) /* Baud Rate Divisor */
#define BR 115200 /* Baud Rate */

Стало:
#define AT91B_MAIN_OSC 14745600//18432000 // Main Oscillator MAINCK
#define AT91B_MCK ((14745600*73/14)/2) //((18432000*73/14)/2) // Output PLL Clock
#define MCK 38338560 //47923200 // MCK (PLLRC div by 2)

//#define BRD (MCK/16/BR) /* Baud Rate Divisor */
#define BRD ((MCK + BR * 8)/16/BR)
#define BR 115200 /* Baud Rate */
aaarrr
Цитата(Limp @ May 28 2008, 16:56) *
Один к одному.

Значит программа может зависнуть при приеме содержащей ошибки команды, например.
Попробуйте просто эхо на UART'е сделать.

Снаружи процессор только светодиодом ворочает? Ошибок в железе быть не может?
Limp
Цитата(aaarrr @ May 28 2008, 16:03) *
Значит программа может зависнуть при приеме содержащей ошибки команды, например.
Попробуйте просто эхо на UART'е сделать.

Снаружи процессор только светодиодом ворочает? Ошибок в железе быть не может?


Уважаемый, aaarrr!
Загляните в личку.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.