8000 Merge pull request #6279 from mjs513/main · tannewt/circuitpython@4aea804 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4aea804

Browse files
authored
Merge pull request micropython#6279 from mjs513/main
Added Settable Clock for MIMXRT BOARDS
2 parents 1fcc73b + 2e9e29b commit 4aea804

File tree

11 files changed

+312
-4
lines changed

11 files changed

+312
-4
lines changed

locale/circuitpython.pot

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,11 @@ msgstr ""
11071107
msgid "Framebuffer requires %d bytes"
11081108
msgstr ""
11091109

1110+
#: ports/mimxrt10xx/common-hal/microcontroller/Processor.c
1111+
msgid ""
1112+
"Frequency must be 24, 150, 396, 450, 528, 600, 720, 816, 912, 960 or 1008 Mhz"
1113+
msgstr ""
1114+
11101115
#: shared-bindings/pwmio/PWMOut.c
11111116
msgid "Frequency must match existing PWMOut using this timer"
11121117
msgstr ""
@@ -3019,7 +3024,7 @@ msgstr ""
30193024
msgid "complex values not supported"
30203025
msgstr ""
30213026

3022-
#: extmod/moduzlib.c shared-module/zlib/DecompIO.c
3027+
#: extmod/moduzlib.c
30233028
msgid "compression header"
30243029
msgstr ""
30253030

@@ -3273,6 +3278,10 @@ msgstr ""
32733278
msgid "format requires a dict"
32743279
msgstr ""
32753280

3281+
#: shared-bindings/microcontroller/Processor.c
3282+
msgid "frequency is read-only for this board"
3283+
msgstr ""
3284+
32763285
#: py/objdeque.c
32773286
msgid "full"
32783287
msgstr ""

ports/mimxrt10xx/boards/sparkfun_teensy_micromod/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ CHIP_FAMILY = MIMXRT1062
88
FLASH = W25Q128JV
99
CIRCUITPY__EVE = 1
1010
CIRCUITPY_USB_HOST = 1
11+
CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1

ports/mimxrt10xx/boards/teensy40/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ CHIP_VARIANT = MIMXRT1062DVJ6A
77
CHIP_FAMILY = MIMXRT1062
88
FLASH = W25Q16JV
99
CIRCUITPY__EVE = 1
10+
CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1

ports/mimxrt10xx/boards/teensy41/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ CHIP_FAMILY = MIMXRT1062
88
FLASH = W25Q64JV
99
CIRCUITPY__EVE = 1
1010
CIRCUITPY_USB_HOST = 1
11+
CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1

ports/mimxrt10xx/common-hal/microcontroller/Processor.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include <math.h>
2929

30+
#include "py/runtime.h"
31+
3032
#include "common-hal/microcontroller/Processor.h"
3133
#include "shared-bindings/microcontroller/Processor.h"
3234
#include "shared-bindings/microcontroller/ResetReason.h"
@@ -50,6 +52,18 @@ float common_hal_mcu_processor_get_temperature(void) {
5052
return temp;
5153
}
5254

55+
uint32_t common_hal_mcu_processor_set_frequency(mcu_processor_obj_t *self,
56+
uint32_t frequency) {
57+
uint32_t freq = frequency / 1000000;
58+
if (freq != 24 && freq != 150 && freq != 396 && freq != 450 && freq != 528 && freq != 600 &&
59+
freq != 720 && freq != 816 && freq != 912 && freq != 960 && freq != 1008) {
60+
mp_raise_ValueError(translate("Frequency must be 24, 150, 396, 450, 528, 600, 720, 816, 912, 960 or 1008 Mhz"));
61+
}
62+
SystemCoreClock = setarmclock(frequency);
63+
return SystemCoreClock;
64+
}
65+
66+
5367
float common_hal_mcu_processor_get_voltage(void) {
5468
return NAN;
5569
}

ports/mimxrt10xx/common-hal/microcontroller/Processor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@
3131
#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 16
3232

3333
#include "py/obj.h"
34+
#include "clocks.h"
3435

3536
typedef struct {
3637
mp_obj_base_t base;
37-
// Stores no state currently.
38+
uint32_t frequency;
3839
} mcu_processor_obj_t;
3940

4041
#endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H

ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/clocks.c

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include "fsl_clock.h"
3636
#include "fsl_iomuxc.h"
37+
#include "fsl_device_registers.h"
3738

3839
#include "clocks.h"
3940

