Skip to content

Fix #2226 for boards that have >64K of PROGMEM available #6317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions hardware/arduino/avr/cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
23 changes: 17 additions & 6 deletions hardware/arduino/avr/variants/mega/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions hardware/arduino/avr/variants/standard/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down