Writting to FLash Memory

Go To Last Post
96 posts / 0 new

Pages

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
the application the board freezes.
This is why God invented ICE debuggers. I would never contemplate working on a bootloader without an ICE to see what's going on !

 

AVRs never really "freeze" (well not unless they execute the SLEEP opcode) so the likelihood is actually that it is held in some kind of conditional while() loop waiting for some even that never occurs. An ICE would let you break execution and find out where it is "stuck".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
AVRs never really "freeze"...

My first job out of college, for a mainframe manufacturer, one of the first things I was taught "When the lights stop blinking, the computer stops thinking".

 

clawson wrote:
An ICE would let you break execution and find out where it is "stuck".

Set up the watchdog for interrupt mode.  When it fires, dig out the come-from address off of the stack and log to EEPROM or whatever.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
When it fires, dig out the come-from address off of the stack and log to EEPROM or whatever.
Me? I think I'd just buy an ICE (or I would if Atmel hadn't already sent me 3 or 4 - not to mention the ones on myriad Xplained bords they've also sent).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
so I can't use TCNT1

Sure you can, you will need to init T1 as you see fit to do.

 

All that code does is reset the T1 back to default values before running your sketch.

 

Jim

 

Edit:  Ok, I have no idea what happened to the message I was replying to ???

Never mind!

 

Edit2: found it msg# 51

Click Link: Get Free Stock: Retire early!

share.robinhood.com/jamesc3274

 

 

 

Last Edited: Thu. Oct 11, 2018 - 04:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

one more question , in the atmega32U4 manual 

it says that the bootloader section from @ 0x3800 :0x3FFF,

 

but based on  my calculation it should be as follwoing

the flash size is 32k

flash ends = 32*1024 =0x8000

flash start = 32-4 = 28k = 28)1024= 0x7000

 

then It should be from 0x7000 to 0x8000 

which is the right start location now ?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
the flash size is 32k

32k bytes, but flash is word addressed, =16k words!

Divide all byte address by 2.

 

 

Jim

 

Click Link: Get Free Stock: Retire early!

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

AVATAR_Freaks wrote:
the flash size is 32k

32k bytes, but flash is word addressed, =16k words!

Divide all byte address by 2.

 

 

Jim

 

 

I did that , but now I can't load my arduino sketch to my board ?? it says 

 

 

 

NO ACTUALLY I CAN't see the device in my device manager anymore , when i but the bootloader at 0x3800 

what is the reason fro that?


Connecting to programmer: .avrdude: butterfly_recv(): programmer is not responding

 

ummmm

Last Edited: Thu. Oct 11, 2018 - 06:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OKay, so I looked into the im32u4.h that comes with the atmel software and the Flash end is defined as

 

#define FLASHEND     (0x7FFF)

this is confusing ??

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
OKay, so I looked into the im32u4.h that comes with the atmel software and the Flash end is defined as

 

#define FLASHEND     (0x7FFF)

this is confusing ??

Don't know why.

32K = 0x8000 = FLASHEND+1

What is the problem?

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You're still getting confused between byte-addresses and word-addresses.

 

NO ACTUALLY I CAN't see the device in my device manager anymore , when i but the bootloader at 0x3800

what is the reason fro that?

Which device?  Your ISP programmer?  Or the 32u4 as a USB-reachable bootloader?  If you've messed up the bootloader, you won't see it in the device manager.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
static void (*do_spm_N)(uint32_t address,  uint8_t *data)__attribute__ ((section(".bootloader"))) ;

AFAICT, you never actually initialize the do_spm_N pointer to point at your actual function.

