Go Down

Topic: how to clock the Due cpu clock at 80 or 96 MHz? (Read 589 times) previous topic - next topic

tito-t

Sep 02, 2017, 10:55 am Last Edit: Sep 02, 2017, 09:57 pm by tito-t
how to clock the Due cpu clock from std 84 MHz to 80 (edit:) or 96 MHz ?
The settings should work with my 1.6.x, 1.8.1, and following IDE updates.

The reason for this is to establish a save UART (Serial) clock at 500kbaud.

ard_newbie


AFAICT your choice of 80 MHz for a 500kbaud rate should not work since (baudrate - 6)/6 should be an integer.

You can reach this baud rate, and even 1 Mbps (according to datasheet) with a 96 MHz clock.

See this code for a 500Kbaudrate without a PDC DMA :

Code: [Select]

void setup() {

#define SYS_BOARD_OSCOUNT   (CKGR_MOR_MOSCXTST(0x8UL))

  // Baudrate = 6 * MULA + 6  ---> MULA = 15 for 96 MHz or 13 for 84 MHz
#define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE \
                             | CKGR_PLLAR_MULA(15ul) \
                             | CKGR_PLLAR_PLLACOUNT(0x3ful) \
                             | CKGR_PLLAR_DIVA(0x1UL))
#define SYS_BOARD_MCKR      ( PMC_MCKR_PRES_CLK_2|PMC_MCKR_CSS_PLLA_CLK)

  /* Set FWS according to SYS_BOARD_MCKR configuration */
  EFC0->EEFC_FMR = EEFC_FMR_FWS(3); // 3 + 1 waitstate flash access for each Flash bank
  EFC1->EEFC_FMR = EEFC_FMR_FWS(3);

  /* Initialize PLLA to 96 MHz */
  PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
  while (!(PMC->PMC_SR & PMC_SR_LOCKA));

  PMC->PMC_MCKR = SYS_BOARD_MCKR;
  while (!(PMC->PMC_SR & PMC_SR_MCKRDY));


  // UART configuration
  // Enable the peripheral uart controller
  PMC->PMC_PCER0 = 1 << ID_UART;

  // Reset and disable receiver & transmitter
  UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;

  // Set the baudrate to 500000
  UART->UART_BRGR = 12; // 96000000 / 16 * BRGR = BaudRate
  // No Parity
  UART->UART_MR = UART_MR_PAR_NO;

  // Disable PDC channel requests
  UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;

  // Disable / Enable interrupts on end of receive
  UART->UART_IDR = 0xFFFFFFFF;
  NVIC_EnableIRQ((IRQn_Type) ID_UART);
  UART->UART_IER = UART_IER_RXRDY;

  // Enable receiver and transmitter
  UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;

  SystemCoreClockUpdate(); // re-synchronize the USB with the new clock speed

}

void loop() {
printf("zsdrgf\n");
delay(1000);
}



tito-t

#2
Sep 02, 2017, 01:43 pm Last Edit: Sep 02, 2017, 10:05 pm by tito-t
Thank you very much!
Actually I falsely assumed that 500 (kbaud) had to be an int devider of cpu clock (80000/500=160), I never heard of your formula (baudrate - 6)/6 so far.
Finally  96 is supposed to work even better (faster) than 80 of course.

tito-t

#3
Sep 02, 2017, 08:28 pm Last Edit: Sep 03, 2017, 10:13 am by tito-t
PS,

As I don't see any Serial.begin() in your code, 2 points are still not clear to me though:

1) How to start Serial, Serial1, and Serial2 then?
Arbitrarily by, e.g.
Serial.begin(115200);
Serial1.begin(500000);
Serial2.begin(9600);
:?:

2) what means this zsdrgf thing in the line
printf("zsdrgf\n");
and to which output device writes printf? Do you mean Serial.print() instead?

tito-t

#4
Sep 05, 2017, 10:03 am Last Edit: Sep 05, 2017, 11:01 am by tito-t
could you/someone else please explain what the code is doing with all those cryptic and obfuscated constants and binary operands, and how they affect both an arbitrary Serial.begin() speed for either UART port  (115200, 500000, 9600, a.s.o.) to be set at the start and also how it affects the system timers (millis, micros, interrupt) ?

tito-t

can please explain someone how to get a changed 96MHz system clock working with either arbitrary Serial/Serial1/Serial2.begin(baudrate) from 9600, 19200, 115200, up to 500000 or even 1000000 ?

HermannSW


tito-t

#7
Sep 10, 2017, 02:42 pm Last Edit: Sep 10, 2017, 02:48 pm by tito-t
hi,
thanks for your reply.
1st I have to state that I have absolutely no idea about everything related to changing the clock speed, and tbh, I don't understand anything what your code is doing actually.

So IIUYC, you suggest to use this code:
Code: [Select]

void setup() {
#define SYS_BOARD_PLLAR (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(15UL) | CKGR_PLLAR_PLLACOUNT(0x3fUL) | CKGR_PLLAR_DIVA(1UL))
#define SYS_BOARD_MCKR ( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)
       
/* Set FWS according to SYS_BOARD_MCKR configuration */
EFC0->EEFC_FMR = EEFC_FMR_FWS(4); //4 waitstate flash access
EFC1->EEFC_FMR = EEFC_FMR_FWS(4);

/* Initialize PLLA to (15+1)*6=96MHz */
PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {}

PMC->PMC_MCKR = SYS_BOARD_MCKR;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {}
 
// your other setup code goes here
}


