Reply by Nick Howes March 18, 20092009-03-18
> Now that I've read this whole thread, I'm curious where the bug did
> lie. And how did you find it? Just curious.

Hi Matt,

Part of my reset handler checks to see what type of reset occurred,
and part of this code examines certain RAM locations. Originally,
these RAM locations were defined as a separate memory in the ld
script. At some point, the ld script was rewritten and these RAM
locations became just another section in the RAM - this meant that
their absolute addresses could change from build to build. This led
to the wrong type of reset being detected, bad assumptions about the
memory state being made, and the code going off in the weeds.

Like most bugs, it seems embarrassingly simple - so obvious in
hindsight. I eventually found it just by thinking about the problem
after it had reared it's ugly head again - one of those eureka moments.
- Nick
Reply by Matt Andrew March 18, 20092009-03-18
> I'm embarrassed to say that (perhaps unsurprisingly) this turned out to be a bug in my code. Thanks for everyone's help and sorry for the waste of bandwidth.

Now that I've read this whole thread, I'm curious where the bug did
lie. And how did you find it? Just curious.
Reply by Nick Howes March 16, 20092009-03-16
--- In A..., Nick Howes wrote:
>
> I'm trying to figure out the reset behavior of my AT91SAM7XC256 :

I'm embarrassed to say that (perhaps unsurprisingly) this turned out to be a bug in my code. Thanks for everyone's help and sorry for the waste of bandwidth.

Reply by Nick Howes January 28, 20092009-01-28
Well, I checked my startup code against the latest from Atmel (at91lib-1.4-at91sam7xc-ek).
There were a few minor differences, so I changed my code to match, and it made no
difference. At this point, I have to get on with other stuff - the workaround seems reliable
and that's what we're going with. I wish I understood what was happening.

Reply by Nick Howes January 27, 20092009-01-27
Hi Eric,

The "workaround" code is:

AT91C_BASE_RSTC->RSTC_RCR = (0xA5 << 24) | AT91C_RSTC_PERRST |
AT91C_RSTC_EXTRST; //reset the peripherals and remap
while ((AT91C_BASE_RSTC->RSTC_RSR) & AT91C_RSTC_SRCMP); //wait for reset to complete
((void(*)(void))0x00100000)(); //transfer control to reset vector in Flash

Note that I'm not trying to reset the processor, just the peripherals.

That said, I'm starting to think that this working is probably a fluke and that there must be
something not quite right in my crt0.s code and/or "LowLevelInit" code. I'm hoping to get a
block of time to look at it again tomorrow.

- Nick
Reply by Eric Pasquier January 27, 20092009-01-27
I have been thinking about your problem for a couple of hours without
finding the reason.

But something is disturbing me.
According to the documentation, as soon as you assert

AT91C_BASE_RSTC->RSTC_RCR = ((0xA5 << 24)
| AT91C_RSTC_PERRST
| AT91C_RSTC_EXTRST
| AT91C_RSTC_PROCRST);

the ARM is in Reset state and you should not be able to execute

while ((AT91C_BASE_RSTC->RSTC_RSR) & AT91C_RSTC_SRCMP);

or even

((void(*)(void))0x00100000)(); //transfer control to reset vector in Flash
(0x00100000)

That's why I am thinking that your problem could be in the initialization
sequence, which should be at address 0x0000000 in flash ....

Eric.

-----Mensagem original-----
De: A... [mailto:A...] Em nome de Nick
Howes
Enviada em: mardi 27 janvier 2009 21:20
Para: A...
Assunto: [AT91SAM] Re: Reset Behavior

--- In AT91SAM@yahoogroups .com,
"jellybean10025" wrote:
>
> Then I think you need to be looking elsewhere as Eric is suggesting.
>
> The code I posted absolutely works. It is in thousands of our
> production units and we do software updates frequently.
>
> There must be something else going on here.

Thanks for the info. You (and Eric) are probably right. I wish I could find
it!

The workaround (jumping to the reset vector in flash) does seem to work
reliably, so I guess
we could go with that.

Thanks to everyone for your suggestions!

- Nick
Reply by Nick Howes January 27, 20092009-01-27
--- In A..., "jellybean10025" wrote:
>
> Then I think you need to be looking elsewhere as Eric is suggesting.
>
> The code I posted absolutely works. It is in thousands of our
> production units and we do software updates frequently.
>
> There must be something else going on here.

Thanks for the info. You (and Eric) are probably right. I wish I could find it!

The workaround (jumping to the reset vector in flash) does seem to work reliably, so I guess
we could go with that.

Thanks to everyone for your suggestions!

- Nick
Reply by jellybean10025 January 27, 20092009-01-27
Then I think you need to be looking elsewhere as Eric is suggesting.

The code I posted absolutely works. It is in thousands of our
production units and we do software updates frequently.

There must be something else going on here.

PS: We strip off the "AT91" to keep the typing down, but otherwise
don't touch the header files.

--- In A..., "Nick Howes" wrote:
>
> --- In A..., "Nick Howes" wrote:
> >
> > --- In A..., "jellybean10025"
wrote:
> >
> > > while ((pRSTC->RSTC_RSR) & C_RSTC_SRCMP)
> >
> > Well yeah, that makes perfect sense - I need to wait for the reset
process to
> > complete so that it doesn't use the wrong vectors.
>
> Well it seemed like this was the answer, but it hasn't solved my
problem. :(
>
> - Nick
>

Reply by Nick Howes January 27, 20092009-01-27
--- In A..., "Eric Pasquier" wrote:

> Can you please test this configuration :

Hi Eric,

I tried the changes you suggested (including the AIC initialization stuff in your separate e-
mail) - it behaved in the same way.

- Nick
Reply by Eric Pasquier January 27, 20092009-01-27
Can you please test this configuration :
- - - (ok)
pPMC->PMC_PLLR = ( - - - ) (ok)

// Wait the startup time (until PMC Status register LOCK bit is set)
while(!(pPMC->PMC_SR & AT91C_PMC_LOCK));

// Wait for the master clock if it was already initialized
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));

// Switch to slow clock + prescaler
pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));

// Switch to fast clock + prescaler
pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));

// Initialize AIC
AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF;
Eric
----- Original Message -----
From: Nick Howes
To: A...
Sent: Tuesday, January 27, 2009 2:15 PM
Subject: [AT91SAM] Re: Reset Behavior
--- In A..., "Eric Pasquier" wrote:

> Can you please post your LowLevelInit sequence ?

Hi Eric,

Is this is what you are asking for?

#define FMCN_PLL_1_0_US 48 //48 cycles for 1us
#define FMCN_PLL_1_5_US 72 //72 cycles for 1.5us
#define MOR_OSC_CNT 8 //1.52 - 2.9 ms depending on SLCK accuracy
#define PLLR_DIV 5 //18.432MHz 5 = 3.6864MHz
#define PLLR_MUL 25 //3.6864MHz * 26 = 95.8464MHz
#define PLLR_PLL_CNT 28 //this value comes from the Atmel sample file
(number of slow clocks before LOCK bit set)
#define PLLR_USB 1 //1 means divide-by-two; 95.8464MHz 2 47.9232MHz (48MHz - 0.16%)

void base_init() {

AT91C_BASE_MC->MC_FMR = (FMCN_PLL_1_5_US << 16) | AT91C_MC_FWS_1FWS;
//setup flash

AT91C_BASE_PMC->PMC_MOR = (MOR_OSC_CNT << 8) | AT91C_CKGR_MOSCEN;
//enable Main Oscillator
while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)); //wait for osc startup

AT91C_BASE_PMC->PMC_PLLR = (PLLR_USB << 28) | (PLLR_MUL << 16) |
(PLLR_PLL_CNT << 8) | PLLR_DIV; //setup PLL
while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)); //wait for PLL startup

AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; //set MCK divider to 2
while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)); //wait for clock to be
ready

AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_PLL_CLK |
AT91C_PMC_PRES_CLK_2; //set MCK source to PLL
while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)); //wait for clock to be
ready

}

(I tried waiting for AT91C_PMC_MCKRDY at the beginning of this routine, but it made no
difference.)

thx, Nick