I'm not sure that you need to, if you're actually linking together your bootloader and application code (but then you shouldn't need a function pointer.)

 

The usual "problem" with calling functions in the bootloader from the application is that they are NOT "linked" together, and the application has no way of knowing exactly where in the bootloader section the "do_spm" function lives.

This is generally solved by putting a jump table at some "known absolute location" - usually at the very beginning of the bootloader section, or at the very end of memory.   For example, a do_spm() was added to Optiboot recently", and they put vectors at the beginning of the section:

 

void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8")));
void pre_main(void) {
  // Allow convenient way of calling do_spm function - jump table,
  //   so entry to this function will always be here, indepedent of compilation,
  //   features etc
  asm volatile (
    "	rjmp	1f\n"
    "	rjmp	do_spm\n"
    "1:\n"
  );
}

There's an example of using it at https://github.com/Optiboot/optiboot/tree/master/optiboot/examples/test_dospm

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
this is confusing ??
The point is this. The granularity of opcodes in AVR is a minimum 16 bit pattern or multiple there of. Therefore Atmel, in their own documentation, always speak in terms of words for addresses and sizes. So a 32K (byte) chip has 16K words and in their scheme these are addressed as 0x0000..0x3FFFF but in byte terms that is 0x0000..0x7FFF

 

The GCC compiler and accompanying tools on the other hand is a generic compiler for a load of different micros and other CPUs. To have a common base it does EVERYTHING in terms of bytes. That is also true of all the addresses in all the ioXXX.h headers in AVR-LibC. That too uses BYTE addressing everywhere. 

 

The confusion arises because Atmel have chosen to bundle GCC with their IDE so some parts are word-centric and some parts are byte-centric.

 

You possibly see this most clearly when you use the "Meomories" section in a project to set a flash address. Atmel invite you to entry the address as words so you may enter 0x1234 but when this is actually passed to the linker as -Wl,-section-start=.something=0x2468 where the 1234 values is seen to be doubled as Atmel have applied a word to byte conversion on it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:

 

You possibly see this most clearly when you use the "Meomories" section in a project to set a flash address. Atmel invite you to entry the address as words so you may enter 0x1234 but when this is actually passed to the linker as -Wl,-section-start=.something=0x2468 where the 1234 values is seen to be doubled as Atmel have applied a word to byte conversion on it.

 

 

Ohhh, they speak in terms of Words, but when it comes to programming then we program in terms of Bytes. Man thank you so much , now it all m make sense 

Last Edited: Fri. Oct 12, 2018 - 12:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:

void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8")));
void pre_main(void) {
  // Allow convenient way of calling do_spm function - jump table,
  //   so entry to this function will always be here, indepedent of compilation,
  //   features etc
  asm volatile (
    "	rjmp	1f\n"
    "	rjmp	do_spm\n"
    "1:\n"
  );
}

There's an example of using it at https://github.com/Optiboot/optiboot/tree/master/optiboot/examples/test_dospm

 

 

Oka great you brough a very important point, that i have been wondering about for a while.

I don't understand what  asm  Volatile do or mean ? it seems so necerssary to have it 

can you explain that in few details 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are wasting you time learning inline asm. While the manual covers it in some detail:

 

https://www.nongnu.org/avr-libc/...

 

There's almost always a better (or at least easier, equal) way to achieve the same thing so I wouldn't waste too much time on it.  The above, for example could just as easily have been written (much clearer in my opinion) as:

    .section .init8

    .extern do_spm
    rjmp skip
    rjmp do_spm
skip:    

    .section .text
do_spm:
    SPM
    ret

Put that into a .S file and build it along with the rest of the code. You get:

// main.c
#include <avr/io.h>

int main(void)
{
		while(1);
}
// asm.S
    .section .init8

    .extern do_spm
    rjmp skip
    rjmp do_spm
skip:    

    .section .text
do_spm:
    SPM
    ret

When built this yields:

00000068 <__ctors_end>:
  68:	11 24       	eor	r1, r1
  6a:	1f be       	out	0x3f, r1	; 63
  6c:	cf ef       	ldi	r28, 0xFF	; 255
  6e:	d8 e0       	ldi	r29, 0x08	; 8
  70:	de bf       	out	0x3e, r29	; 62
  72:	cd bf       	out	0x3d, r28	; 61
    .section .init8

    .extern do_spm
    rjmp skip
  74:	01 c0       	rjmp	.+2      	; 0x78 <skip>
    rjmp do_spm
  76:	06 c0       	rjmp	.+12     	; 0x84 <do_spm>

00000078 <skip>:
  78:	0e 94 44 00 	call	0x88	; 0x88 <main>
  7c:	0c 94 49 00 	jmp	0x92	; 0x92 <_exit>

00000080 <__bad_interrupt>:
  80:	0c 94 00 00 	jmp	0	; 0x0 <__vectors>

00000084 <do_spm>:
skip:    

    .section .text
do_spm:
    SPM
  84:	e8 95       	spm
    ret
  86:	08 95       	ret

00000088 <main>:
etc. etc.

The only time you need asm() is when something is SO timing critical you cannot afford the CALL/RET overhead to access it. Otherwise .S files are a MUCH easier answer.

 

PS I still don't understand why Bill would have you do this anyway? Sure that has put an "rjmp spm" at 0x0076 but with what intention? In fact, for my money I would have thought:

// asm.S 
#include <avr/interrupt.h> 
    .global INT0_vect 
    
INT0_vect: 
    SPM 
    ret

would be a better solution. This compiles to be:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__ctors_end>
   4:	0c 94 40 00 	jmp	0x80	; 0x80 <__vector_1>
   8:	0c 94 3e 00 	jmp	0x7c	; 0x7c <__bad_interrupt>
...
00000080 <__vector_1>:
	#include <avr/interrupt.h>

	.global INT0_vect

INT0_vect:
    SPM
  80:	e8 95       	spm
    ret
  82:	08 95       	ret

so I now have a "do_spm" always available at a a fixed start+0x0004 which can never be subject to change (because INT0 is not going anywhere!)

 

This does, of course, rely on the bootloader never wanting to use interrupts and specifically never wanting to use INT0.

 

OTOH maybe the whole thing is built with -nostartfiles anyway??

Last Edited: Fri. Oct 12, 2018 - 01:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

// main.c
#include <avr/io.h>

int main(void)
{
		while(1);
}
// asm.S
    .section .init8

    .extern do_spm
    rjmp skip
    rjmp do_spm
skip:    

    .section .text
do_spm:
    SPM
    ret

 

 

Okay i wanna try that, but I am new to assembly langague so take it easy on me ,then that for me should be ':-

// main.c
#include <avr/io.h>

int main(void)
{
		while(1);
}


// asm.S
    .section .init8

    .extern do_spm_N
    rjmp skip
    rjmp do_spm_N
skip:    

    .section .text
do_spm_N:
    SPM
    ret

SO how can i added to my code when I build, do i uses something like include file, I build useing a makefile not the atmel studio. 

 

 

what is "SPM" , and "ret" refer too? 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The way I am suggesting you add Asm code to a mainly C project is to add a new source file. When you do AS7 offers you the option of creating an "Asm source" with a .s extension. Atmel have actually got this wrong it should have a .S extension so change the entire name offered to something like "myasm.S" and save. That adds a blank file (well a comment at the top) to your project. Make the first two lines:

#define __SFR_OFFSET 0
#include <avr/io.h>

then you write the Asm code after that. You'll need to learn AVR Asm first.

 

if you want to interact between Asm and C code then the Asm has to be written to follow the Application Binary Interface (ABI) of the GCC compiler. (things like first function parameter in R25 and R24 etc).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I don't think optippot works with atmega32u4 ... I tested it and it is not working 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely if it's a 32U4 you want to use a DFU bootloader not a UART one like Optiboot?

 

(DFU = USB class for Device Firmware Update)

 

The whole point of buying a 32U4 is the USB so you might as well use it!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Surely if it's a 32U4 you want to use a DFU bootloader not a UART one like Optiboot?

 

(DFU = USB class for Device Firmware Update)

 

The whole point of buying a 32U4 is the USB so you might as well use it!

 

Yes true, that is exactly why choose it. I am using Caterina and the LUFA project together to take a advantage of the USB , and it came out very nice-except that the eeprom is too small for the data we need. so we trying to explore the idea of using the flash memory to save the data. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So Caterina is a USB based bootloader is it? If so then surely you can just make its own SPM functions visible to the app code and call those ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

So Caterina is a USB based bootloader is it? If so then surely you can just make its own SPM functions visible to the app code and call those ?

 

Yes it is 

the problem with its SPM function is need special commands take a a look 

static void ReadWriteMemoryBlock(const uint8_t Command)
{
	uint16_t BlockSize;
	char     MemoryType;

	bool     HighByte = false;
	uint8_t  LowByte  = 0;

	BlockSize  = (FetchNextCommandByte() << 8);
	BlockSize |=  FetchNextCommandByte();

	MemoryType =  FetchNextCommandByte();

	if ((MemoryType != 'E') && (MemoryType != 'F'))
	{
		/* Send error byte back to the host */
		WriteNextResponseByte('?');

		return;
	}

	/* Disable timer 1 interrupt - can't afford to process nonessential interrupts
	 * while doing SPM tasks */
	TIMSK1 = 0;

	/* Check if command is to read memory */
	if (Command == 'g')
	{		
		/* Re-enable RWW section */
		boot_rww_enable();

		while (BlockSize--)
		{
			if (MemoryType == 'F')
			{
				/* Read the next FLASH byte from the current FLASH page */
				#if (FLASHEND > 0xFFFF)
				WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
				#else
				WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
				#endif

				/* If both bytes in current word have been read, increment the address counter */
				if (HighByte)
				  CurrAddress += 2;

				HighByte = !HighByte;
			}
			else
			{
				/* Read the next EEPROM byte into the endpoint */
				WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >> 1)));

				/* Increment the address counter after use */
				CurrAddress += 2;
			}
		}
	}
	else
	{
		uint32_t PageStartAddress = CurrAddress;

		if (MemoryType == 'F')
		{
			boot_page_erase(PageStartAddress);
			boot_spm_busy_wait();
		}

		while (BlockSize--)
		{
			if (MemoryType == 'F')
			{
				/* If both bytes in current word have been written, increment the address counter */
				if (HighByte)
				{
					/* Write the next FLASH word to the current FLASH page */
					boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) | LowByte));

					/* Increment the address counter after use */
					CurrAddress += 2;
				}
				else
				{
					LowByte = FetchNextCommandByte();
				}
				
				HighByte = !HighByte;
			}
			else
			{
				/* Write the next EEPROM byte from the endpoint */
				eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());

				/* Increment the address counter after use */
				CurrAddress += 2;
			}
		}

		/* If in FLASH programming mode, commit the page after writing */
		if (MemoryType == 'F')
		{
			/* Commit the flash page to memory */
			boot_page_write(PageStartAddress);

			/* Wait until write operation has completed */
			boot_spm_busy_wait();
		}

		/* Send response byte back to the host */
		WriteNextResponseByte('\r');
	}

	/* Re-enable timer 1 interrupt disabled earlier in this routine */	
	TIMSK1 = (1 << OCIE1A);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just isolate the call to boot_page_write() into a separate function and then you can also call that from your app code (if you can pass the address of where it is).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Just isolate the call to boot_page_write() into a separate function and then you can also call that from your app code (if you can pass the address of where it is).

 

