diff --git a/SampleProjects/TestSomething/test/godmode.cpp b/SampleProjects/TestSomething/test/godmode.cpp index e6c69502..15c13f3c 100644 --- a/SampleProjects/TestSomething/test/godmode.cpp +++ b/SampleProjects/TestSomething/test/godmode.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "fibonacciClock.h" GodmodeState* state = GODMODE(); diff --git a/cpp/arduino/Arduino.h b/cpp/arduino/Arduino.h index e107126e..4cec73ad 100644 --- a/cpp/arduino/Arduino.h +++ b/cpp/arduino/Arduino.h @@ -14,8 +14,6 @@ Where possible, variable names from the Arduino library are used to avoid confli #include "Print.h" #include "Stream.h" #include "HardwareSerial.h" -#include "SPI.h" -#include "Wire.h" typedef bool boolean; typedef uint8_t byte; diff --git a/cpp/arduino/Godmode.h b/cpp/arduino/Godmode.h index 12fa1b51..6887769b 100644 --- a/cpp/arduino/Godmode.h +++ b/cpp/arduino/Godmode.h @@ -1,6 +1,8 @@ #pragma once #include "ArduinoDefines.h" +#if defined(__AVR__) #include +#endif #include "WString.h" #include "PinHistory.h" @@ -18,16 +20,18 @@ unsigned long micros(); #define MOCK_PINS_COUNT 256 -#if defined(UBRR3H) - #define NUM_SERIAL_PORTS 4 -#elif defined(UBRR2H) - #define NUM_SERIAL_PORTS 3 -#elif defined(UBRR1H) - #define NUM_SERIAL_PORTS 2 -#elif defined(UBRRH) || defined(UBRR0H) - #define NUM_SERIAL_PORTS 1 -#else - #define NUM_SERIAL_PORTS 0 +#if (!defined NUM_SERIAL_PORTS) + #if defined(UBRR3H) + #define NUM_SERIAL_PORTS 4 + #elif defined(UBRR2H) + #define NUM_SERIAL_PORTS 3 + #elif defined(UBRR1H) + #define NUM_SERIAL_PORTS 2 + #elif defined(UBRRH) || defined(UBRR0H) + #define NUM_SERIAL_PORTS 1 + #else + #define NUM_SERIAL_PORTS 0 + #endif #endif class GodmodeState { diff --git a/cpp/arduino/HardwareSerial.h b/cpp/arduino/HardwareSerial.h index d4ea97f9..68c2010c 100644 --- a/cpp/arduino/HardwareSerial.h +++ b/cpp/arduino/HardwareSerial.h @@ -44,19 +44,19 @@ class HardwareSerial : public StreamTape operator bool() { return true; } }; -#if defined(UBRRH) || defined(UBRR0H) +#if NUM_SERIAL_PORTS >= 1 extern HardwareSerial Serial; #define HAVE_HWSERIAL0 #endif -#if defined(UBRR1H) +#if NUM_SERIAL_PORTS >= 2 extern HardwareSerial Serial1; #define HAVE_HWSERIAL1 #endif -#if defined(UBRR2H) +#if NUM_SERIAL_PORTS >= 3 extern HardwareSerial Serial2; #define HAVE_HWSERIAL2 #endif -#if defined(UBRR3H) +#if NUM_SERIAL_PORTS >= 4 extern HardwareSerial Serial3; #define HAVE_HWSERIAL3 #endif diff --git a/cpp/arduino/SPI.h b/cpp/arduino/SPI.h index f10cd201..e22be357 100644 --- a/cpp/arduino/SPI.h +++ b/cpp/arduino/SPI.h @@ -94,10 +94,14 @@ class SPIClass: public ObservableDataStream { uint16_t transfer16(uint16_t data) { union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; in.val = data; + #if defined(SPCR) && defined(DORD) if (!(SPCR & (1 << DORD))) { out.msb = transfer(in.msb); out.lsb = transfer(in.lsb); - } else { + } + else + #endif + { out.lsb = transfer(in.lsb); out.msb = transfer(in.msb); } diff --git a/cpp/arduino/avr/pgmspace.h b/cpp/arduino/avr/pgmspace.h index 6b21287b..cab19057 100644 --- a/cpp/arduino/avr/pgmspace.h +++ b/cpp/arduino/avr/pgmspace.h @@ -14,8 +14,10 @@ out = externs.map {|l| l.split("(")[0].split(" ")[-1].gsub("*", "") }.uniq out.each { |l| puts d(l) } */ -#include #include +#include +#include +#include #define PROGMEM @@ -27,6 +29,11 @@ out.each { |l| puts d(l) } #define PGM_VOID_P const void * #endif +// These are normally 32-bit, but here use (u)intptr_t to ensure a pointer can +// always be safely cast to these types. +typedef intptr_t int_farptr_t; +typedef uintptr_t uint_farptr_t; + // everything's a no-op #define PSTR(s) ((const char *)(s)) @@ -34,13 +41,13 @@ out.each { |l| puts d(l) } #define pgm_read_word_near(address_short) (* (const uint16_t *) (address_short) ) #define pgm_read_dword_near(address_short) (* (const uint32_t *) (address_short) ) #define pgm_read_float_near(address_short) (* (const float *) (address_short) ) -#define pgm_read_ptr_near(address_short) (* (const void *) (address_short) ) +#define pgm_read_ptr_near(address_short) (* (const void **) (address_short) ) #define pgm_read_byte_far(address_long) (* (const uint8_t *) (address_long) ) #define pgm_read_word_far(address_long) (* (const uint16_t *) (address_long) ) #define pgm_read_dword_far(address_long) (* (const uint32_t *) (address_long) ) #define pgm_read_float_far(address_long) (* (const float *) (address_long) ) -#define pgm_read_ptr_far(address_long) (* (const void *) (address_long) ) +#define pgm_read_ptr_far(address_long) (* (const void **) (address_long) ) #define pgm_read_byte(address_short) pgm_read_byte_near(address_short) #define pgm_read_word(address_short) pgm_read_word_near(address_short) @@ -50,46 +57,69 @@ out.each { |l| puts d(l) } #define pgm_get_far_address(var) ( (uint_farptr_t) (&(var)) ) -#define memchr_P(...) ::memchr(__VA_ARGS__) -#define memcmp_P(...) ::memcmp(__VA_ARGS__) -#define memccpy_P(...) ::memccpy(__VA_ARGS__) -#define memcpy_P(...) ::memcpy(__VA_ARGS__) -#define memmem_P(...) ::memmem(__VA_ARGS__) -#define memrchr_P(...) ::memrchr(__VA_ARGS__) -#define strcat_P(...) ::strcat(__VA_ARGS__) -#define strchr_P(...) ::strchr(__VA_ARGS__) -#define strchrnul_P(...) ::strchrnul(__VA_ARGS__) -#define strcmp_P(...) ::strcmp(__VA_ARGS__) -#define strcpy_P(...) ::strcpy(__VA_ARGS__) -#define strcasecmp_P(...) ::strcasecmp(__VA_ARGS__) -#define strcasestr_P(...) ::strcasestr(__VA_ARGS__) -#define strcspn_P(...) ::strcspn(__VA_ARGS__) -#define strlcat_P(...) ::strlcat(__VA_ARGS__) -#define strlcpy_P(...) ::strlcpy(__VA_ARGS__) -#define strnlen_P(...) ::strnlen(__VA_ARGS__) -#define strncmp_P(...) ::strncmp(__VA_ARGS__) -#define strncasecmp_P(...) ::strncasecmp(__VA_ARGS__) -#define strncat_P(...) ::strncat(__VA_ARGS__) -#define strncpy_P(...) ::strncpy(__VA_ARGS__) -#define strpbrk_P(...) ::strpbrk(__VA_ARGS__) -#define strrchr_P(...) ::strrchr(__VA_ARGS__) -#define strsep_P(...) ::strsep(__VA_ARGS__) -#define strspn_P(...) ::strspn(__VA_ARGS__) -#define strstr_P(...) ::strstr(__VA_ARGS__) -#define strtok_P(...) ::strtok(__VA_ARGS__) -#define strtok_P(...) ::strtok(__VA_ARGS__) -#define strlen_P(...) ::strlen(__VA_ARGS__) -#define strnlen_P(...) ::strnlen(__VA_ARGS__) -#define memcpy_P(...) ::memcpy(__VA_ARGS__) -#define strcpy_P(...) ::strcpy(__VA_ARGS__) -#define strncpy_P(...) ::strncpy(__VA_ARGS__) -#define strcat_P(...) ::strcat(__VA_ARGS__) -#define strlcat_P(...) ::strlcat(__VA_ARGS__) -#define strncat_P(...) ::strncat(__VA_ARGS__) -#define strcmp_P(...) ::strcmp(__VA_ARGS__) -#define strncmp_P(...) ::strncmp(__VA_ARGS__) -#define strcasecmp_P(...) ::strcasecmp(__VA_ARGS__) -#define strncasecmp_P(...) ::strncasecmp(__VA_ARGS__) -#define strstr_P(...) ::strstr(__VA_ARGS__) -#define strlcpy_P(...) ::strlcpy(__VA_ARGS__) -#define memcmp_P(...) ::memcmp(__VA_ARGS__) +inline const void * memchr_P(const void *s, int val, size_t len) { return memchr(s, val, len); } +inline int memcmp_P(const void *s1, const void *s2, size_t len) { return memcmp(s1, s2, len); } +inline void *memcpy_P(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); } +inline char *strcat_P(char *dest, const char *src) { return strcat(dest, src); } +inline const char *strchr_P(const char *s, int val) { return strchr(s, val); } +inline int strcmp_P(const char *s1, const char *s2) { return strcmp(s1, s2); } +inline char *strcpy_P(char *dest, const char *src) { return strcpy(dest, src); } +inline size_t strcspn_P(const char *s, const char *reject) { return strcspn(s, reject); } +// strlcat and strlcpy are AVR-specific and not entirely trivial to reimplement using strncat it seems +//inline size_t strlcat_P(char *dst, const char *src, size_t siz) { return strlcat(dst, src, siz); } +//inline size_t strlcpy_P(char *dst, const char *src, size_t siz) { return strlcpy(dst, src, siz); } +//inline size_t strlcat_PF(char *dst, uint_farptr_t src, size_t n) { return strlcat(dst, (const char*)src, n); } +//inline size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz) { return strlcpy(dst, (const char*)src, siz); } +inline int strncmp_P(const char *s1, const char *s2, size_t n) { return strncmp(s1, s2, n); } +inline char *strncat_P(char *dest, const char *src, size_t len) { return strncat(dest, src, len); } +inline char *strncpy_P(char *dest, const char *src, size_t n) { return strncpy(dest, src, n); } +inline char *strpbrk_P(const char *s, const char *accept) { return (char*)strpbrk(s, accept); } +inline const char *strrchr_P(const char *s, int val) { return strrchr(s, val); } +inline size_t strspn_P(const char *s, const char *accept) { return strspn(s, accept); } +inline char *strstr_P(const char *s1, const char *s2) { return (char*)strstr(s1, s2); } +inline char *strtok_P(char *s, const char * delim) { return strtok(s, delim); } +inline size_t strlen_PF(uint_farptr_t s) { return strlen((char*)s); } +inline void *memcpy_PF(void *dest, uint_farptr_t src, size_t n) { return memcpy(dest, (const char*)src, n); } +inline char *strcpy_PF(char *dst, uint_farptr_t src) { return strcpy(dst, (const char*)src); } +inline char *strncpy_PF(char *dst, uint_farptr_t src, size_t n) { return strncpy(dst, (const char*)src, n); } +inline char *strcat_PF(char *dst, uint_farptr_t src) { return strcat(dst, (const char*)src); } +inline char *strncat_PF(char *dst, uint_farptr_t src, size_t n) { return strncat(dst, (const char*)src, n); } +inline int strcmp_PF(const char *s1, uint_farptr_t s2) { return strcmp(s1, (const char*)s2); } +inline int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncmp(s1, (const char*)s2, n); } +inline char *strstr_PF(const char *s1, uint_farptr_t s2) { return (char*)strstr(s1, (const char*)s2); } +inline int memcmp_PF(const void *s1, uint_farptr_t s2, size_t len) { return memcmp(s1, (const char*)s2, len); } +inline size_t strlen_P(const char *src) { return strlen(src); } + +// TODO: These functions cannot be found on the CYGWIN test build for +// some reason, so disable them for now. Most of these are less common +// and/or GNU-specific addons anyway +//inline void *memccpy_P(void *dest, const void *src, int val, size_t len) { return memccpy(dest, src, val, len); } +//inline void *memmem_P(const void *s1, size_t len1, const void *s2, size_t len2) { return memmem(s1, len1, s2, len2); } +//inline const void *memrchr_P(const void *src, int val, size_t len) { return memrchr(src, val, len); } +//inline const char *strchrnul_P(const char *s, int c) { return strchrnul(s, c); } +//inline int strcasecmp_P(const char *s1, const char *s2) { return strcasecmp(s1, s2); } +//inline char *strcasestr_P(const char *s1, const char *s2) { return (char*)strcasestr(s1, s2); } +//inline int strncasecmp_P(const char *s1, const char *s2, size_t n) { return strncasecmp(s1, s2, n); } +//inline char *strsep_P(char **sp, const char *delim) { return strsep(sp, delim); } +//inline char *strtok_r_P(char *string, const char *delim, char **last) { return strtok_r(string, delim, last); } +//inline int strcasecmp_PF(const char *s1, uint_farptr_t s2) { return strcasecmp(s1, (const char*)s2); } +//inline int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncasecmp(s1, (const char*)s2, n); } +//inline size_t strnlen_P(uint_farptr_t s, size_t len) { return strnlen((char*)s, len); } + +// These are normally defined by stdio.h on AVR, but we cannot override that +// include file (at least not without no longer being able to include the +// original as well), so just define these here. It seems likely that any +// sketch that uses these progmem-stdio functions will also include pgmspace.h +inline int vfprintf_P(FILE *stream, const char *__fmt, va_list __ap) { return vfprintf(stream, __fmt, __ap); } +inline int printf_P(const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vprintf(__fmt, args); va_end(args); } +inline int sprintf_P(char *s, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return sprintf(s, __fmt, args); va_end(args); } +inline int snprintf_P(char *s, size_t __n, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vsnprintf(s, __n, __fmt, args); va_end(args); } +inline int vsprintf_P(char *s, const char *__fmt, va_list ap) { return vsprintf(s, __fmt, ap); } +inline int vsnprintf_P(char *s, size_t __n, const char *__fmt, va_list ap) { return vsnprintf(s, __n, __fmt, ap); } +inline int fprintf_P(FILE *stream, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vfprintf(stream, __fmt, args); va_end(args); } +inline int fputs_P(const char *str, FILE *__stream) { return fputs(str, __stream); } +inline int puts_P(const char *str) { return puts(str); } +inline int vfscanf_P(FILE *stream, const char *__fmt, va_list __ap) { return vfscanf(stream, __fmt, __ap); } +inline int fscanf_P(FILE *stream, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vfscanf(stream, __fmt, args); va_end(args); } +inline int scanf_P(const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vscanf(__fmt, args); va_end(args); } +inline int sscanf_P(const char *buf, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vsscanf(buf, __fmt, args); va_end(args); } diff --git a/exe/arduino_ci_remote.rb b/exe/arduino_ci_remote.rb index 12ab224e..5241eb72 100755 --- a/exe/arduino_ci_remote.rb +++ b/exe/arduino_ci_remote.rb @@ -227,7 +227,7 @@ def perform_unit_tests(file_config) config.allowable_unittest_files(cpp_library.test_files).each do |unittest_path| unittest_name = unittest_path.basename.to_s compilers.each do |gcc_binary| - attempt_multiline("Unit testing #{unittest_name} with #{gcc_binary}") do + attempt_multiline("Unit testing #{unittest_name} with #{gcc_binary} for #{p}") do exe = cpp_library.build_for_test_with_configuration( unittest_path, config.aux_libraries_for_unittest, diff --git a/misc/default.yml b/misc/default.yml index 67d7f87f..1bef2e27 100644 --- a/misc/default.yml +++ b/misc/default.yml @@ -22,7 +22,10 @@ platforms: gcc: features: defines: + - __AVR__ - __AVR_ATmega328P__ + - ARDUINO_ARCH_AVR + - ARDUINO_AVR_UNO warnings: flags: due: @@ -31,7 +34,10 @@ platforms: gcc: features: defines: - - __AVR_ATmega328__ + - __SAM3X8E__ + - ARDUINO_ARCH_SAM + - ARDUINO_SAM_DUE + - NUM_SERIAL_PORTS=4 warnings: flags: zero: @@ -40,8 +46,11 @@ platforms: gcc: features: defines: - - __SAMD21G18A__ - - ARDUINO_SAMD_ZERO + - __SAMD21G18A__ + - ARDUINO_ARCH_SAMD + - ARDUINO_SAMD_ZERO + # This also has SerialUSB, which is not included here. + - NUM_SERIAL_PORTS=2 warnings: flags: esp32: @@ -50,6 +59,10 @@ platforms: gcc: features: defines: + - ESP32 + - ARDUINO_ARCH_ESP32 + - ARDUINO_FEATHER_ESP32 + - NUM_SERIAL_PORTS=3 warnings: flags: esp8266: @@ -58,6 +71,10 @@ platforms: gcc: features: defines: + - ESP8266 + - ARDUINO_ARCH_ESP8266 + - ARDUINO_ESP8266_ESP12 + - NUM_SERIAL_PORTS=2 warnings: flags: leonardo: @@ -66,7 +83,10 @@ platforms: gcc: features: defines: + - __AVR__ - __AVR_ATmega32U4__ + - ARDUINO_ARCH_AVR + - ARDUINO_AVR_LEONARDO warnings: flags: trinket: @@ -75,6 +95,10 @@ platforms: gcc: features: defines: + - __AVR__ + - __AVR_ATtiny85__ + - ARDUINO_ARCH_AVR + - ARDUINO_AVR_TRINKET5 warnings: flags: gemma: @@ -83,6 +107,10 @@ platforms: gcc: features: defines: + - __AVR__ + - __AVR_ATtiny85__ + - ARDUINO_ARCH_AVR + - ARDUINO_AVR_GEMMA warnings: flags: m4: @@ -91,6 +119,12 @@ platforms: gcc: features: defines: + - __SAMD51__ + - __SAMD51J19A__ + - ARDUINO_ARCH_SAMD + - ARDUINO_METRO_M4 + # Serial is actually USB virtual serial, not HardwareSerial + - NUM_SERIAL_PORTS=2 warnings: flags: mega2560: @@ -99,7 +133,10 @@ platforms: gcc: features: defines: + - __AVR__ - __AVR_ATmega2560__ + - ARDUINO_ARCH_AVR + - ARDUINO_AVR_MEGA2560 warnings: flags: cplayClassic: @@ -108,6 +145,10 @@ platforms: gcc: features: defines: + - __AVR__ + - __AVR_ATmega32U4__ + - ARDUINO_ARCH_AVR + - ARDUINO_AVR_CIRCUITPLAY warnings: flags: cplayExpress: @@ -116,6 +157,11 @@ platforms: gcc: features: defines: + - __SAMD21G18A__ + - ARDUINO_ARCH_SAMD + - ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS + # Serial is actually an alias of SerialUSB, not a HardwareSerial + - NUM_SERIAL_PORTS=2 warnings: flags: