EmbDev.net

Forum: ARM programming with GCC/GNU tools Beginner's blinky C code for AT91SAM9


von John (Guest)


Rate this post
useful
not useful
Hi all,

I just finished writing a simple blinky code (my first code) for 
AT91SAM9 and it compiled fine. Anyone mind looking at it to see if 
overall I have used the correct registers? I dont have the device yet so 
I can not test it.

Thanks!

1
#include <../inc/AT91SAM9G45.h>
2
                             //anything else I should include as a standard?
3
#define F_CPU 12000000UL     //12MHz
4
 
5
int main(void) {
6
        AT91C_BASE_PIOA->PIO_PER = 1;     //enables the Parallel IO; disables peripheral          
7
        //can I use P0 like PAx in AVR? applicable to ARM programming for setting bits? 
8
        
9
        AT91C_BASE_PIOA->PIO_OER = 1;     //enables output
10
        
11
        
12
        while(1) {  
13
                AT91C_BASE_PIOA->PIO_CODR = 1;     //clears output; LED on (LED connected to Vcc)
14
                //delay function, which I have no idea if there is a library for this
15
                
16
                AT91C_BASE_PIOA->PIO_SODR = 1;     //set output data to 1; LED off
17
                //delay function   
18
        }
19
}

von Daniel G. (motello)


Rate this post
useful
not useful
Hi,

it is correct to enable the PIO controller and to switch it to output 
state, but what you should know is, that you can control each single pin 
independently. The registers are 32bit and when you are writing 1 to 
this register, you enable pin 1. Is that your intention?

If you instead want to enable or control another pin, for example pin 
number 14, you have to write a number to the register which equals 
10000000000000 to the basis 2. better to write is (1 << 14) where 1 is 
shifted 14 bits left.

AT91C_BASE_PIOA->PIO_PER = 1 << 14;

The same procedure for the other registers.

For the delay you can use one of the timer of your microcontroller. 
there is probably a software package from atmel available which covers 
this issue. so you don't need to write your own driver for the timer.

von John (Guest)


Rate this post
useful
not useful
Daniel G. (motello),

Thank you so much for your descriptive response!

I looked over the datasheet again and didn't see any settings for fuse 
bits. Perhaps ARM9s don't have fuse bits to set security settings and 
clock selection?

I am also quite confused about the internal & external clocks (including 
the usage of PLL) from the AT91SAM9G45 datasheet. Would you please shine 
some light?

Thank you very much!

von Daniel G. (motello)


Rate this post
useful
not useful
Hi,

I have experience especially in ARM9 and Atmel MCU. There are no fuse 
bits or security settings for the PIO controller. You only have to 
enable the PIOC clock in the Power Management Controller (PMC). This 
feature is useful to save energy.

You surely have a crystal on your board of around 15-20MHz. This 
frequency is of course to low for a appropriate processor clock for an 
ARM9. You have to configure the divider and PLL block to divide and then 
to multiply (PLL) the clock to the desired frequency. This part is done 
by the clock generator. The generated clock signal can be connected to 
the CPU.

But for the peripherals, you will need the so called master clock. It is 
configured by the PMC.

I recommend to use the AT91Bootstrap framework, which does all the clock 
initialization, so that you don't need to bother about these things in 
your program. Which board you want to use finally? Potentially, the 
manufacturer provides a adapted version of the framework which is 
already configured.

I hope I could help you!
Cheers, Daniel

von John (Guest)


Rate this post
useful
not useful
Daniel,

So in order for the PIO/the above blinky to work, the PMC would have to 
be configured first? This means I would have to either use its internal 
RC oscillator or supply an external one. I am reading the "Device 
Initialization" section of the datasheet, and it seems to me that the 
initialization sequence is automatically executed (the device first uses 
a slow clock, then automically switches to an external main oscillator 
if one is present and detected), is this correct?

I will be designing my own board and booting the device from a SD card.

Thanks!
John

von Daniel G. (motello)


Rate this post
useful
not useful
Hi,

the slow clock is clocked either by an internal RC-oscillator or by an 
external crystal. The processor is clocked with this clock first but to 
increase the operation speed, it is worth to initialize the clock 
generator in an early state. I only know the AT91SAM9260 and there, the 
clock initialization is not automatically done. I thought it is the same 
for similar devices. which device you are exactly going to use?

To use any of the peripherals, you need to initialize the master clock 
and to switch on this clock for your PIOC.

You are going to design your own board!? Thats a very ambitious effort 
since you will surely encounter problems with your design and have to 
debug it. It is very hard to find a hardware bug when you cannot surely 
say that your software is bugfree and vice versa.