that is exactly what I did for my do_spm_n function

void do_spm_N (uint32_t BMem_address){
	uint16_t i;
    uint8_t sreg;
	char  w ;
	w  =  "testing01234";
    // Disable interrupts.
    sreg = SREG;
    cli();
    eeprom_busy_wait ();
    boot_page_erase (BMem_address);
    boot_spm_busy_wait ();      // Wait until the memory is erased.
	 for (i=0; i<SPM_PAGESIZE; i+=2)
    {
        // Set up little-endian word.
       // uint16_t w = *data++;
        //w += (*data++) << 8;

        boot_page_fill (BMem_address + i, w);
    }
    boot_page_write (BMem_address);     // Store buffer in flash page.
    boot_spm_busy_wait();       // Wait until the memory is written.
    // Reenable RWW-section again. We need this if we want to jump back
    // to the application after bootloading.
    boot_rww_enable ();
    // Re-enable interrupts (if they were ever enabled).
    SREG = sreg;

}
/**********

but every time i call the do_spm_N from my arduino sketch the rx and tx go solid yellow 

 

 

Last Edited: Fri. Oct 12, 2018 - 05:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
the rx and tx go solid yellow 
No idea what those are and how they are connected to the above code (which as far as I can see has nothing to control an LED??)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

AVATAR_Freaks wrote:
the rx and tx go solid yellow 
No idea what those are and how they are connected to the above code (which as far as I can see has nothing to control an LED??)

 

yes you are right, but  in the arduino sketch I use the erial port to communicate and send data here is the sketch 


// this is the Arduino code, SPM.ino 

#include"SPM.h"

void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);

}

void loop() {
    byte data;

    uint32_t Read_Ptr = 0x6000;

    // Print current flash buffer content
    if (Serial.available() > 0 ) {
      data = Serial.read() ;
        switch (data) {

            case 'n' :{
               do_spm_N(Read_Ptr);

          }
   }
  }
}

/****************************************************************/

