Go Down

Topic: Few Low-level Questions on ATmega328 of Arduino-UNO (Read 860 times) previous topic - next topic

GolamMostafa

Jan 23, 2017, 08:00 am Last Edit: Jan 23, 2017, 11:54 am by GolamMostafa
1. What are the Arduino Fuse Settings Values?
2. From what location of Flash, the application program begins execution.
3. Does Arduino compiler produce list file and Intel-Hex formatted file?
    If so, how can we get access to them?
4. If we wish to use the analog pins (A0 - A5) as digital output lines, do we need to set the directions
    of these lines as output (DDRC = 0xFF)? 
5. Is there any Arduino C function to provide correct BCD result for the incorrect BCD result that
    appears after the execution of the following instruction: unsigned char x1 = BCD1 (09);
    unsigned char y = BCD2 (03); unsigned char z = x + y (0x0C)? We want that z should
    contain 12?   

westfw

Quote
1. What are the Arduino Fuse Settings Values?
dependent on the chip and operating mode - Listed in boards.txt.
Generally: low power crystal oscillator, 512byte bootloader started at reset.

Quote
2. From what location of Flash, the application program begins execution.
0x0000 - typically 0x0000 with contain simply a jump to some other locations (a "vector"), and that location can be anywhere in the flash address space.


Quote
3. Does Arduino compiler produce list file and Intel-Hex formatted file?
    If so, how can we get access to them?
It produces a .hex file that you can get at with "export compiled binary" option under "sketch" menu.  Or you can go to the build directory (copied from verbose compile log) and see it there.
No listing.  gcc listings tend not to be very useful.   You can use avr-objdump to create a disassembly.


Quote
4. If we wish to use the analog pins (A0 - A5) as digital output lines, do we need to set the directions
    of these lines as output (DDRC = 0xFF)? 
Yes.   Only the pins that you actually use as outputs, of course.  and pinMode() does the right thing; you don't need to revert to bare port manipulation.

Quote
5. Is there any Arduino C function to provide correct BCD...
There are no Arduino or avr-libc functions to do anything with BCD at all.   Nor does the underlying AVR architecture provide any support for BCD.   There is no reason to ever use BCD on an Arduino.  If you have to use BCD for (say) a school assignment or something, it is probably the intent that you write the functions completely from scratch.  Looking at the BCD instructions available on older chips like the 8080 might be useful:

 
Quote
15. DAA: - Decimal adjust accumulator.


The contents of the accumulator are changed from a binary value to two 4-bit binary coded decimal (BCD) digits. This is the only instruction that uses the auxiliary flag to perform the binary to BCD conversion, and the
 conversion procedure is described below. S, Z, AC, P, CY flags are altered to reflect the results of the operation.
If the value of the low-order 4-bits in the accumulator is greater than 9 or if AC flag is set, the instruction adds 6 to the low-order four bits. If the value of the high-order 4-bits in the accumulator is greater than 9 or if the Carry flag is set, the instruction adds 6 to the high-order four bits.

GolamMostafa

People sometimes ask: who (which organization) and when proposed these four rules? Any idea!

westfw

I have no idea which "4 rules" you are talking about.


GolamMostafa