will then work Serial or Serial1 or Serial2.begin(baudrate) (e.g., 9600, 19200, 115200, 500000) with either baudrate stable, solid, and correctly,
and also each delay(ms),
and also each Wire.begin(i2c-clock)(100k, 400k),
out of the box, without any recalculations of either parameter ?

tito-t

is there an understandable reason why I don't get an answer to my questions?

westfw

Quote
Code: [Select]

  // Baudrate = 6 * MULA + 6  ---> MULA = 15 for 96 MHz or 13 for 84 MHz
#define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE \ ...


I never heard of your formula (baudrate - 6)/6 so far.
"Baud" in that comment is a typo - a mistake.  It should say "PLL Output Clock" or something like that.
Quote
is there an understandable reason why I don't get an answer to my questions?
What you are trying to do is more complicated than you seem to think, and it doesn't sound like you really have the background to get it working.  To get the uart working at 500kbps, you need to:
  • pick a clock rate that yields a workable BRG divisor.  (You've done that part.)
  • Figure out how to change the PLL configuration to get the new clock rate out of the PLL. (ard_newbie has done that.)
  • Adjust the rest of the Arduino core to know about the new clock rate.  Some things will use SystemCoreClock, which is updated by ard_newbie's code, but other parts use F_CPU.  Notably the sysTick timer that supplies the ticks for millis() and micros() and delay().   Also, the SystemInit() code is currently hard-wired to 84MHz (it SHOULD look at F_CPU!), so it would be desirable to change that rather than have the system come up at 84MHz and then use other code to change it to  80/96MHz.
  • SystemInit() also seems to be part of libsam, which seems to mean that it needs separate compilation, somehow.
  • Ensure that anything else that relies on clockrate still works.  (ard_newbie mentions USB.  Ugh.)

All in all, it's a bunch of messy modifications to not-very-clear code, requiring someone with a significant amount of experience to change.   If someone knew of a Due Core that already supported alternate clock rates, they probably would have mentioned it.  Since they didn't, you might be out of luck.

I think Zero and Teensy3 have fancier baud rate generators, and should support 500kbps "out of the box" with no change.

tito-t

@westfw:
thank you for your reply, that was eventually understandable. In fact I am quite a common Arduino user with perhaps average skills in C and Arduinish and don't understand low level functions.
So for my purpose of 500 kbaud UART plus further standard features for timers and clocks the Due must have to be dropped, and even the approaches mentioned above would not work in the end without issues as I read from your statements.
Zero and/or Teensy are no options though, as they have far too few GPIO pins and far too few serial and i2c pins.

HermannSW

#11
Sep 16, 2017, 12:07 pm Last Edit: Sep 16, 2017, 12:32 pm by HermannSW
... Zero and/or Teensy are no options though, as they have far too few GPIO pins and far too few serial and i2c pins.
I have quite some (12$) Dues, but many other microcontrollers as well.
Maybe this 9$ 160MHz 32bit Dual core Arduino (ESP32) with Wifi, Bluetooth and OLED has enough pins for your project?
https://forum.arduino.cc/index.php?topic=495555.0

https://diyprojects.io/esp32-card-choose-develop-diy-connected-objects/#ESP-WROOM-32_Technical_Specifications

Hermann.

(quality for a 170m indoor wifi connection to Raspberry Pi Zero W)

tito-t

#12
Sep 16, 2017, 02:38 pm Last Edit: Sep 16, 2017, 02:43 pm by tito-t
this ESP32 thing is really awesome!
Nonetheless I would need to have all over all ~50 Due's digital pins for 6-8 rotary encoder motors (5 pins each) plus extra ones for 1-wire and switches, and all that compatible to the PID_v1 lib, Due Scheduler, and Due Timer, or similar simple PID regulation, multithreading,  and timer libs.
With the Due libs I'm almost fine (admittedly the PID_v1 is jerking by running it in proprietary threads but that might be caused by poor tuning so far).

westfw


tito-t

#14
Sep 18, 2017, 08:15 pm Last Edit: Sep 19, 2017, 02:39 pm by tito-t
How about a TI Tiva Lauchpad:
http://www.ti.com/tool/ek-tm4c1294xl  Many pins, and ethernet.
http://www.ti.com/tool/ek-tm4c123gxl  Fewer pins; cheaper
http://www.ti.com/tool/msp-exp432p401r  Slower, lower-power, supports multi-tasking via TI-RTOSl

All are supported by http://Energia.nu]http://www.ti.com/tool/msp-exp432p401r[/ur]  Slower, lower-power, supports multi-tasking via TI-RTOSl

All are supported by [url=http://Energia.nu]http://Energia.nu
, which is an Arduino IDE clone.

no thanks, it has to be Arduino-IDE and API-compatible and fully supported by Arduino.cc, no extra RTOS, but just like the libs designed for the Due or perhaps for the Zero M0.

Go Up