// SPM.h 

#include <avr/boot.h>

void (*do_spm_N)(uint32_t address)=0x7000; // this is the location , or what i think is the location
// this comes from the .booloader  at the linker
//

if you notice I don't print anything to the serial port, yet . this code is just for testing the do_spm_N . so when i send "n" on the serial port the app should call do_spm_N and write the data to the flash at location 0x6000. but the RX,TX led turn on solid  yellow , and doesn't turn off at all and I have to restart the board (arduino Micro Board) 

Last Edited: Fri. Oct 12, 2018 - 06:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void (*do_spm_N)(uint32_t address)=0x7000; // this is the location , or what i think is the location
// this comes from the .booloader  at the linker

1) I highly doubt that this is the correct address. You can't "give" it an address from within the application (I already told you in #20 that all the .bootloader stuff in the OP is nonsense). For this function pointer approach you need to find out the actual address where the function got located in the bootloader.

 

2) For this function pointer approach you need to use the word address (again, I already told you that in #20).

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:

void (*do_spm_N)(uint32_t address)=0x7000; // this is the location , or what i think is the location
// this comes from the .booloader  at the linker

1) I highly doubt that this is the correct address. You can't "give" it an address from within the application (I already told you in #20 that all the .bootloader stuff in the OP is nonsense). For this function pointer approach you need to find out the actual address where the function got located in the bootloader.

 

 

remmeber we discussed that before, and we couldn't locate the exact address, but I know where the section .bootloader lives which at(0x7000) and the only thing in this section is do_spm_N,  so it has to be at 0x7000

 

sternst wrote:

2) For this function pointer approach you need to use the word address (again, I already told you that in #20).

 

 

What you mean us the word adress, fo yo mean something like that 

#define address= 0x7000;

void (*do_spm_N)(uint32_t address)=address;

OR "address" is already a defined  macro can be used in Ardino environment 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
but I know where the section .bootloader lives which at(0x7000) and the only thing in this section is do_spm_N
But you wrote this:
AVATAR_Freaks wrote:
that is exactly what I did for my do_spm_n function

 void do_spm_N (uint32_t BMem_address){

I can't see any relocation of the function there.

And you can't put it at 0x7000 (where the bootloader starts) anyway.

 

 

AVATAR_Freaks wrote:
What you mean us the word adress, fo yo mean something like that
No, I mean something like this:

void (*do_spm_N)(uint32_t address) = 0x7000 / 2;

(but again: 0x7000 is for sure not the correct address)

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I still don't understand why Bill would have you do this anyway? Sure that has put an "rjmp spm" at 0x0076 but with what intention? In fact, for my money I would have thought:

// asm.S 
#include <avr/interrupt.h> 
    .global INT0_vect 
    
INT0_vect: 
    SPM 
    ret

Well, first of all, I didn't write this code.  It was written by Marek Wodziński ("Majekw")  I just played "gatekeeper" on the official Optiboot page.

2nd, simple code like the above won't work because SPM requires those "timed write sequences" where you write some code to SPMCSR and then do the SPM within four clock cycles.  CALL is a 4-cycle instruction; I don't think it would work to have just the SPM be callable.

3rd, the way the code was originally written, it also replaced all of the uses of SPM within Optiboot itself, with some overall savings in code space requirements, but having it do "all the stuff that is ever needed, whether its needed or not."   (This wasn't retained - it conflicts with the desire to use avr-libc functions as often as possible, and we don't need the space at the moment.)

 

I should mention that the scheme with vectors in .init8 only results in "known locations" if you're also omitting the standard startup files ("-nostartfiles" in the link command.)  Otherwise the vectors end up being located after an "unknown" amount of startup code (as Clawson's sample asm listing showed.)  (this somewhat argues that the vectors should have gone at the end of flash, instead.  (too late now!  Sigh.))  (perhaps one of the other .initN sections would be better.)

 

 

[inline asm vs separate .S files]

 We can probably blame the avr-libc authors for that.  There is lots of inline ASM in the boot.h file.

I'm not really convinced.  Use of ASM seems to three general cases:

  1. very simple stuff, like insertion of a particular instruction.  (like these vectors, actually.)  Not much to learn, so I don't see why to avoid inline asm.
  2. relatively complex stand-alone functions (say, like the soft-uart functions in optiboot.)  These would be a lot cleaner in their own .S file.
  3. asm that interacts in complex ways with the C code (accessing local variables, maintaining register optimization, etc.)  Really annoying, and this is where you call up the tutorial on one page, while you write your code in another.

 

 

[no Optiboot for 32u4]

It's been requested, and even implemented: https://github.com/Optiboot/opti...

It has not been added, because Optiboot is a serial-only bootloader, and claiming 32u4 support would probably confuse more people (expecting it to work over USB) than it would help...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

The way I am suggesting you add Asm code to a mainly C project is to add a new source file. When you do AS7 offers you the option of creating an "Asm source" with a .s extension. Atmel have actually got this wrong it should have a .S extension so change the entire name offered to something like "myasm.S" and save. That adds a blank file (well a comment at the top) to your project. Make the first two lines:

#define __SFR_OFFSET 0
#include <avr/io.h>

then you write the Asm code after that. You'll need to learn AVR Asm first.

 

if you want to interact between Asm and C code then the Asm has to be written to follow the Application Binary Interface (ABI) of the GCC compiler. (things like first function parameter in R25 and R24 etc).

 

I use a make file to build the projecy, how can i do that using make file

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
PS I still don't understand why Bill would have you do this anyway?

I'm missing something.  Is "Bill" one of the players in this comic tragedy?

 

Mr. Bill:

 

Red Green's "Adventures with Bill":

 

From our friends down under:

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw = Bill Westfield = current maintainer of the main Arduion bootloader: Optiboot.

AVATAR_Freaks wrote:
I use a make file to build the projecy, how can i do that using make file
That depends entirely on the structure of your Makefile. If it happens to use the Mfile template (a wise choice) then near the top of the file it will have:

# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c


# List Assembler source files here.
#     Make them always end in a capital .S.  Files ending in a lowercase .s
#     will not be considered source files but generated files (assembler
#     output from the compiler), and will be deleted upon "make clean"!
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
#     it will preserve the spelling of the filenames, and gcc itself does
#     care about how the name is spelled on its command-line.
ASRC = 

So you will list .c files on the SRC= line and .S files on the ASRC= line. Something like

# List C source files here. (C dependencies are automatically generated.)
SRC = main.c foo.c bar.c


# List Assembler source files here.
#     Make them always end in a capital .S.  Files ending in a lowercase .s
#     will not be considered source files but generated files (assembler
#     output from the compiler), and will be deleted upon "make clean"!
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
#     it will preserve the spelling of the filenames, and gcc itself does
#     care about how the name is spelled on its command-line.
ASRC = myasm.S some_other_asm.S

If you aren't using Mfile, take a look:

 

http://www.sax.de/~joerg/mfile/

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

 

# List C source files here. (C dependencies are automatically generated.)
SRC = main.c foo.c bar.c


# List Assembler source files here.
#     Make them always end in a capital .S.  Files ending in a lowercase .s
#     will not be considered source files but generated files (assembler
#     output from the compiler), and will be deleted upon "make clean"!
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
#     it will preserve the spelling of the filenames, and gcc itself does
#     care about how the name is spelled on its command-line.
ASRC = myasm.S some_other_asm.S

 

 

okay it build successfully, but why after building the project  the myasm.S file is deleted ? is that normal 

is there away to know for sure that it was included, is there any information about inin the hex or .o or ,elf file ?

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVATAR_Freaks wrote:
, but why after building the project  the myasm.S file is deleted ?
Did you call it myasm.s or myasm.S ?? It MUST have a capital .S for two reasons:

 

1) most "clean" rules will delete "*.s" (but not "*.S")

