Skip to content

Commit

Permalink
Address #565
Browse files Browse the repository at this point in the history
  • Loading branch information
SpenceKonde committed Dec 19, 2021
1 parent ea2449d commit 62604d3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 27 deletions.
12 changes: 8 additions & 4 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ This page documents (nearly) all bugfixes and enhancements that produce visible
## Changes not yet in release
Changes listed here are checked in to GitHub ("master" branch unless specifically noted; this is only done when a change involves a large amount of work and breaks the core in the interim, or where the change is considered very high risk, and needs testing by others prior to merging the changes with master). These changes are not yet in any "release" nor can they be installed through board manager, only downloading latest code from github will work. These changes will be included in the listed version, though planned version numbers may change without notice - critical fixes may be inserted before a planned release and the planned release bumped up a version, or versions may go from patch to minor version depending on the scale of changes.

## Planned 2.5.1
* Added support for serial buffer sizes of 256.
* Added test for defined(USE_ASM_TXC), USE_ASM_RXC, and USE_ASM_DRE in UART.h so that variants and board definitions can now turn this off.
* Attempting to use illegal options, like buffer sizes that aren't powers of 2, now errors out.

### Ongoing
* Port enhanced documentation from DxCore.

### Planned 2.5.0
## Released Versions

### 2.5.0
* **New I2C/TWI implementation** (I2C and TWI refer to the same interface, the one provided by Wire.h; don't get me started about how these and the library are named).
* Support for acting as both master and slave (on the same pins); this configuration, sometimes known as "multi-master", includes not only the simple case of multiple masters and slaves on an I2C bus, each of which is always exclusively either a master or a slave, but also the more complicated case, which has been a frequent request: For the AVR device to act as both master AND slave. It can both initiate transactions with slaves, or respond to transactions initiated by other masters.
* New tools menu option to select whether to support only being a master *or* a slave, as we do now (default) or to support acting as both master *and* slave (new functionality).
Expand Down Expand Up @@ -49,9 +56,6 @@ Changes listed here are checked in to GitHub ("master" branch unless specificall
* Improve methods used to block attempts to use "upload using programmer" when an optiboot board is selected. That confiuration is guaranteed not to work, and we should not do things that we know 100% will not work. We would need a merged output file for this, but the IDE doesn;t make those for us here. (only over on attinycore, where they're not usable and we must go out of our way to delete the damned things)
* Timers.h shared with DxCore.


## Released Versions

### 2.4.2
* Correct bug with openDrainFast(pin,CHANGE); This was a really nasty one, albeit for a rare corner case. Using CHANGE on a pin that was not on PORTA would alter other settings for other pins seemingly at random instead due to a missing '0x' in a memory offset.
* Add a whole bunch of missing devices to SerialUPDI.
Expand Down
22 changes: 14 additions & 8 deletions megaavr/cores/megatinycore/UART.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ ISR(USART1_TXC_vect, ISR_NAKED) {
}
*/
#if (defined(USE_ASM_RXC) && USE_ASM_RXC == 1 && (SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) /* && defined(USART1)*/ )
#if (defined(USE_ASM_RXC) && USE_ASM_RXC == 1 && (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) /* && defined(USART1)*/ )
// We only ever use this on the 2-series. 1-series doesn't gain anything with this. The inlining makes the compiler FAR more efficient. RXC isn't compiled stupidly,
// the problem is that the ABI requires it to be inefficient as hell. But it's a big deal for the smaller size 2-series parts.
void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) _do_rxc(void) {
Expand Down Expand Up @@ -151,9 +151,10 @@ ISR(USART1_TXC_vect, ISR_NAKED) {
"andi r24, 0x1F" "\n\t" // Wrap the head around
#elif SERIAL_RX_BUFFER_SIZE == 16
"andi r24, 0x0F" "\n\t" // Wrap the head around
#else
#elif SERIAL_RX_BUFFER_SIZE != 256
#error "Can't happen - we already checked for unsupported buffer sizes!"
#endif
// otherwise it's 256, and wraps around naturally.
"ldd r18, Z + 18" "\n\t" // load tail index
"cp r18, r24" "\n\t" // See if head is at tail. If so, buffer full,
"breq _end_rxc" "\n\t" // can't do anything, just restore state and leave.
Expand Down Expand Up @@ -222,8 +223,8 @@ ISR(USART0_DRE_vect, ISR_NAKED) {
*/

#if defined(USE_ASM_DRE) && USE_ASM_DRE == 1 && \
(SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
(SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16)
(SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
(SERIAL_TX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16)
void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) _do_dre(void) {
__asm__ __volatile__(
"_do_dre:" "\n\t"
Expand All @@ -245,7 +246,11 @@ ISR(USART0_DRE_vect, ISR_NAKED) {
"movw r26, r30" "\n\t" // copy of serial in X
"add r26, r25" "\n\t" // Serial + txtail - txtail 0~63
"adc r27, r18" "\n\t" // Carry (X = &Serial + 0~63)
#if SERIAL_RX_BUFFER_SIZE == 128
#if SERIAL_RX_BUFFER_SIZE == 256
"subi r26, 0xEB" "\n\t" //
"sbci r27, 0xFE" "\n\t" // +277
"ld r24, X" "\n\t" // grab the character
#elif SERIAL_RX_BUFFER_SIZE == 128
"subi r26, 0x6B" "\n\t" //
"sbci r27, 0xFF" "\n\t" // +149
"ld r24, X" "\n\t" // grab the character
Expand Down Expand Up @@ -274,9 +279,10 @@ ISR(USART0_DRE_vect, ISR_NAKED) {
"andi r25, 0x1F" "\n\t" // Wrap the head around
#elif SERIAL_TX_BUFFER_SIZE == 16
"andi r25, 0x0F" "\n\t" // Wrap the head around
#else
#elif SERIAL_TX_BUFFER_SIZE != 256
#error "Can't happen - we already checked for unsupported buffer sizes!"
#endif
// otherwise it's 256, and wraps around naturally.
"ldd r24, Y + 5" "\n\t" // get CTRLA into r24
"ldd r18, Z + 19" "\n\t" // txhead into r18
"cpse r18, r25" "\n\t" // if they're the same
Expand Down Expand Up @@ -370,8 +376,8 @@ void UartClass::_poll_tx_data_empty(void) {
return;
}
#if !(defined(USE_ASM_DRE) && USE_ASM_DRE == 1 && \
(SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
(SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
(SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
(SERIAL_TX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
_tx_data_empty_irq(*this);
#else
#ifdef USART1
Expand Down
50 changes: 35 additions & 15 deletions megaavr/cores/megatinycore/UART.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,17 @@
* (to be fair, you are allowed to use external RAM - also I think
* a unique feature)
*/
#define USE_ASM_TXC 1 // This *appears* to work? It's the easy one. saves 6b for 1 USART, 50 for 2.
#define USE_ASM_RXC 1 // This now works. Saves only 4b for 1 usart but 102 for 2.
#define USE_ASM_DRE 1 // This is the hard one...Depends on BOTH buffers, and has that other method of calling it. saves 34b for 1 USART 102 for 2
#if !defined(USE_ASM_TXC)
#define USE_ASM_TXC 1 // This *appears* to work? It's the easy one. saves 6b for 1 USART, 50 for 2.
#endif

#if !defined(USE_ASM_RXC)
#define USE_ASM_RXC 1 // This now works. Saves only 4b for 1 usart but 102 for 2.
#endif

#if !defined(USE_ASM_DRE)
#define USE_ASM_DRE 1 // This is the hard one...Depends on BOTH buffers, and has that other method of calling it. saves 34b for 1 USART 102 for 2
#endif
// savings:
// 44 total for 0/1,
// 301 for 2-series, which may be nearly 9% of the total flash!
Expand Down Expand Up @@ -108,6 +116,30 @@
#error "ERROR: RX buffer size must be a power of two."
#endif

#if defined(USE_ASM_RXC) && USE_ASM_RXC == 1 && !(SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16)
#error "Assembly RX Complete (RXC) ISR is only supported when RX buffer size are 256, 128, 64, 32 or 16 bytes"
#endif

#if defined(USE_ASM_DRE) && USE_ASM_DRE == 1 && !((SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
(SERIAL_TX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
#error "Assembly Data Register Empty (DRE) ISR is only supported when both TX and RX buffer sizes are 256, 128, 64, 32 or 16 bytes"
#endif


#define syncBegin(port, baud, config, syncopts) ({\
if ((config & 0xC0) == 0x40) \
{pinConfigure(port.getPin(2), syncopts); \
port.begin(baud >> 3, config); \
}})

#define mspiBegin(port, baud, config, invert) ({ \
if ((config & 0xC0) == 0xC0) { \
pinConfigure(port.getPin(2), invert); \
port.begin(baud >> 3, config); \
}})



// tinyAVR 0/1-series has 2 bits devoted to RS485, supporting normal (00), RS485 with XDIR driven to control
// an external line driver (01), and some other mysterious mode (10) the function of which is unclear. There is
// evidence that this poorly documented feature is also present in other hardware, and was only removed on paper.
Expand Down Expand Up @@ -173,18 +205,6 @@ const uint8_t _usart_pins[][4] = {
*/


#define syncBegin(port, baud, config, syncopts) ({\
if ((config & 0xC0) == 0x40) \
{pinConfigure(port.getPin(2), syncopts); \
port.begin(baud >> 3, config); \
}})

#define mspiBegin(port, baud, config, invert) ({ \
if ((config & 0xC0) == 0xC0) { \
pinConfigure(port.getPin(2), invert); \
port.begin(baud >> 3, config); \
}})


/* DANGER DANGER DANGER */
/* CHANGING THE MEMBER VARIABLES BETWEEN HERE AND THE OTHER SCARY COMMENT WILL COMPLETELY BREAK SERIAL
Expand Down

0 comments on commit 62604d3

Please sign in to comment.