MCUdude / MightyCore

Arduino hardware package for ATmega1284, ATmega644, ATmega324, ATmega324PB, ATmega164, ATmega32, ATmega16 and ATmega8535
Other
649 stars 182 forks source link

ATmega1284p cannot change SPI speed #200

Closed zoonman closed 3 years ago

zoonman commented 3 years ago

Hello Hans,

I used your core with platformio. After flashing fuses it put my board into a state where it was using external clock source instead of onboard ceramic resonator which is pretty typical these days. I is pretty confusing. After some hardware hacking I was able to recover the board and flash fuses as E:FD, H:D6, L:8F. It got my 16 MHz clock back. But I discovered another issue - SPI bus sends 8MHz sync on SCK pin which is not what I expect. I think default is 4 MHz. I am using ST7735 display with Adafruit_ST7735 library and it works only at 1 MHz SPI. I tried setting divider (SPI.setClockDivider(SPI_CLOCK_DIV128) and tft.setSPISpeed(125000)) and defining DEFAULT_SPI_FREQ to change SPI bus SCK frequency and none of it had any effect. Displays shows whitescreen.

MCUdude commented 3 years ago

Hi Philipp!

After flashing fuses it put my board into a state where it was using external clock source instead of onboard ceramic resonator which is pretty typical these days. I is pretty confusing. After some hardware hacking I was able to recover the board and flash fuses as E:FD, H:D6, L:8F. It got my 16 MHz clock back.

Ah, this has happened to me many times. If you don't have a crystal, or the hardware you're working on doesn't allow you to add one, you can use a fast clock pulse (from a signal generator, or a pin from an Arduino) and connect this signal to the XTAL1 pin using a sharp probe or similar.

But I discovered another issue - SPI bus sends 8MHz sync on SCK pin which is not what I expect. I think default is 4 MHz.

This sounds weird. I just loaded the DigitalPotControl SPI example (because it's very bare-bone), and without modifications, it outputs a 4 MHz clock. By adding SPI.setClockDivider(SPI_CLOCK_DIV128), I got a 125 kHz clock signal instead. I tested this with Arduino IDE and with PlatformIO. Measured with an oscilloscope.

Can you also try this example? By stripping away unnecessary code it's easier to possibly figure out the issue.

The default SPI clock is 4 MHz for a 16 MHz system clock. As mentioned, this can be changed with the SPI.setClockDivider() function.

The TFT library may be messing with the SPI settings. I can at least confirm that the SPI library itself works like it should.

MCUdude commented 3 years ago

Also, are you sure you're not outputting any PWM signal (using timer3) on the SCK pin?

zoonman commented 3 years ago

Turns out the library is so poorly written that call to update default SPI frequency has to be made after initR() call like this:

tft.initR(INITR_BLACKTAB);
tft.setSPISpeed(100000); // counterintuitive, should be part of init or pre-init process

That stuff works. I am still wrestling with white screen but I am glad that SPI speed gets updated.

Thank you, Hans!

Maybe you can give me advice with another thing - I want do something like

digitalWrite(PD5, HIGH); // but it works only as  digitalWrite(13, HIGH);

Is there a call or something else I have to do to use symbolic pin names?

MCUdude commented 3 years ago

Turns out the library is so poorly written that call to update default SPI frequency has to be made after initR() call like this:

Ugh, That's not very elegant at all.

Maybe you can give me advice with another thing - I want do something like digitalWrite(PD5, HIGH); // but it works only as digitalWrite(13, HIGH);

I've actually thought of this, since various "Arduino pinouts" makes portability difficult. Use PIN_macros instead! They work on all my Arduino cores + ATTinyCore and megaTinyCore. In other words, you can use these macros on pretty much any AVR though Arduino IDE.

digitalWrite(PIN_PD5, HIGH); // same as digitalWrite(13, HIGH);

Pin macros are defined in in the pins_arduino.h file. If you use these macros it no longer matters if you use the standard pinout (still recommended though), bobuino, or sanguino pinout.

https://github.com/MCUdude/MightyCore/blob/0dc520f968642b8f7d0822262bd10a0746212be3/avr/variants/standard/pins_arduino.h#L137-L177

zoonman commented 3 years ago

I tried to make config.h and hardcoded bunch of defines with numbers. I like these PIN_xxx! It really improves portability and readability!

I don't use ArduinoIDE instead I use Clion with Platformio plugin. That combo is for the win, tbh. Also I was looking at Platformio code editor but it didn't stick to me. Sadly I am not VSCode fan. But it looks really promising.

Thank you very much, Hans! Happy holidays!

MCUdude commented 3 years ago

I don't use ArduinoIDE instead I use Clion with Platformio plugin. That combo is for the win, tbh. Also I was looking at Platformio code editor but it didn't stick to me. Sadly I am not VSCode fan. But it looks really promising.

I use Arduino for test sketches and small programmers. For bigger ones I definitely use PlatformIO, and I can live with VSCode. I have no experience with CLion. Does it have "IntelliSense" and "right-click -> go to implementation"?

I have a few 90kB+ projects with 10+ source files with several external libraries. It's fantastic to have one project where library dependencies, build flags, upload configuration and fuse settings are located. The amount of time and work I put into the PlatformIO project to get support for all my Arduino cores and dynamic fuse calculation was definitely worth it.

Thank you very much, Hans! Happy holidays!

Thank you, Philipp! I have two days left before I take a week off. Happy holidays to you too!

zoonman commented 3 years ago

Does it have "IntelliSense" and "right-click -> go to implementation"? Yes and I found it pretty amazing!

Screen Shot 2020-12-20 at 16 18 13