2) avr-gcc will pass .s files straight to the assembler. for .S files it passes them first through the preprocessor and then on to the assembler. As most .S files will at the very least "#include <avr/io.h>" then it must be preprocessed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

 Did you call it myasm.s or myasm.S ?? It MUST have a capital .S for two reasons:

 

 

I actually Called it myasm.S , but it still gets deleted.  

#define __SFR_OFFSET 0
#include <avr/io.h>

  .section .init8

    .extern do_spm_N
    rjmp skip
    rjmp do_spm_N
skip:    

    .section .text
do_spm_N:
    SPM
    ret

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well presumably you can see the command issued as the Makefile executes? So which one do you think is doing it? Presumably an "rm" or "del" or something?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Well presumably you can see the command issued as the Makefile executes? So which one do you think is doing it? Presumably an "rm" or "del" or something?

 

It is the rm command,  and it is not in the clean list 


clean_list :
	@echo
	@echo $(MSG_CLEANING)
	$(REMOVE) $(TARGET).hex
	$(REMOVE) $(TARGET).eep
	$(REMOVE) $(TARGET).cof
	$(REMOVE) $(TARGET).elf
	$(REMOVE) $(TARGET).map
	$(REMOVE) $(TARGET).sym
	$(REMOVE) $(TARGET).lss
	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
	$(REMOVE) $(SRC:.c=.s)
	$(REMOVE) $(SRC:.c=.d)
	$(REMOVE) $(SRC:.c=.i)
	$(REMOVEDIR) .dep

 

 

