Teensy 2.0 has stopped compiling the Adafruit GFX library

I'm using a teensy 2.0 as a MIDI controller which uses an OLED screen. I program it via the Arduino IDE, using the libraries Adafruit_GFX.h and Adafruit_SSD1306.h to display characters on the OLED. Has worked fine until now. I haven't made any changes (IDE, drivers etc) since my last successful compile and upload a week or so ago.

I just did some minor updates to the code but it now refuses to compile, throwing this error:

cc1.exe: fatal error: C:\Users\clive\OneDrive\Pictures\Documents\Arduino\libraries\arduino_110187\glcdfont.c: Permission denied
compilation terminated.

I tracked this back to the OLED libraries. So I tried compiling an example sketch supplied by Adafruit, SSD1306_128x64_i2c which threw the same error. However, when I compiled this for an Arduino Nano it built fine, no errors. I'm at a complete loss, all advice would be very welcome, thanks!

Here's the code for the example sketch in case it helps:

Code:
/**************************************************************************
 This is an example for our Monochrome OLEDs based on SSD1306 drivers

 Pick one up today in the adafruit shop!
 ------> http://www.adafruit.com/category/63_98

 This example is for a 128x64 pixel display using I2C to communicate
 3 pins are required to interface (two I2C and one reset).

 Adafruit invests time and resources providing this open
 source code, please support Adafruit and open-source
 hardware by purchasing products from Adafruit!

 Written by Limor Fried/Ladyada for Adafruit Industries,
 with contributions from the open source community.
 BSD license, check license.txt for more information
 All text above, and the splash screen below must be
 included in any redistribution.
 **************************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
  0b00000001, 0b11000000,
  0b00000001, 0b11000000,
  0b00000011, 0b11100000,
  0b11110011, 0b11100000,
  0b11111110, 0b11111000,
  0b01111110, 0b11111111,
  0b00110011, 0b10011111,
  0b00011111, 0b11111100,
  0b00001101, 0b01110000,
  0b00011011, 0b10100000,
  0b00111111, 0b11100000,
  0b00111111, 0b11110000,
  0b01111100, 0b11110000,
  0b01110000, 0b01110000,
  0b00000000, 0b00110000 };

void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();      // Draw many lines

  testdrawrect();      // Draw rectangles (outlines)

  testfillrect();      // Draw rectangles (filled)

  testdrawcircle();    // Draw circles (outlines)

  testfillcircle();    // Draw circles (filled)

  testdrawroundrect(); // Draw rounded rectangles (outlines)

  testfillroundrect(); // Draw rounded rectangles (filled)

  testdrawtriangle();  // Draw triangles (outlines)

  testfilltriangle();  // Draw triangles (filled)

  testdrawchar();      // Draw characters of the default font

  testdrawstyles();    // Draw 'stylized' characters

  testscrolltext();    // Draw scrolling text

  testdrawbitmap();    // Draw a small bitmap image

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000); // Pause for 2 seconds
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=3) {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn circle
    delay(1);
  }

  delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  display.println(3.141592);

  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

  display.display();
  delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for(f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS]   = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for(;;) { // Loop forever...
    display.clearDisplay(); // Clear the display buffer

    // Draw each snowflake:
    for(f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
    }

    display.display(); // Show the display buffer on the screen
    delay(200);        // Pause for 1/10 second

    // Then update coordinates of each flake...
    for(f=0; f< NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height()) {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS]   = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}
 
There have been a number of posts lately where anti-virus software was getting in the way. Can you turn off your AV and try again?
 
I'm using a teensy 2.0 as a MIDI controller which uses an OLED screen. I program it via the Arduino IDE, using the libraries Adafruit_GFX.h and Adafruit_SSD1306.h to display characters on the OLED. Has worked fine until now. I haven't made any changes (IDE, drivers etc) since my last successful compile and upload a week or so ago.

I just did some minor updates to the code but it now refuses to compile, throwing this error:

cc1.exe: fatal error: C:\Users\clive\OneDrive\Pictures\Documents\Arduino\libraries\arduino_110187\glcdfont.c: Permission denied
compilation terminated.

Note: the path almost looked like it had a space after the word Arduino... although quote of it does not show it...

But wondering if maybe there is an issue with your Arduino preferences. And check the string where your sketchbook is located.

Or maybe the Path name length has issues.

Or as Paul mentioned, maybe there is some limitation with your onedrive setup... I have not really used One drive much in a long time. Although I do keep it around, such that it can mirror the data up to cloud...
 
There have been a number of posts lately where anti-virus software was getting in the way. Can you turn off your AV and try again?

Thanks for the suggestion, I did try this when I was trying to troubleshoot the problem, but sadly it didn't help (I use Avast AV). I guess I really struggle with the fact that it will compile fine for a Nano but not a Teensy, and that it's worked fine for a Teensy in the past, using the same setup.
 
Maybe try with the files actually on your computer rather than OneDrive?

Thanks Paul, I think that's just the way that Windows sets up it's default installation (maybe?) - I don't use OneDrive, all those files and folders are physically located on the hard drive. I think maybe Windows mirrors everything in OneDrive folders if you have it set up.
 
Note: the path almost looked like it had a space after the word Arduino... although quote of it does not show it...

But wondering if maybe there is an issue with your Arduino preferences. And check the string where your sketchbook is located.

Or maybe the Path name length has issues.

Or as Paul mentioned, maybe there is some limitation with your onedrive setup... I have not really used One drive much in a long time. Although I do keep it around, such that it can mirror the data up to cloud...

I think the space after Arduino must be a formatting error, there isn't one in the actual folder name or path itself.

Bearing in mind the suggestions about path names, preferences etc I moved all the libraries, my sketches and examples to a single folder: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino. I also changed the sketchbook path in the IDE preferences to be the same folder. I restarted the IDE and tried compiling the sketch, which gave this error:

cc1.exe: fatal error: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\Wire\utility\twi.c: Permission denied
compilation terminated.
Multiple libraries were found for "SPI.h"
Used: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\SPI
Not used: C:\Program Files\Arduino\hardware\teensy\avr\libraries\SPI
Multiple libraries were found for "Wire.h"
Used: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\Wire
Not used: C:\Program Files\Arduino\hardware\teensy\avr\libraries\Wire

So on the basis that I should really be using the Teensy libraries, I moved the SPI and Wire libraries out of the C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\ folder. This got rid of the 'cc1.exe: fatal error: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\Wire\utility\twi.c: Permission denied' error and the 'multiple libraries' messages but sadly got me back to square one, ie I got the 'cc1.exe: fatal error: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\arduino_110187\glcdfont.c: Permission denied compilation terminated.' error.

Once again, compiling for the Nano worked fine!
 
Can you open that glcdfont.c file with a text editor like Notepad, or does it also get permission denied?

That was actually my first thought when I first got this error - the libraries all had permissions set to read only (as I'd expect), I changed them all to read/write to make sure. I can open, edit and save the glcdfont.c file with Notepad no problem.
 
Oh, this is not good. Libraries in your Arduino\libraries folder are overriding the libraries of the same name which are meant to be used for Teensy.

cc1.exe: fatal error: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\Wire\utility\twi.c: Permission denied
compilation terminated.
Multiple libraries were found for "SPI.h"
Used: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\SPI
Not used: C:\Program Files\Arduino\hardware\teensy\avr\libraries\SPI
Multiple libraries were found for "Wire.h"
Used: C:\Users\clive\OneDrive\Desktop\Core Data\Arduino\libraries\Wire
Not used: C:\Program Files\Arduino\hardware\teensy\avr\libraries\Wire

This is a pretty common problem, which is the reason Arduino prints those messages about multiple libraries found. If you have libraries for one type of board (eg, Arduino Nano) which override all others, you can expect that particular board to work and all others to have trouble.

Still, it's strange to see this manifest as a permission denied error on a particular file. There might be other problems here. But this library override issue needs to be fixed if you want your Arduino installation to be able to work with more than 1 type of board.
 
Thanks Paul, I was hoping that this might be a one-off due to my moving the libraries around, and could be resolved by removing the 'overriding' ones - but maybe not?

Like you, I'm suspicious of the 'permission denied' error. I wonder if it's something else altogether, which is confusing the compiler.

I've been trying to avoid it for obvious reasons, but is all of this pointing me towards having to reinstall the Arduino IDE, possibly an older version (I'm currently on 1.8.19)?
 
You could install a copy of Arduino 1.8.19 in portable mode.

https://docs.arduino.cc/software/ide-v1/tutorials/PortableIDE

If you create the portable folder before running the Teensyduino installer, the installer will recognize it and perform an install appropriate for portable mode. Then you can have a completely self-contained copy that works for Teensy, regardless of what you do with other stuff on your PC.

The main problem with have 2 or more copies of Arduino (regular or portable) is uncertainty when you click an a INO file in Windows explore or other programs. Windows will have to pick which one to run. Many times people have been confused because Windows ran a different copy than intended. But if you're careful to run the one you want and then open files from within it, multiple copies of the IDE for different boards can be an easy way to know it will work long-term.


I'm also curious, and I know this is probably an overly obvious question, but you've tried rebooting your PC regarding that permission problem, right?
 
That's a great idea, thanks. I'll let you know how it goes in case it helps anyone else.

I did a fair amount of troubleshooting before I bothered you good people with my problem, and in the course of this there were multiple reboots, none of which resolved the issue sadly.
 
That's a great idea, thanks. I'll let you know how it goes in case it helps anyone else.

Quick update: THIS WORKED!!! Thank you so much.

Longer update: installing a portable version of the Arduino IDE was fairly straightforward as was the Teensyduino install. I turned off both Avast antivirus and Windows Defender for the installations and the first couple of compiles. When I turned the AV back on it initially blocked a couple of the Teensy activities but allowed me to add exceptions for them and has been fine since then. I had a look at the instructions here to prevent Windows Defender slowing down the IDE, but they don't seem too relevant to Windows 10. I did find a way to allow specific programs through the firewall so I added the portable IDE to the list and it seems to be OK. I can post the steps I took if it'd help.

One of my first compiles threw a fatal error of this type: internal error in mingw32_gt_pch_use_address

A bit of Googling indicated that this seems to be an intermittent error which can usually be cleared by emptying the temporary build files. I did this and the next compile was fine, I suspect that simply closing and restarting the IDE would have the same effect.

So right now I'm back to being able to compile code for the Teensy which is great, thanks again.

Of course my updated MIDI controller code has now got some new bugs but no surprises there!
 
Back
Top