@@ -335,3 +336,257 @@ void clocks_init(void) {
335336

336337
CLOCK_EnableClock(kCLOCK_Iomuxc);
337338
}
339+
340+
/* clockspeed.c
341+
* http://www.pjrc.com/teensy/
342+
* Copyright (c) 2017 PJRC.COM, LLC
343+
*
344+
* Permission is hereby granted, free of charge, to any person obtaining a copy
345+
* of this software and associated documentation files (the "Software"), to deal
346+
* in the Software without restriction, including without limitation the rights
347+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
348+
* copies of the Software, and to permit persons to whom the Software is
349+
* furnished to do so, subject to the following conditions:
350+
*
351+
* The above copyright notice and this permission notice shall be included in
352+
* all copies or substantial portions of the Software.
353+
*
354+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
355+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
356+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
357+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
358+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
359+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
360+
* THE SOFTWARE.
361+
*/
362+
// Note setarmclock is a port from Teensyduino for the Teensy 4.x written by Paul Stroffgren,
363+
// A brief explanation of F_CPU_ACTUAL vs F_CPU
364+
// https://forum.pjrc.com/threads/57236?p=212642&viewfull=1#post212642
365+
volatile uint32_t F_CPU_ACTUAL = 396000000;
366+
volatile uint32_t F_BUS_ACTUAL = 132000000;
367+
368+
// Define these to increase the voltage when attempting overclocking
369+
7863 // The frequency step is how quickly to increase voltage per frequency
370+
// The datasheet says 1600 is the absolute maximum voltage. The hardware
371+
// can actually create up to 1575. But 1300 is the recommended limit.
372+
// (earlier versions of the datasheet said 1300 was the absolute max)
373+
#define OVERCLOCK_STEPSIZE 28000000
374+
#define OVERCLOCK_MAX_VOLT 1575
375+
376+
#define DCDC_REG3 0x40080012
377+
#define DCDC_REG0 0x40080000
378+
#define DCDC_REG0_STS_DC_OK_L ((uint32_t)(1 << 31))
379+
#define CCM_ANALOG_PLL_USB1_ENABLE_L ((uint32_t)(1 << 13))
380+
#define CCM_ANALOG_PLL_USB1_POWER_L ((uint32_t)(1 << 12))
381+
#define CCM_ANALOG_PLL_USB1_EN_USB_CLKS_L ((uint32_t)(1 << 6))
382+
#define CCM_ANALOG_PLL_USB1_LOCK_L ((uint32_t)(1 << 31))
383+
#define CCM_CCGR6_DCDC(n) ((uint32_t)(((n) & 0x03) << 6))
384+
#define CCM_ANALOG_PLL_ARM_LOCK_L ((uint32_t)(1 << 31))
385+
#define CCM_ANALOG_PLL_ARM_BYPASS_L ((uint32_t)(1 << 16))
386+
#define CCM_ANALOG_PLL_ARM_ENABLE_L ((uint32_t)(1 << 13))
387+
#define CCM_ANALOG_PLL_ARM_POWERDOWN_L ((uint32_t)(1 << 12))
388+
#define CCM_CDHIPR_ARM_PODF_BUSY_L ((uint32_t)(1 << 16))
389+
#define CCM_CDHIPR_AHB_PODF_BUSY_L ((uint32_t)(1 << 1))
390+
#define CCM_CDHIPR_PERIPH_CLK_SEL_BUSY_L ((uint32_t)(1 << 5))
391+
#define CCM_CBCDR_PERIPH_CLK_SEL_L ((uint32_t)(1 << 25))
392+
#define CCM_CCGR_OFF 0
393+
#define CCM_CCGR_ON_RUNONLY 1
394+
#define CCM_CCGR_ON 3
395+
396+
/* Teensyduino Core Library - clockspeed.c
397+
* http://www.pjrc.com/teensy/
398+
* Copyright (c) 2017 PJRC.COM, LLC.
399+
*
400+
* Permission is hereby granted, free of charge, to any person obtaining
401+
* a copy of this software and associated documentation files (the
402+
* "Software"), to deal in the Software without restriction, including
403+
* without limitation the rights to use, copy, modify, merge, publish,
404+
* distribute, sublicense, and/or sell copies of the Software, and to
405+
* permit persons to whom the Software is furnished to do so, subject to
406+
* the following conditions:
407+
*
408+
* 1. The above copyright notice and this permission notice shall be
409+
* included in all copies or substantial portions of the Software.
410+
*
411+
* 2. If the Software is incorporated into a build system that allows
412+
* selection among a list of target devices, then similar target
413+
* devices manufactured by PJRC.COM must be included in the list of
414+
* target devices and selectable in the same manner.
415+
*
416+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
417+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
418+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
419+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
420+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
421+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
422+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
423+
* SOFTWARE.
424+
*/
425+
426+
// uint32_t set_arm_clock(uint32_t frequency);
427+
428+
// stuff needing wait handshake:
429+
// CCM_CACRR ARM_PODF
430+
// CCM_CBCDR PERIPH_CLK_SEL
431+
// CCM_CBCMR PERIPH2_CLK_SEL
432+
// CCM_CBCDR AHB_PODF
433+
// CCM_CBCDR SEMC_PODF
434+
435+
uint32_t setarmclock(uint32_t frequency) {
436+
uint32_t cbcdr = CCM->CBCDR; // pg 1021
437+
uint32_t cbcmr = CCM->CBCMR; // pg 1023
438+
uint32_t dcdc = DCDC->REG3;
439+
440+
// compute required voltage
441+
uint32_t voltage = 1150; // default = 1.15V
442+
if (frequency > 528000000) {
443+
voltage = 1250; // 1.25V
444+
#if defined(OVERCLOCK_STEPSIZE) && defined(OVERCLOCK_MAX_VOLT)
445+
if (frequency > 600000000) {
446+
voltage += ((frequency - 600000000) / OVERCLOCK_STEPSIZE) * 25;
447+
if (voltage > OVERCLOCK_MAX_VOLT) {
448+
voltage = OVERCLOCK_MAX_VOLT;
449+
}
450+
}
451+
#endif
452+
} else if (frequency <= 24000000) {
453+
voltage = 950; // 0.95
454+
}
455+
456+
// if voltage needs to increase, do it before switch clock speed
457+
CCM->CCGR6 |= CCM_CCGR6_DCDC(CCM_CCGR_ON);
458+
if ((dcdc & ((uint32_t)(0x1F << 0))) < ((uint32_t)(((voltage - 800) / 25) & 0x1F) << 0)) {
459+
dcdc &= ~((uint32_t)(0x1F << 0));
460+
dcdc |= ((uint32_t)(((voltage - 800) / 25) & 0x1F) << 0);
461+
DCDC->REG3 = dcdc;
462+
while (!(DCDC->REG0 & DCDC_REG0_STS_DC_OK_L)) {
463+
; // wait voltage settling
464+
}
465+
}
466+
467+
if (!(cbcdr & CCM_CBCDR_PERIPH_CLK_SEL_L)) {
468+
const uint32_t need1s = CCM_ANALOG_PLL_USB1_ENABLE_L | CCM_ANALOG_PLL_USB1_POWER_L |
469+
CCM_ANALOG_PLL_USB1_LOCK_L | CCM_ANALOG_PLL_USB1_EN_USB_CLKS_L;
470+
uint32_t sel, div;
471+
if ((CCM_ANALOG->PLL_USB1 & need1s) == need1s) {
472+
sel = 0;
473+
div = 3; // divide down to 120 MHz, so IPG is ok even if IPG_PODF=0
474+
} else {
475+
sel = 1;
476+
div = 0;
477+
}
478+
if ((cbcdr & ((uint32_t)(0x07 << 27))) != CCM_CBCDR_PERIPH_CLK2_PODF(div)) {
479+
// PERIPH_CLK2 divider needs to be changed
480+
cbcdr &= ~((uint32_t)(0x07 << 27));
481+
cbcdr |= CCM_CBCDR_PERIPH_CLK2_PODF(div);
482+
CCM->CBCDR = cbcdr;
483+
}
484+
if ((cbcmr & ((uint32_t)(0x03 << 12))) != CCM_CBCMR_PERIPH_CLK2_SEL(sel)) {
485+
// PERIPH_CLK2 source select needs to be changed
486+
cbcmr &= ~((uint32_t)(0x03 << 12));
487+
cbcmr |= CCM_CBCMR_PERIPH_CLK2_SEL(sel);
488+
CCM->CBCMR = cbcmr;
489+
while (CCM->CDHIPR & ((uint32_t)(1 << 3))) {
490+
; // wait
491+
}
492+
}
493+
// switch over to PERIPH_CLK2
494+
cbcdr |= ((uint32_t)(1 << 25));
495+
CCM->CBCDR = cbcdr;
496+
while (CCM->CDHIPR & ((uint32_t)(1 << 5))) {
497+
; // wait
498+
}
499+
}
500+
501+
// TODO: check if PLL2 running, can 352, 396 or 528 can work? (no need for ARM PLL)
502+
503+
// DIV_SELECT: 54-108 = official range 648 to 1296 in 12 MHz steps
504+
uint32_t div_arm = 1;
505+
uint32_t div_ahb = 1;
506+
while (frequency * div_arm * div_ahb < 648000000) {
507+
if (div_arm < 8) {
508+
div_arm = div_arm + 1;
509+
} else {
510+
if (div_ahb < 5) {
511+
div_ahb = div_ahb + 1;
512+
div_arm = 1;
513+
} else {
514+
break;
515+
}
516+
}
517+
}
518+
uint32_t mult = (frequency * div_arm * div_ahb + 6000000) / 12000000;
519+
if (mult > 108) {
520+
mult = 108;
521+
}
522+
if (mult < 54) {
523+
mult = 54;
524+
}
525+
526+
frequency = mult * 12000000 / div_arm / div_ahb;
527+
528+
const uint32_t arm_pll_mask = CCM_ANALOG_PLL_ARM_LOCK_L | CCM_ANALOG_PLL_ARM_BYPASS_L |
529+
CCM_ANALOG_PLL_ARM_ENABLE_L | CCM_ANALOG_PLL_ARM_POWERDOWN_L |
530+
CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK;
531+
if ((CCM_ANALOG->PLL_ARM & arm_pll_mask) != (CCM_ANALOG_PLL_ARM_LOCK_L
532+
| CCM_ANALOG_PLL_ARM_ENABLE_L | CCM_ANALOG_PLL_ARM_DIV_SELECT(mult))) {
533+
// printf("ARM PLL needs reconfigure\n");
534+
CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_POWERDOWN_L;
535+
// TODO: delay needed?
536+
CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_ENABLE_L
537+
| CCM_ANALOG_PLL_ARM_DIV_SELECT(mult);
538+
while (!(CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_LOCK_L)) {
539+
; // wait for lock
540+
}
541+
}
542+
543+
if ((CCM->CACRR & ((uint32_t)(0x07 << 0))) != (div_arm - 1)) {
544+
CCM->CACRR = CCM_CACRR_ARM_PODF(div_arm - 1);
545+
while (CCM->CDHIPR & CCM_CDHIPR_ARM_PODF_BUSY_L) {
546+
; // wait
547+
}
548+
}
549+
550+
if ((cbcdr & ((uint32_t)(0x07 << 10))) != CCM_CBCDR_AHB_PODF(div_ahb - 1)) {
551+
cbcdr &= ~((uint32_t)(0x07 << 10));
552+
cbcdr |= CCM_CBCDR_AHB_PODF(div_ahb - 1);
553+
CCM->CBCDR = cbcdr;
554+
while (CCM->CDHIPR & CCM_CDHIPR_AHB_PODF_BUSY_L) {
555+
; // wait
556+
}
557+
}
558+
559+
uint32_t div_ipg = (frequency + 149999999) / 150000000;
560+
if (div_ipg > 4) {
561+
div_ipg = 4;
562+
}
563+
if ((cbcdr & ((uint32_t)(0x03 << 8))) != (CCM_CBCDR_IPG_PODF(div_ipg - 1))) {
564+
cbcdr &= ~((uint32_t)(0x03 << 8));
565+
cbcdr |= CCM_CBCDR_IPG_PODF(div_ipg - 1);
566+
// TODO: how to safely change IPG_PODF ??
567+
CCM->CBCDR = cbcdr;
568+
}
569+
570+
// cbcdr &= ~CCM_CBCDR_PERIPH_CLK_SEL;
571+
// CCM_CBCDR = cbcdr; // why does this not work at 24 MHz?
572+
CCM->CBCDR &= ~((uint32_t)(1 << 25));
573+
while (CCM->CDHIPR & CCM_CDHIPR_PERIPH_CLK_SEL_BUSY_L) {
574+
; // wait
575+
576+
}
577+
F_CPU_ACTUAL = frequency;
578+
F_BUS_ACTUAL = frequency / div_ipg;
579+
// scale_cpu_cycles_to_microseconds = 0xFFFFFFFFu / (uint32_t)(frequency / 1000000u);
580+
581+
// if voltage needs to decrease, do it after switch clock speed
582+
if ((dcdc & ((uint32_t)(0x1F << 0))) > ((uint32_t)(((voltage - 800) / 25) & 0x1F) << 0)) {
583+
dcdc &= ~((uint32_t)(0x1F << 0));
584+
dcdc |= ((uint32_t)(0x1F << 0));
585+
DCDC->REG3 = dcdc;
586+
while (!(DCDC->REG0 & DCDC_REG0_STS_DC_OK_L)) {
587+
; // wait voltage settling
588+
}
589+
}
590+
591+
return frequency;
592+
}

ports/mimxrt10xx/peripherals/mimxrt10xx/clocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@
2727
extern uint32_t SystemCoreClock;
2828

2929
void clocks_init(void);
30+
uint32_t setarmclock(uint32_t frequency);

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ CFLAGS += -DCIRCUITPY_SDIOIO=$(CIRCUITPY_SDIOIO)
346346
CIRCUITPY_SERIAL_BLE ?= 0
347347
CFLAGS += -DCIRCUITPY_SERIAL_BLE=$(CIRCUITPY_SERIAL_BLE)
348348

349+
CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY?= 0
350+
CFLAGS += -DCIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY=$(CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY)
351+
349352
CIRCUITPY_SHARPDISPLAY ?= $(CIRCUITPY_FRAMEBUFFERIO)
350353
CFLAGS += -DCIRCUITPY_SHARPDISPLAY=$(CIRCUITPY_SHARPDISPLAY)
351354

0 commit comments

Comments
 (0)
0