@@ -169,24 +169,51 @@ extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
169
169
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
170
170
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM [];
171
171
extern const uint8_t PROGMEM digital_pin_to_timer_PGM [];
172
+ extern const uint8_t digital_pin_count ;
173
+
174
+ #define NOT_A_PIN 0
175
+ #define NOT_A_PORT 0
176
+
177
+ #define NOT_AN_INTERRUPT -1
172
178
173
179
// Get the bit location within the hardware port of the given virtual pin.
174
180
// This comes from the pins_*.c file for the active board configuration.
175
181
//
176
182
// These perform slightly better as macros compared to inline functions
177
- //
178
- #define digitalPinToPort (P ) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
179
- #define digitalPinToBitMask (P ) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
180
- #define digitalPinToTimer (P ) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
183
+ //
181
184
#define analogInPinToBit (P ) (P)
182
185
#define portOutputRegister (P ) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
183
186
#define portInputRegister (P ) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
184
187
#define portModeRegister (P ) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
185
-
186
- #define NOT_A_PIN 0
187
- #define NOT_A_PORT 0
188
-
189
- #define NOT_AN_INTERRUPT -1
188
+ //
189
+ // bounds checking on these functions because they return a pointer to an address that will be modified.
190
+ // An out of bounds write can result in stack corruption and fun to track-down errors.
191
+ //
192
+ static inline const uint8_t digitalPinToPort (const uint8_t P ) {
193
+ if (P > digital_pin_count ) {
194
+ return NOT_A_PIN ;
195
+ } else {
196
+ return pgm_read_byte ( digital_pin_to_port_PGM + P );
197
+ }
198
+ }
199
+ static inline const uint8_t digitalPinToBitMask (const uint8_t P ) {
200
+ if (P > digital_pin_count ) {
201
+ return NOT_A_PIN ;
202
+ } else {
203
+ return pgm_read_byte ( digital_pin_to_bit_mask_PGM + P );
204
+ }
205
+ }
206
+ static inline const uint8_t digitalPinToTimer (const uint8_t P ) {
207
+ if (P > digital_pin_count ) {
208
+ return NOT_A_PIN ;
209
+ } else {
210
+ return pgm_read_byte ( digital_pin_to_timer_PGM + P );
211
+ }
212
+ }
213
+ // these defines are to maintain backwards compatibility with #ifdef
214
+ #define digitalPinToPort digitalPinToPort
215
+ #define digitalPinToBitMask digitalPinToBitMask
216
+ #define digitalPinToTimer digitalPinToTimer
190
217
191
218
#ifdef ARDUINO_MAIN
192
219
#define PA 1
0 commit comments