The USART double speed bit U2X set by default?

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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!

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

I think it's the bootloader.

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.

 

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

westfw wrote:

I think it's the bootloader.

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. cheeky

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

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

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

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

 

I don't. wink 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!

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

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.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

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

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".

 

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

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?

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

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.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

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

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
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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. laugh 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!

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

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.

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

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!

share.robinhood.com/jamesc3274

 

 

 

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

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.' smiley

 

 

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!

 

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

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?

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

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.

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

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.

 

 

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

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.

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

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.

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

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

 

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

JustinCase wrote:

I highly doubt any of you wrote their own bootloader.

 

Then you'd be wrong. cheeky

 

#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

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

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