One or more of the following four rules (refer your post #1) which the 80x86 (8085, 8051 but not ATmega) microprocessor applies to obtain correct BCD result after the addition of 8-bit BCD numbers.

For example:

mov     al, 09h     ; 09 is a BCD number
add      al, 01h     ; 01 is a BCD ; (al) = 0A in stead of 10
daa                    ; (al) = 10 = 00010000


(1) After the addition of two 8-bit BCD numbers if lower 4-bit is greater than 09 then add 06h with the
    incorrect BCD result to get the correct (adjusted) BCD result.

(2) After the addition of two 8-bit BCD numbers if upper 4-bit is greater than 09 then add 60h with the
    incorrect BCD result to get the correct (adjusted) BCD result.

(3) After the addition of two 8-bit BCD numbers if there is a generation of half (auxiliary) carry
    than 09 then add 06h with the incorrect BCD result to get the correct (adjusted) BCD result.

(4) After the addition of two 8-bit BCD numbers if there is a generation of full carry (carry)
    than 09 then add 60h with the incorrect BCD result to get the correct (adjusted) BCD result.


westfw

I dunno.  COBOL programmers like BCD a lot, and back before IEEE standard for floating point, IBM Mainframes (and perhaps others) had BCD-based floating point numbers.  I assume the algorithms are all well understood and probably published, back in the 1960s or so.  (Hmm.  50s.  Have you read the wikipedia article?  They reference "Arithmetic Operations in Digital Computers, R. K. Richards, 397pp, D. Van Nostrand Co., NY, 1955"

Some of it is simple math.  If you add 5 and 6, you get 11, which is greater than 9.  So you add 6, which gives you 17, or "1" in the low four bits and a carry into the next 4 bits.  Detecting "greater than 9" in hardware should be pretty easy (b3&(b2|b1))...


GolamMostafa

I dunno.  COBOL programmers like BCD a lot, and back before IEEE standard for floating point, IBM Mainframes (and perhaps others) had BCD-based floating point numbers.  I assume the algorithms are all well understood and probably published, back in the 1960s or so.  (Hmm.  50s.  Have you read the wikipedia article?  They reference "Arithmetic Operations in Digital Computers, R. K. Richards, 397pp, D. Van Nostrand Co., NY, 1955"

Some of it is simple math.  If you add 5 and 6, you get 11, which is greater than 9.  So you add 6, which gives you 17, or "1" in the low four bits and a carry into the next 4 bits.  Detecting "greater than 9" in hardware should be pretty easy (b3&(b2|b1))...


I dunno.  COBOL programmers like BCD a lot, and back before IEEE standard for floating point, IBM Mainframes (and perhaps others) had BCD-based floating point numbers.  I assume the algorithms are all well understood and probably published, back in the 1960s or so.  (Hmm.  50s.  Have you read the wikipedia article?  They reference "Arithmetic Operations in Digital Computers, R. K. Richards, 397pp, D. Van Nostrand Co., NY, 1955"

Some of it is simple math.  If you add 5 and 6, you get 11, which is greater than 9.  So you add 6, which gives you 17, or "1" in the low four bits and a carry into the next 4 bits.  Detecting "greater than 9" in hardware should be pretty easy (b3&(b2|b1))...


Thanks for the cool reply!

GolamMostafa

#7
Mar 04, 2017, 06:37 am Last Edit: Mar 04, 2017, 10:53 am by GolamMostafa
Knowing the fact that the Arduino C's delay() function has been implemented using TOV0 (Timer-0 Overflow) interrupt, I would like to know the basic Time Tick interrupt of the delay() function given the available clocking frequencies for Timer-0 are:

1. 16 Mhz/1 = 16 MHz (Period: .0625 uS)

2.  16 Mhz/8 =  2 M Hz ( Period: 0.5 uS)

3.  16 MHz/64 = 250 KHz (Period: 4 uS)

4.  16 MHz/256 = 62.5 KHz (Period: 16 uS)

5. 16 MHz/1024 = 15.625 KHZ (Period: 64 uS)

This information will help me to understand how the delay() function interrupt collides with INT0 interrupt and prevents ISR(INT0_vect) from undergoing correct execution.

westfw

(3): 4us - which is why the micros() function has a 4us resolution.
TOV0 happens every 256 ticks, or 1024us, and the ISR function does some tracking of the low digits to convert to milliseconds.

You know, all of the source code is included with the IDE download, or you can look at it online.
the overflow ISR is https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c#L42
and the timer initialization is in init(), further down in "wiring.c"
It's not extensively documented, but there ARE comments that say things like:
Code: [Select]
// set timer 0 prescale factor to 64


GolamMostafa

Is there any Learning Kit (board) of Arduino Family, which supports 64-bit data size? (Something like:
int quadruple_word.)

westfw

avr-gcc (as used in the Arduino IDE) supports a 64-bit integer type "long long" or "unsigned long long" - no additional hardware or SW needed.  It doesn't have a very good reputation for performance; apparently it starts using generic gcc library code (written in C) rather than optimized AVR code...

There's no support for 64bit floating point in avr-gcc (true "double"), though.

Imagecraft is a commercial compiler vendor that supports 64bit floats, in their $500 "pro" version.  I'm not sure about the other commercial compilers.

krupski

1. What are the Arduino Fuse Settings Values?
2. From what location of Flash, the application program begins execution.
3. Does Arduino compiler produce list file and Intel-Hex formatted file?
    If so, how can we get access to them?
4. If we wish to use the analog pins (A0 - A5) as digital output lines, do we need to set the directions
    of these lines as output (DDRC = 0xFF)?  
5. Is there any Arduino C function to provide correct BCD result for the incorrect BCD result that
    appears after the execution of the following instruction: unsigned char x1 = BCD1 (09);
    unsigned char y = BCD2 (03); unsigned char z = x + y (0x0C)? We want that z should
    contain 12?  
(1), (2) you need a copy of the Atmel datasheet. It will answer these questions as well as many others:

328P Datasheet

(3) You are mixing up terms. The Arduino IDE generates the strings required to run the AVR-GCC compiler. Although the compiler, as well as avr-objcopy and avr-objdump can be used to generate listing files, the Arduino IDE does not tell them to.  All it does is generate the Intel HEX files used to upload code to the AVR.

(4) Yes

(5) Don't know what you're using for BCD math, but here are two simple functions that should help you:

Code: [Select]
// convert decimal to BCD
uint8_t dec2bcd (uint8_t dec)
{
    return ((dec / 10 * 16) + (dec % 10));
}

// convert BCD to decimal
uint8_t bcd2dec (uint8_t bcd)
{
    return ((bcd / 16 * 10) + (bcd % 16));
}


Hope this helps.
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

krupski

avr-gcc (as used in the Arduino IDE) supports a 64-bit integer type "long long" or "unsigned long long" - no additional hardware or SW needed.  It doesn't have a very good reputation for performance; apparently it starts using generic gcc library code (written in C) rather than optimized AVR code...

There's no support for 64bit floating point in avr-gcc (true "double"), though.

Imagecraft is a commercial compiler vendor that supports 64bit floats, in their $500 "pro" version.  I'm not sure about the other commercial compilers.

Ever hear of "newlib"? https://sourceware.org/newlib/
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

westfw

Quote
Ever hear of "newlib"? https://sourceware.org/newlib/
Yeah.  Most of the free ARM and MIPS compilers end up using it for libc, don't they?

I thought floating point is normally in libgcc rather than libc, and newlib was more the latter.   But I see from the referenced page that newlib DOES include a bunch of higher-level floating point math functions (the stuff that would be in math.h.)    Does it have the basic add/subtract/multiply/divide?  How does it compare with the gcc functions?

Does it run on AVRs?

My general opinion of newlib on the sort of deeply-embedded systems like Arduino is not good;  It was designed for Real OS environments (linux/etc), and trimmed down (newlib nano) for smaller systems, but it still ends up looking pretty bloated compared to something like avr-libc that was designed for small microcontrollers from the ground up.  I was shocked when I noticed that the "obvious" way to add printf() support to MPIDE (PIC32/MIPS Arduino) ended up sucking in a whole filesystem layer :-(

I keep hoping someone will port avr-libc to ARM :-)

GolamMostafa

(1), (2) you need a copy of the Atmel datasheet. It will answer these questions as well as many others:

328P Datasheet

(3) You are mixing up terms. The Arduino IDE generates the strings required to run the AVR-GCC compiler. Although the compiler, as well as avr-objcopy and avr-objdump can be used to generate listing files, the Arduino IDE does not tell them to.  All it does is generate the Intel HEX files used to upload code to the AVR.

(4) Yes

(5) Don't know what you're using for BCD math, but here are two simple functions that should help you:

Code: [Select]
// convert decimal to BCD
uint8_t dec2bcd (uint8_t dec)
{
    return ((dec / 10 * 16) + (dec % 10));
}

// convert BCD to decimal
uint8_t bcd2dec (uint8_t bcd)
{
    return ((bcd / 16 * 10) + (bcd % 16));
}


Hope this helps.
Quote
(1), (2) you need a copy of the Atmel datasheet. It will answer these questions as well as many others:
1. My requirements are very objectives. It is the liberty of a Forum Member to provide the solution
    should he/she possesses.

2. Data sheets of ATmega328 say:
  (a) Default Fuse Settings: EFuse = 0xFF; HFuse =0xD9; LFuse = 0x62
       Major Interpretation: BOOTRST Fuse is unprogrammed. So, the MCU will always start up at
                                    location 0x0000. If we leave aside the vector space (0x0000 - 0x003F), the
                                    application program will usually begin at location 0x0040. In ASM we start
                                    with:
                                              .org    0x0000
                                     RESET: rjmp  0x0040

                                               .org   0x0040
                                      START: nop                     ; MLP begins
 
  (b) The ATmega328 of ArduinoUNO Board certainly has BOOTRST Fuse programmed (0), as it always
       starts up from 'Boot Flash location'.

  (c) The availability of the Fuse Settings of ArduinoUNO could help to understand the startup
       configuration of ATmega328 in respect of: Boot Size, CLKDIV8, and etc.

2.     From a posting (dc42) of the Arduino Forum, the Fuse Settings appeared:
       uno.bootloader.low_fuses=0xff
       uno.bootloader.high_fuses=0xde  = 1101 1110 ; Boot Loader Flash Section: 0x3F00 = 0x3FFF
       uno.bootloader.extended_fuses=0x05

3. By saying 'from what location does application program begin?': I wanted to know:
   (a) In ArduinoUNO, the MCU starts at location 0x3F00.

   (b) If there is no command from the Host for onward writing of a new sketch into the application
        flash, the control must be transferring to the beginning of the previously loaded application
        program.

   (c) What is the numerical address of this location? Is is dynamic or static?

4. I have been interested to see list file to check that the numerical values of the port addresses
    matches with that of the ATmega32. (Program written for ATmega328 using Arduino IDE does
    not run in ATmega32.)

5. BCD Math requirement: In AT89S52, we can use daa instruction to adjust incorrect BCD result
    after the addition of two BCD numbers (1235 + 76 (1311) --> 12AB = MOV  A, #35H;
    ADD   A, #76h; DAA  ; MOV  B, A; MOV  A, #12h; ADC A, #00H; AB contains correct BCD = 1311.

    The ATmega architecture does not contain instruction similar to DAA.   

5. Thanks for noticing my queries.

Go Up