DIP Boards have swapped Rx/Tx

A project log for Freeduino 4809

This is an Arduino Uno Wifi2 derivative (atmega4809) with the WiFi and other "extra" features deleted.

WestfWWestfW 07/31/2019 at 05:524 Comments

Sigh.  The DIP boards have the RX and TX pins swapped at the ATmega side.  A crossover works ("Hello World!" !!), and it's less relevant if you're not using particular USB/Serial module I'm using, but it's annoying.  I could swear I had checked that carefully  :-(

void uart_init() {
    VPORTA.DIR |= 1<<4;  // set TX pin to output
    VPORTA.OUT |= 1<<4;  // and "1" as per datasheet
    PORTMUX.USARTROUTEA = 1;  // alternate pinout to use PA4/5
    USART0.DBGCTRL = 1;  // run during debug
    USART0.CTRLC = (USART_CHSIZE_gm & USART_CHSIZE_8BIT_gc);  // Async, Parity Disabled, 1 StopBit
    USART0.CTRLA = 0;  // Interrupts: all off


James Newton wrote 08/05/2019 at 02:22 point

Made exactly the same mistake on my BOB PID board. Welcome to to club. rx and tx are stupid symbols. It should be ho and hi (host out and host in) or ho and pi (host out, peripheral in). Or anything that doesn't depend on point of view. 

  Are you sure? yes | no

WestfW wrote 08/05/2019 at 03:08 point

Oh, I've done it before as well (on the Z80 board, IIRC.) The annoying thing is that this time I was sure that I had CHECKED!

  Are you sure? yes | no

WestfW wrote 08/04/2019 at 22:09 point

Yes, the 4809 is set up more like an XMega chip; the peripherals are different, and prefer the structure-based definitions rather than individual #defines for each register.  There are a couple of advantages to the structure-based approach:

1) If you have multiple identical peripherals, you can treat them as such.  All the code above that references USART0 could equally reference USART1.  Or an abstracted USART via a pointer (myuart->BAUD = ...)  (this also gets rid of the rather silly (IMO) redundant defines: UCSR0A and UCSR1A or even PORTB1 and PORTD1...)

2) Since the peripherals are mostly in RAM space, code that accesses multiple registers in a peripheral will end up loading a base address into an index register and using smaller indexed-addressing instructions to get to the individual registers (compared to the LDS instructions it would need to access each register individually.  gcc isn't smart enough to optimize loads from 0x804, 0x805, and 0x806 into a load of 0x800 and indexed addressing instructions.  This will USUALLY result in shorter faster code.)
(The VPorts are still in IO space, so they can still be accessed with SBI/CBI for setting individual bits.)
Note that there is no disadvantage here.  The compiler IS smart enough to optimize a single access to a structure reference to the appropriate LDS/STS instruction.)

3) This is the way "the big boys" have done peripheral access for ages.  ARM, PIC32, X86, PPC, 68k, PDP11...  It's a natural for anything with memory-mapped peripherals and indexed addressing...

  Are you sure? yes | no

ronald.sutherland wrote 08/04/2019 at 19:02 point

That is different than the mega's I have looked at, I guess those defines are more or less how xmega was done. So this may be relevant:

I am confused with the virtual port stuff (e.g., "VPORTA.OUT" vs. "PORTA_OUT"). Does it have an advantage over the flattened fully qualified defines? I don't see PORTA_OUT4_bp in the iom4809 header; it would seem that some of the ideas got dropped.

  Are you sure? yes | no