## The USART double speed bit U2X set by default?

24 posts / 0 new
Author
Message

After banging my head for over an hour I decided to see if maybe, just maybe I did something wrong with the speed calculations and tried 19200 instead of the 9600 everything was set to work at. 'lo and behold, it worked. I had read the short USART section 3 times over and knew I did everything according to it. The only suspect was the U2X0 bit. So I tried setting it and the result was the same, the speed was still at 19200. So I forcibly cleared it during initialisation even though the datasheet says it's cleared on power-up and finally I had my 9600 bps.

So from now on I will always forcibly clear it when not wanted, but why is it set? Is the datasheet wrong? Did I miss something? Is it the bootloader doing something?

Thanks.

Edit: The board is an Arduino Pro mini that was supposed to be 16MHz but the vendor unloaded some 8MHz onto me. :( So Atmega328P 8MHz and I'm using VSCode with PlatformIO.

Last Edited: Tue. Oct 9, 2018 - 12:50 AM

Have never seen the bit set by default but the Arduino may set it that way.

EDIT from the datasheet

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

Last Edited: Tue. Oct 9, 2018 - 01:22 AM

The more I think about it, the more I think it's the bootloader. I should receive my 3\$ TinyISP soon si I'll try without the bootloader. If it is, it's probably documented somewhere but I'm just too lazy to read about bootloaders right now. Lazy means I'm having too much fun now that I switched from PIC to AVR to go read stuff about a problem I already solved!

Case closed. Blame it on the bootloader!

Have a good one!

I think you're right.  Optiboot (the current Uno bootloader, for quite some time now) is very careful to start the user sketch with the CPU state as close as possible to the original reset state.  Earlier bootloaders (ATmegaBoot as used in the Pro Minis) were not nearly so careful.

westfw wrote:

Optiboot (the current Uno bootloader, for quite some time now) is very careful to start the user sketch with the CPU state as close as possible to the original reset state.

If the bit is flipped by the bootloader, it probably goes unnoticed because most people do a plain assignment to the register with the bit cleared instead of only flipping the needed bits like I do (most of the times.) Or they think their arduino is overclocked and just roll with it.

And people wonder why I always initialise every register and avoid |=.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

Brian Fairchild wrote:
And people wonder why I always initialise every register and avoid |=.

I don't.  But my post count says I'm not a person yet.

I come from the PIC world and there, there is bit addressing. They also like to stuff their registers with bits belonging to different peripherals like the PIR1 register holding the bits for the PSP, ADC, USART, spi/i2c Serial bus (yes, it's shared), Timer1, Timer2 and CCP1 interrupts. So single bit manipulations are quite common over there.

I also like to initialise by device. If I need an interrupt or a pin for a device, I will configure it close to that device initialisation. It makes my life easier when I want to move things around and only costs a microsecond or two. So I'm not really afraid of single bit manipulations to the point of always doing things one way. Besides, the problem I encountered is probably of the very few and far between kind. Not worth changing my way of doing things. But I've been here (in the AVR world) for less than two week so know knows... I'm open-minded!

In the end, I guess it is to each his own!

Have a nice one!

The AVR instruction set also has bit manipulation instructions.

ASM codes are sbi (set bit immediate) and cbi (clear bit immediate).

A long time ago it was common to use C macro's to acces these asm instructions.

And then they got moved to:

/usr/lib/avr/include/compat/deprecated.h

/**
\ingroup deprecated_items
\def sbi(port, bit)
\deprecated

Set \c bit in IO port \c port.
*/
#define sbi(port, bit) (port) |= (1 << (bit))

I used to nitpick over small things.

When changing a single bit, |= gets translated to a sbi instruction and is the fastest.

When changing 3 or more bits in a single I/O register just loading a consstant and setting the whole byte is faster.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

Paulvdh wrote:

The AVR instruction set also has bit manipulation instructions.

ASM codes are sbi (set bit immediate) and cbi (clear bit immediate).

A long time ago it was common to use C macro's to acces these asm instructions.

And then they got moved to:

/usr/lib/avr/include/compat/deprecated.h

/**
\ingroup deprecated_items
\def sbi(port, bit)
\deprecated

Set \c bit in IO port \c port.
*/
#define sbi(port, bit) (port) |= (1 << (bit))

I used to nitpick over small things.

When changing a single bit, |= gets translated to a sbi instruction and is the fastest.

When changing 3 or more bits in a single I/O register just loading a consstant and setting the whole byte is faster.

sbi is a read-modify-write instruction; works for a single bit

For more bits you have no luck. You have to read-modify-write the whole byte by yourself.

What did you say in the last sentence is faster but not read-modify write. In other words, it isn't "changing".

Thanks both for those clarifications. One day I should send a fruit basket to the people developing compilers. I dread having to use asm. It's good to know it's there and that the compiler is taking care of it. Does the compiler also understand &= ~(1 << XYZ); to be a cbi or it's just a sbi thing?

JustinCase wrote:
Does the compiler also understand &= ~(1 << XYZ); to be a cbi or it's just a sbi thing?
Yep, but of course only when it's possible. SBI and CBI have a limited range of adresses, but I do not have the apetite to write much asm myself and I trust the compiler for such things.

Also, as you might know GCC uses asm as an intermediate step to generate a binary image, and it can generate listing files (.LSS) where generated asm is intertwined with the C source code as comment.

This can be a usefull tool to (for example) study the results of different C constructs and optimisations.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

JustinCase wrote:
Does the compiler also understand &= ~(1 << XYZ); to be a cbi or it's just a sbi thing?
Almost all the AVR C compilers are smart enough to know when something is in range of CBI/SBI, IN/OUT or only LDS/STS

For example this is avr-gcc with a mega328:

int main(void)
{
// these in range of SBI / CBI
PORTB |= (1 << 3);
PORTB &= ~(1 << 5);

// these in range of IN / OUT
MCUCR |= (1 << IVSEL);
MCUCR &= ~(1 << BODS);

// these only reachable with ST(S)/LD(S)
UCSR0B = (1 << TXEN0);
UCSR0B &= ~(1 << RXEN0);
}


the code generated is:

	// these in range of SBI / CBI
PORTB |= (1 << 3);
80:	2b 9a       	sbi	0x05, 3	; 5
PORTB &= ~(1 << 5);
82:	2d 98       	cbi	0x05, 5	; 5

// these in range of IN / OUT
MCUCR |= (1 << IVSEL);
84:	85 b7       	in	r24, 0x35	; 53
86:	82 60       	ori	r24, 0x02	; 2
88:	85 bf       	out	0x35, r24	; 53
MCUCR &= ~(1 << BODS);
8a:	85 b7       	in	r24, 0x35	; 53
8c:	8f 7b       	andi	r24, 0xBF	; 191
8e:	85 bf       	out	0x35, r24	; 53

// these only reachable with ST(S)/LD(S)
UCSR0B = (1 << TXEN0);
90:	e1 ec       	ldi	r30, 0xC1	; 193
92:	f0 e0       	ldi	r31, 0x00	; 0
94:	88 e0       	ldi	r24, 0x08	; 8
96:	80 83       	st	Z, r24
UCSR0B &= ~(1 << RXEN0);
98:	80 81       	ld	r24, Z
9a:	8f 7e       	andi	r24, 0xEF	; 239
9c:	80 83       	st	Z, r24


You, the programmer didn't have to tell the compiler which type of access to use (with optimization enabled) it will use the best it can. So if the target (PORTB) is low enough it can use SBI/CBI, if it's in range on IN/OUT (MCUCR) then those are used but if it's at a high SFR address then it has to use ST.

BTW see what happens if you switch the optimizer off:

    // these in range of SBI / CBI
PORTB |= (1 << 3);
88:	85 e2       	ldi	r24, 0x25	; 37
8a:	90 e0       	ldi	r25, 0x00	; 0
8c:	25 e2       	ldi	r18, 0x25	; 37
8e:	30 e0       	ldi	r19, 0x00	; 0
90:	f9 01       	movw	r30, r18
92:	20 81       	ld	r18, Z
94:	28 60       	ori	r18, 0x08	; 8
96:	fc 01       	movw	r30, r24
98:	20 83       	st	Z, r18
PORTB &= ~(1 << 5);
9a:	85 e2       	ldi	r24, 0x25	; 37
9c:	90 e0       	ldi	r25, 0x00	; 0
9e:	25 e2       	ldi	r18, 0x25	; 37
a0:	30 e0       	ldi	r19, 0x00	; 0
a2:	f9 01       	movw	r30, r18
a4:	20 81       	ld	r18, Z
a6:	2f 7d       	andi	r18, 0xDF	; 223
a8:	fc 01       	movw	r30, r24
aa:	20 83       	st	Z, r18

// these in range of IN / OUT
MCUCR |= (1 << IVSEL);
ac:	85 e5       	ldi	r24, 0x55	; 85
ae:	90 e0       	ldi	r25, 0x00	; 0
b0:	25 e5       	ldi	r18, 0x55	; 85
b2:	30 e0       	ldi	r19, 0x00	; 0
b4:	f9 01       	movw	r30, r18
b6:	20 81       	ld	r18, Z
b8:	22 60       	ori	r18, 0x02	; 2
ba:	fc 01       	movw	r30, r24
bc:	20 83       	st	Z, r18
MCUCR &= ~(1 << BODS);
be:	85 e5       	ldi	r24, 0x55	; 85
c0:	90 e0       	ldi	r25, 0x00	; 0
c2:	25 e5       	ldi	r18, 0x55	; 85
c4:	30 e0       	ldi	r19, 0x00	; 0
c6:	f9 01       	movw	r30, r18
c8:	20 81       	ld	r18, Z
ca:	2f 7b       	andi	r18, 0xBF	; 191
cc:	fc 01       	movw	r30, r24
ce:	20 83       	st	Z, r18

// these only reachable with ST(S)/LD(S)
UCSR0B = (1 << TXEN0);
d0:	81 ec       	ldi	r24, 0xC1	; 193
d2:	90 e0       	ldi	r25, 0x00	; 0
d4:	28 e0       	ldi	r18, 0x08	; 8
d6:	fc 01       	movw	r30, r24
d8:	20 83       	st	Z, r18
UCSR0B &= ~(1 << RXEN0);
da:	81 ec       	ldi	r24, 0xC1	; 193
dc:	90 e0       	ldi	r25, 0x00	; 0
de:	21 ec       	ldi	r18, 0xC1	; 193
e0:	30 e0       	ldi	r19, 0x00	; 0
e2:	f9 01       	movw	r30, r18
e4:	20 81       	ld	r18, Z
e6:	2f 7e       	andi	r18, 0xEF	; 239
e8:	fc 01       	movw	r30, r24
ea:	20 83       	st	Z, r18

(this is why I have an entry in my signature saying "never use -O0"!!!)

Last Edited: Thu. Oct 11, 2018 - 08:46 AM

Thanks again to both. Very instructive. I tried a few days ago to find those intermediate files I don't remember for which reason, but couldn't find them. All I could find was the .elf and .hex files (I want to believe.) I'm using PlatformIO inside VSCode (multi-cursor is so amazing!) and it took me forever just to find where to pass extra flags to the linker and another forever to understand how they're doing it!

I didn't know different address ranges could have different access methods and speed. It makes sense to have the PORTn registers somewhere fast. I did notice all the PORTn, PINn and DDRn had the high nibble at 0 when I was looking for a way to pass ports and pins as function/constructor parameters.

Now that I know my way around a bit more I think it's time to reset my working environment and take some time to understand it. As it is, I compile, look at the program memory used, change one instruction and re-compile to see if it takes more or less program memory.  Seems silly but that's how I found X &= ~(SomeConstantThatMadeSureXWouldEqual0); was fewer instructions than a plain X=0. With what's above I think I understand why even though that constant had 2 bits set (6 after the ~flip) and was most likely stored in the high address space. When I find those asm files I'll know the secret!

Thank again. Have a nice one!

JustinCase wrote:
I didn't know different address ranges could have different access methods and speed.

Interesting, I guess.  How much time have you spend with datasheets -- core, memory, register summary?

JustinCase wrote:
a way to pass ports and pins as function/constructor parameters.

...yet you are trying to implement "generic I/O" to which (as you are finding out) the AVR architecture is not well suited.  [As commented in prior discussions, are the port connections on your app board going to change during operation such that you need to "pass" the information?]

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.

theusch wrote:
are the port connections on your app board going to change during operation such that you need to "pass" the information?

+1!

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

theusch wrote:

JustinCase wrote:

I didn't know different address ranges could have different access methods and speed.

Interesting, I guess.  How much time have you spend with datasheets -- core, memory, register summary?

JustinCase wrote:

a way to pass ports and pins as function/constructor parameters.

...yet you are trying to implement "generic I/O" to which (as you are finding out) the AVR architecture is not well suited.  [As commented in prior discussions, are the port connections on your app board going to change during operation such that you need to "pass" the information?]

Lots and lots and lots of time with datasheets. All colors and flavors of datasheets. Sometimes the same one more than thrice. I don't like using pre-made libraries and I'm stubborn, so I read. But as far as MCU goes I mostly skip the part about the asm instruction set and memory organisation. Always have. It's not my cup of tea. But even if I don't write in asm, I think it's informations that is good to know.

My first dabbling with AVR a couple weeks ago was with some Arduino stuff and I knew many things were different from PICs, just not how much. I noticed some libraries were passing, say, the Chip Select pin as a constructor parameter, but as 1 parameter for both the port and pin. I thought it was an usual AVR thing so I wanted to find out how it was done and do it that way too. I since figured it's simply a pinToPort-like macro based on the particular Arduino board so I ditched that idea although stuffing the pin # in the high nibble of the port/ddr/pin address is tempting, just because! It's also not generic I/O but very specific I/O needs!

Stuff on the board itself will seldom change during operation, but I like to re-use my code and going back in the source of a library just to set which pin is CS, RST and so on is annoying and already caused me a few headaches because I forgot to change them after moving things around on the board WHILE developing. That source code is also used by different projects so changing it for one means it changes for all. Also, how am I supposed to use two of the same thing if the CS pin is hardcoded? Port and pin as a parameter makes perfect sense to me. I don't understand how someone with over 38k posts doesn't get that.

Right now I have a TFT display, BMP280, DFPlayer (with feedback), INA219, motion sensor, rotary encoder, DS3231 RTC, SD card reader, external flash, LDR to set the PWM for the LCD backlight, a switch and last but not least, a feedback LED all hooked on that poor Pro mini. I'm pushing it too see what it can take (and it's a lot!) so I don't have much choice as far as pin selection goes. I even had to put pins on the board for A6/A7!

Here's a nice little pic of my board. I called the project 'BiGMess.'

No Adafruit library or Arduino.h was used in this picture. I don't think that would be possible anyway. Some of that Adafruit stuff is terrible.

So yeah, the more I know the happier I am. Even if it's something that's not going to be used.

Have a nice one!

ki0bk wrote:

theusch wrote:

are the port connections on your app board going to change during operation such that you need to "pass" the information?

+1!

Will I get a +1 too?

JustinCase wrote:
Will I get a +1 too?

At the risk of being lambasted, not from me.  Yes, certainly, things can get confusing.  But on the one hand saying you read a lot in the datasheets and then saying you never looked at the core,memory,I/(O register sections on the other hand, even when a situation related to them, seems contradictory.  On the one hand you don't use libraries yet on the other hand the original situation was apparently caused by using pre-built code, and not initializing used peripherals.  In a similar vein, it appears that you are using pre-built mechanisms for generic I/O?  Yet you seem concerned with when a CBI is generated.  Lessee -- a few cycles and words for direct access, and many words and cycles for generic.

That's all I'm pointing out.  Remember that I am the resident Surly Curmudgeon.

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.

theusch wrote:

JustinCase wrote:

Will I get a +1 too?

At the risk of being lambasted, not from me.  Yes, certainly, things can get confusing.  But on the one hand saying you read a lot in the datasheets and then saying you never looked at the core,memory,I/(O register sections on the other hand, even when a situation related to them, seems contradictory.  On the one hand you don't use libraries yet on the other hand the original situation was apparently caused by using pre-built code, and not initializing used peripherals.  In a similar vein, it appears that you are using pre-built mechanisms for generic I/O?  Yet you seem concerned with when a CBI is generated.  Lessee -- a few cycles and words for direct access, and many words and cycles for generic.

That's all I'm pointing out.  Remember that I am the resident Surly Curmudgeon.

Mostly skip isn't 'never looking.' You'd make a terrible pre-processor if you re-interpret words however you want. I take what I need, when I need it, once I find out I need it. And the code that is being talked about in the OP is the bootloader code. I highly doubt any of you wrote their own bootloader.

What pre-built mechanism are you referring to? Is there any? And for what generic I/O? I thought I made it clear it was specific I/O (CS/RST/SQW/etc.) I looked at some Arduino code to see how they were passing the port AND pin as ONE parameter in the examples, and found out it was an Arduino thing and not an AVR thing. So I'm doing it my way instead, but I'm tempted to stuff the pin # in the high nibble of the port/ddr/pin register address constructor parameter since they're all in the 0x0 to 0xF range (not considering the 0x20 offset, before you get all pedantic on me.) Not for any particular reason, just because it could be done. But I won't.

The rest seems like generic Internet rambling... It feels like you didn't even read half my post.

JustinCase wrote:
You'd make a terrible pre-processor if you re-interpret words however you want.

Sheesh.  Please list specific examples of your works and my "re-interpretation".  I went back and re-read what YOU POSTED.  OK, fine....I'll go away from this thread.

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.

JustinCase wrote:
What pre-built mechanism are you referring to?
JustinCase wrote:
I don't like using pre-made libraries and I'm stubborn
JustinCase wrote:
And for what generic I/O?
JustinCase wrote:
I was looking for a way to pass ports and pins as function/constructor parameters.

JustinCase wrote:
an Arduino thing and not an AVR thing.

Do I even need to respond to that one?  Are you using an Arduino variant >>not<< based on AVR?

JustinCase wrote:
The rest seems like generic Internet rambling...
???

theusch wrote:
Yet you seem concerned with when a CBI is generated. Lessee -- a few cycles and words for direct access, and many words and cycles for generic.
(do I need to find the cycle-counting references?)

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.

JustinCase wrote:

.... I'm tempted to stuff the pin # in the high nibble of the port/ddr/pin register

address constructor parameter since they're all in the 0x0 to 0xF range ....

Not always!  The ATmega2560, for example, has several ports (H,J,K,L) located

in the address range 0x0100 - 0x010B.

--Mike

JustinCase wrote:

I highly doubt any of you wrote their own bootloader.

Then you'd be wrong.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

Brian Fairchild wrote:
Then you'd be wrong.
+1

In fact do we score more if we've written several ??

Also, if you visit the project section here exactly how many "home written" bootloaders do you find there? I haven't looked but if it's not at least 20+ I'd be astonished.

What's more there are regular questions in the forums here from others writing their own bootloaders. Maybe 1 or 2 a week. In fact right now there are at least 2 active threads discussing the very thing. Just a search for the term SPM will hit 1,000's of prior threads.

EDIT: in fact...

etc.

EDIT2: Oh and there are 32 projects in the project section here with "bootloader" in the title.

Last Edited: Fri. Oct 12, 2018 - 11:25 AM