There are so many good evaluation boards available. I use Olimex, for 
example. Or are you an experienced hardware designer?

There is an important application note provided by atmel, dealing with 
signal integrity. It may be worth for you to read it:
http://www.atmel.com/dyn/products/app_notes.asp?part_id=3870
http://www.atmel.com/dyn/resources/prod_documents/doc6349.pdf

Cheers, Daniel

von John (Guest)


Rate this post
useful
not useful
Daniel,

Thanks for the links! It is very helpful! I've also taken a look at the 
AT91SAM9260 datasheet to see its similarities with the 9G45 device. 
Here's its device initialization (9260):

Initialization follows the steps described below:
1. FIQ Initialization
2. Stack setup for ARM supervisor mode
3. External Clock Detection
4. Switch Master Clock on Main Oscillator
5. C variable initialization
6. Main osc freq detection if no external clock detected
7. PLL setup
8. Initialization of the DBGU serial port...
9. Jump to DataFlash Boot sequence.
...more boot sequences...

I noticed that the actual blinky code doesn't execute until (or after) 
step 9, when it boots off an external memory. This means all the steps 
before 9 are executed from ROM, where the code is already written from 
Atmel (correct me if I'm wrong), so I wouldn't have to bother with the 
ROM code? On step 4 the device automatically switches to the main 
oscillator from the slow clock. The only clock configuration left for 
the developer is to set the Master Clock, and the PLL if one is needed. 
That's my understanding for now :)

Thanks!
John

von John (Guest)


Rate this post
useful
not useful
Daniel,

Are the initialization steps automatically done? or does the programmer 
have to write code for it?

Thanks,
John

von Daniel G. (motello)


Attached files:

Rate this post
useful
not useful
John wrote:
> Thanks for the links! It is very helpful! I've also taken a look at the
> AT91SAM9260 datasheet to see its similarities with the 9G45 device.
> Here's its device initialization (9260):
>
> Initialization follows the steps described below:
> 1. FIQ Initialization
> 2. Stack setup for ARM supervisor mode
> 3. External Clock Detection
> 4. Switch Master Clock on Main Oscillator
> 5. C variable initialization
> 6. Main osc freq detection if no external clock detected
> 7. PLL setup
> 8. Initialization of the DBGU serial port...
> 9. Jump to DataFlash Boot sequence.
> ...more boot sequences...

Hi John,

if you are going to use the AT91bootstrap, you don't have to deal with 
some of the steps below. The AT91bootstrap doc gives you more 
information:
http://www.atmel.com/dyn/resources/prod_documents/doc6277.pdf
http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4093

The framework will load your program image from dataflash or Nandflash 
to SDRAM for example and runs it. But you cannot start with C-code 
before you haven't executet the so called startup or c-runtime code. 
This code does some of the above listed steps. Here is what the code has 
to be done:

1. Build a valid vector table (actually not a step but this table has to 
lie at the beginning of your image for that the framework will regard 
your image as valid).
2. initialize ALL stackpointer (C-code depend of the stack)
3. zero all global uninitialized variables (bss section) (it's better 
not to load the variables into your image (NOLOAD - instruction for the 
linker) to keep the file size low.
4. enable irq and fiq if needed.
5. branch to your c-code.

So what you have to do is, if you are using the AT91bootstrap-framework:
1. compile your c-code with your startup code
2. link everything
3. strip all additional information in the object file (your MCU only 
expects instructions rather than object file header)
4. load your image to the address in ROM, which you have registered in 
the framework
5. load the framework to address 0x0 in your ROM.
6. reset - and your program will hopefully run :-)

here is a good introduction in building bare-metal systems (w/o OS):
http://www.state-machine.com/arm/Building_bare-metal_ARM_with_GNU.pdf

Attached you will find my startup code.

I hope, I haven't forgotten something.

Cheers,
Daniel

von Daniel G. (motello)


Rate this post
useful
not useful
John wrote:
> Are the initialization steps automatically done? or does the programmer
> have to write code for it?

Everything has to be done by software (either by yourself or by the 
bootstrap framework, for example).

von John (Guest)


Rate this post
useful
not useful
Daniel,

Thanks! I have re-read the datasheet (again) and it seems like the 
device ships with an initialization startup code already:

"The Boot Program is contained in the embedded ROM. It is also called: 
“Rom Code” or “First level bootloader”. At power on, if the BMS pin is 
detected at 1, the boot memory is the embedded
ROM and the Boot Program is executed."

That's pretty nice! I wouldn't need to fiddle with the ROM code, at 
least as of yet that is :)

Thanks again,
John

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.