We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
I've problems with the printf() routine. I receive frames over the ethernet in a very short intervall. If I received a frame I set a flag in the ISR.
void ethernet_interrupt(void) __irq { unsigned int status; AT91PS_EMAC pEmac = AT91C_BASE_EMAC; status = pEmac->EMAC_ISR; if (status & AT91C_EMAC_RCOM) /* Receive complete */ Emac_Receive++; // clear receive status register pEmac->EMAC_RSR &= ~(AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA); AT91C_BASE_AIC->AIC_EOICR = 0; /* End of ISR */ }
In the main routine I ask if the flag is set -> if it is set, I use printf() to see via the usart that I get a new frame...
printf("h");
The problem is that I always get a data abort within the printf() routine..
Could it be that the ethernet frames came to close together (in a short time) so that the printf() routine has not finish to transmit the last character?
And after the ISR the printf() routine don't know what to do / what to send -> data abort??
If the printf-argument is much bigger - it is often so that I only can transmit one or two letter - but not the whole word...
e.g.
printf("hello world\n");
I only transmit "hel" - that's all...
best regards Johannes
If your ARM supports a data-change breakpoint, then set such a breakpoint on the pointer and then run the program.
If it doesn't, then you have to figure this out manually. Is the pointer a global variable? Are there any array variables with lower address, so that a overrun will kill following variables?
Where is the stack in relation to this pointer? WÃll the stack grow into your variables?
Add test code to verify your pointer at a number of places in your program and run. Can you figure out that it always gets destroyed between two points, then narrow it down.
Or, it may be an interrupt handler that breaks it.
In other worlds, normal elbow grease...
Your goal is to figure out why your pointer is invalid, not where the data abort happens.
You don't care about which instruction that generates a data abort, since you already know that the data abort is caused by an invalid pointer. In short: Valid code is more or less expected to generate a data abort if you fail to fulfill the required preconditions.
Is the pointer a global variable?
Yes the pointer COM1_1 is a global variable so that I can reach it from the init_usart function and the COM1_1_sendchar() function.
Where is the stack in relation to this pointer? WÃÂll the stack grow into your variables?
Where can I see how big the stack is within the programm runs? Or if a overflow occured?
Johannes
You are reading the documentation for the Keil compiler, and the documentation for your processor? As I said, it is time for some elbow grease - yours, not mine.
another problem - maybe you have a answer... now I have disabled the whole ethernet-story - so I get no data abort but when I write printf("hello world\n"); -> I only get "hello worl" and the \n but not the last character - unindependent how long the printf message is...
Your implementation sends a single character at a time to the UART. printf() will return as soon as the last character has sent to the UART. But the character has not been sent out on the cable yet.
Do you do anything hurtful directly after the printf() call - such as changing baudrate, or turning off the power to the UART?
that's the whole code + the retarget function...
int COM1_1_sendchar(int ch); unsigned int Emac_Receive = 0; unsigned int buffer = 0, overrun = 0; #define MCK 60000000 /* Clock-Rate für USART */ AT91PS_USART COM1_1 = AT91C_BASE_US1; /* Variable COM1 für die Struct _AT91S_USART definieren */ void initialize_usart1() { AT91F_PIO_CfgPeriph(AT91C_BASE_PIOB,AT91C_PB21_RXD1 | AT91C_PB20_TXD1,0); AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<<AT91C_ID_US1 ) ; AT91F_US_Configure (COM1_1, MCK,AT91C_US_ASYNC_MODE, 115200, 0); COM1_1->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; // AT91F_US_EnableIt(COM1_1, AT91C_US_TXRDY); //enable AT91C_US_TXRDY interrupt } int main(void) { // int status; initialize_usart1(); printf("usart_init\n"); printf("done\n"); // status = ethernet(); /* Ethernet */ printf("Emac init\n"); while(1); }
You often post code that doesn't match your descriptive text - or text that doesn't match your code.
Can we be sure that you really check if the UART is ready before you insert the character? The '\n' part is special, since you make two inserts in your function.
If the first insert (the '\r') is done before the UART is ready, it may/will kill the character directly before the '\n' in the input string.
is the usart init not ready, when I am able to run the first printf("usart_init\n")? Or how can I make sure, that the usart is really able to transmit all characters?
initialize_usart1(); printf("usart_init\n");
Read my text again. I'm not talking about if the USART is ready after the initialize_usart1() call. I'm talking about if the USART is ready for the '\r' character that you insert before every '\n' character.
ok I figured out, that everything works fine, when I only init usart and ethernet - but when a interrupt from the ethernet occured - COM1_1 don't work...
while(1) { if(Emac_Receive >= 1) printf("%x\n", COM1_1); }
Emac_Receive is higher than 1 when a interrupt occured...
then I only get "fff" or "fffc4" - always the beginning of the right address but not the whole address which is 0xFFFC4000
no the '\r' is not the problem
while (!(COM1_1->US_CSR & AT91C_US_TXRDY)) { if(COM1_1 != AT91C_BASE_US1) i++; <- data abort } return (COM1_1->US_THR = ch);
there must be something wrong with the interrupt and the prinft together...
Are you not talking about two separate problems?
One problem is that you loose the last character before '\n'.
One problem is that when you build with Ethernet, your comport pointer gets corrupted and you get a data abort.
right - but the first problem should be solved... that I lost the last character bevor \n -> maybe, the problem was a false heather which was included...
right - the problem happens only when I use the MAC interrupts... I don't know what's the reason for - I have no arrays (the buffer for the ethernet packets are safed in the external sdram..
Increase stack