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'm working with the AT91RM9200 from Atmel and I have some problems with data abort. The stack size is big enough. I tested it by making the user stack size zero and see which errors now occured. Everything was overwritten by other things. At the moment my stack size is 0x00000200. The error which occured is that the ptr to the usart base address is overwritten either if the usart.o is stored in the internal ram or the external ram. I use the watch window to see if the ptr would change his value - but nothing happens. I only know that the value is changed because I set a dummy within the retarget function for printf() - (thanks for the hint Per).
The whole programm only includes the ethernet init part, the usart and retarget function in separate c-files. So I have one main file with only the main routine where I init all other functions by calling the right function. In the while loop (main.c) I only poll if a flag is set by receiving a new frame by the ethernet. This works with the data abort problems.
These problems don't appear always at the same part of code. Is my acceptance right, that if I would have a stack size problem, the error would occurred always at the same part of code?
When I test the whole programm several times, I have one or two passes where no error occured. Very often the error happened bevor I call the init function for the ethernet part. So I don't think there would be a error during the execution of the code. I think the error could / must be very global. If I don't include the ethernet part, then I got no data abort error. But I'm not able to find the / or these problems.
the headerfile of the ethernet part:
#define AT91C_EMAC_TDLIST_BASE 0x21000000 /* */ #define ETH_PACKET_SIZE 1536 /* greater than 1518 or 1522 (VLAN) bytes */ #define NB_ETH_RX_PACKETS 10 /* number of RX buffer */ #define EMAC_RXBUF_ADD_WRAP 0x02 /* WRAP Bit at the end of the list descriptor */ #define MII_STS_REG 0x01 #define MII_STS2_REG 0x11 #define RxPacket (AT91C_EMAC_TDLIST_BASE + (8 * NB_ETH_RX_PACKETS)) typedef struct { unsigned int RxBufAddr; unsigned int RxBufStatus; } *EMAC_pRX_descriptor; void Phy_Init(void);
If i wrote
if(AT91C_ID_EMAC != (unsigned int) 24) Emac_Receive=0;
then it is never correct - but I'm not sure if this is the correct request.
Moreover I tested this:
if(AT91C_AIC_SVR[AT91C_ID_EMAC] != 0x1000032c) Emac_Receive=0;
AT91C_AIC_SVR: in this register should be stored the addresses of the corresponding handler for each interrupt source. My address of the function ethernet_interupt is 0x1000032c, which I can read out of the .map file.
But it fails... the correct address of the ISR is not stored.
within the function AT91F_AIC_ConfigureIt:
void (*newHandler) (void) ) // \arg address of the interrupt handler
which should be the ISR in the call of this function:
pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ;
and stored in this register...
Johannes
Now I think I've found the problem, but I don't know why this could be the problem...
I've one c-file where I install the ethernet PHY. At the beginning of this c-file is the ISR for the PHYs.
I installed one global variable Emac_Receive (at the top of this c-file)
volatile unsigned int Emac_Receive=0;
Within the ISR I changed the value of this variable if a ethernet frame is received (Emac_Receive=1). So it should be my flag (I don't know if there's a better routine to do that).
I have another c-file with the main.c where I called the first function for the initialisation of the ethernet PHYs. In the while(1) loop I always polling the variable Emac_Receive if there's a new ethernet frame received...
if (Emac_Receive==1)
At the top of this c-file I wrote:
extern unsigned int Emac_Receive;
If I comment out the polling routine within the main routine, then I get no data abort error...
But why could there be a error? What I'm doing wrong here?
I get also a data abort error, if I write the ISR at the top of the main.c-file.
Is there a problem with the extern reference?
Bad idea. Make it a rule: Never write "extern" in any .c file. Declarations interfacing one module to the next belong into the interface description of the exporting module, i.e. the corresponding .h file (and don't forget to #include that header in the defining module, too!).
As an extra advantage, this would have immediately caught the discrepancy between definition and declaration: you missed the "volatile".
I wrote in the extern declaration into the headerfile, but the data abort error occured again. I included this headerfile to both of the two c-files.
extern volatile unsigned int Emac_Receive;
You seem to like to experiment.
Have you played around with the linker, causing it to place this variable at a bad place?
I wrote my own linker script (scatter-file) - but if I use the linker script file from Keil it caused the same error (blinky-example).
When I took a look into the watch window, I'm able to see the address of the global variable Emac_Receive and this address seems to be ok.
Options for target > linker: I only insert my scatterfile and the activiation for (report might fail conditions as Errors) - I made no other settings.