From db87e0c875379d923f71be7d8a428738cd98e999 Mon Sep 17 00:00:00 2001 From: Wesley Roozing Date: Tue, 23 May 2017 20:17:23 +0200 Subject: [PATCH] Defined GCCPROGMEM for boards with ATmega 1280 and 2560 that have >64K of PROGMEM available, to fix #2226 --- hardware/arduino/avr/cores/arduino/Arduino.h | 27 +++++++++++++------ .../arduino/avr/variants/mega/pins_arduino.h | 23 +++++++++++----- .../avr/variants/standard/pins_arduino.h | 10 +++++++ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/Arduino.h b/hardware/arduino/avr/cores/arduino/Arduino.h index 09c14489506..b7cc5e330bc 100644 --- a/hardware/arduino/avr/cores/arduino/Arduino.h +++ b/hardware/arduino/avr/cores/arduino/Arduino.h @@ -158,16 +158,27 @@ void loop(void); #define analogInPinToBit(P) (P) +// Define GCCPROGMEM +// The GCCPROGMEM keyword ensures the resulting PGM data is stored in PGM at locations +// below 64K, allowing them to be accessed using 16-bit pointers and allowing the pin +// functions to work properly. The GCCPROGMEM keyword uses the .progmem.gcc.* section +// in the standard linker map, also used by gcc functions, storing the Arduino +// contents in .progmem.gcc.arduinocore.* +// Solves #2226: https://github.com/arduino/Arduino/issues/2226 +#ifndef GCCPROGMEM +#define GCCPROGMEM __attribute__((section(".progmem.gcc.arduinocore"))) +#endif + // On the ATmega1280, the addresses of some of the port registers are // greater than 255, so we can't store them in uint8_t's. -extern const uint16_t PROGMEM port_to_mode_PGM[]; -extern const uint16_t PROGMEM port_to_input_PGM[]; -extern const uint16_t PROGMEM port_to_output_PGM[]; - -extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; -// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; +extern const uint16_t GCCPROGMEM port_to_mode_PGM[]; +extern const uint16_t GCCPROGMEM port_to_input_PGM[]; +extern const uint16_t GCCPROGMEM port_to_output_PGM[]; + +extern const uint8_t GCCPROGMEM digital_pin_to_port_PGM[]; +// extern const uint8_t GCCPROGMEM digital_pin_to_bit_PGM[]; +extern const uint8_t GCCPROGMEM digital_pin_to_bit_mask_PGM[]; +extern const uint8_t GCCPROGMEM digital_pin_to_timer_PGM[]; // Get the bit location within the hardware port of the given virtual pin. // This comes from the pins_*.c file for the active board configuration. diff --git a/hardware/arduino/avr/variants/mega/pins_arduino.h b/hardware/arduino/avr/variants/mega/pins_arduino.h index 5115c044a4c..82f4721f459 100644 --- a/hardware/arduino/avr/variants/mega/pins_arduino.h +++ b/hardware/arduino/avr/variants/mega/pins_arduino.h @@ -111,7 +111,18 @@ static const uint8_t A15 = PIN_A15; #ifdef ARDUINO_MAIN -const uint16_t PROGMEM port_to_mode_PGM[] = { +// Define GCCPROGMEM +// The GCCPROGMEM keyword ensures the resulting PGM data is stored in PGM at locations +// below 64K, allowing them to be accessed using 16-bit pointers and allowing the pin +// functions to work properly. The GCCPROGMEM keyword uses the .progmem.gcc.* section +// in the standard linker map, also used by gcc functions, storing the Arduino +// contents in .progmem.gcc.arduinocore.* +// Solves #2226: https://github.com/arduino/Arduino/issues/2226 +#ifndef GCCPROGMEM +#define GCCPROGMEM __attribute__((section(".progmem.gcc.arduinocore"))) +#endif + +const uint16_t GCCPROGMEM port_to_mode_PGM[] = { NOT_A_PORT, (uint16_t) &DDRA, (uint16_t) &DDRB, @@ -127,7 +138,7 @@ const uint16_t PROGMEM port_to_mode_PGM[] = { (uint16_t) &DDRL, }; -const uint16_t PROGMEM port_to_output_PGM[] = { +const uint16_t GCCPROGMEM port_to_output_PGM[] = { NOT_A_PORT, (uint16_t) &PORTA, (uint16_t) &PORTB, @@ -143,7 +154,7 @@ const uint16_t PROGMEM port_to_output_PGM[] = { (uint16_t) &PORTL, }; -const uint16_t PROGMEM port_to_input_PGM[] = { +const uint16_t GCCPROGMEM port_to_input_PGM[] = { NOT_A_PIN, (uint16_t) &PINA, (uint16_t) &PINB, @@ -159,7 +170,7 @@ const uint16_t PROGMEM port_to_input_PGM[] = { (uint16_t) &PINL, }; -const uint8_t PROGMEM digital_pin_to_port_PGM[] = { +const uint8_t GCCPROGMEM digital_pin_to_port_PGM[] = { // PORTLIST // ------------------------------------------- PE , // PE 0 ** 0 ** USART0_RX @@ -234,7 +245,7 @@ const uint8_t PROGMEM digital_pin_to_port_PGM[] = { PK , // PK 7 ** 69 ** A15 }; -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { +const uint8_t GCCPROGMEM digital_pin_to_bit_mask_PGM[] = { // PIN IN PORT // ------------------------------------------- _BV( 0 ) , // PE 0 ** 0 ** USART0_RX @@ -309,7 +320,7 @@ const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { _BV( 7 ) , // PK 7 ** 69 ** A15 }; -const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { +const uint8_t GCCPROGMEM digital_pin_to_timer_PGM[] = { // TIMERS // ------------------------------------------- NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX diff --git a/hardware/arduino/avr/variants/standard/pins_arduino.h b/hardware/arduino/avr/variants/standard/pins_arduino.h index 2ea01905435..1399b5fed8f 100644 --- a/hardware/arduino/avr/variants/standard/pins_arduino.h +++ b/hardware/arduino/avr/variants/standard/pins_arduino.h @@ -119,6 +119,16 @@ static const uint8_t A7 = PIN_A7; // A0-A7 PF0-PF7 // A8-A15 PK0-PK7 +// Define GCCPROGMEM +// The GCCPROGMEM keyword ensures the resulting PGM data is stored in PGM at locations +// below 64K, allowing them to be accessed using 16-bit pointers and allowing the pin +// functions to work properly. The GCCPROGMEM keyword uses the .progmem.gcc.* section +// in the standard linker map, also used by gcc functions, storing the Arduino +// contents in .progmem.gcc.arduinocore.* +// Solves #2226: https://github.com/arduino/Arduino/issues/2226 +#ifndef GCCPROGMEM +#define GCCPROGMEM __attribute__((section(".progmem.gcc.arduinocore"))) +#endif // these arrays map port names (e.g. port B) to the // appropriate addresses for various functions (e.g. reading