Also, I have another issue , when I compile using "make all" in Linux the hex file from (0x7000 to 0x7F960) 

when I compile using make all in windows power shell the hex file from(0x7000 to 0x8044)

when I compile using the Atmel studio 7 -> Use External Makefile  the hex file from (0x7000 to 0x7FA4)

 

 

why is that ? why the one from windows is bigger , and off course since it ends at 0x8044 I can't upload it to my 32u4 because its memory ends at 0x8000.

Does my atmel compiler or linux compile delete stuff from my code ??

 

 

Last Edited: Fri. Oct 19, 2018 - 01:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are they exactly the same issue of the compiler in each case and are the tools being invoked with 100% identical options? For example if you used a 4.3.4 in one place and 5.4.2 in another you would get different code and if you used -O1 in one place and -Os in another you would get different code, etc etc

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Are they exactly the same issue of the compiler in each case and are the tools being invoked with 100% identical options? For example if you used a 4.3.4 in one place and 5.4.2 in another you would get different code and if you used -O1 in one place and -Os in another you would get different code, etc etc

 

I use the same exact make file tho, 

how cani check that 

Last Edited: Fri. Oct 19, 2018 - 01:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Are they exactly the same issue of the compiler in each case and are the tools being invoked with 100% identical options? For example if you used a 4.3.4 in one place and 5.4.2 in another you would get different code and if you used -O1 in one place and -Os in another you would get different code, etc etc

 

Also when i Compile i get a warning about the function do_spm_N

Caterina.c: In function 'do_spm_N':
Caterina.c:729: warning: initialization from incompatible pointer type

is that the reason I cant get it to work ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Are they exactly the same issue of the compiler in each case and are the tools being invoked with 100% identical options? For example if you used a 4.3.4 in one place and 5.4.2 in another you would get different code and if you used -O1 in one place and -Os in another you would get different code, etc etc

 

 

I looked at the .lss file and when I compile using the powershell i get this 

/*  Writing to flash*/
void do_spm_N (void){
    7000:	6a c0       	rjmp	.+212    	; 0x70d6 <__ctors_end>
	return true;
#endif
}

 

 

but when I compile using the atmel i get this , which  just my function code no address assigned 

 

void do_spm_N (void){
	
volatile uint16_t *const Bemin_register = (volatile uint16_t *)0x0400;
uint8_t volatile  *const port = (uint16_t *) 0x0430;
*Bemin_register =0x5a5a;
*port=10;

 

 

but If I look at any other function i can see the adress for it ,

0000718c <StartSketch>:

what possible could i be doing wrong and why they differetn.... very confused

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've lost the plot and haven't got a clue what you are talking about so, sorry I can't help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I've lost the plot and haven't got a clue what you are talking about so, sorry I can't help.

thank you 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Are they exactly the same issue of the compiler in each case and are the tools being invoked with 100% identical options? For example if you used a 4.3.4 in one place and 5.4.2 in another you would get different code and if you used -O1 in one place and -Os in another you would get different code, etc etc

You are right I was using different Versions and that is why it was coming different size 

 

thanks alot 

Pages