Routing MCLK to P2[31] on MODM7AE70

Discussion to talk about hardware related topics only.
Post Reply
depwl9992
Posts: 3
Joined: Fri Jun 14, 2024 2:55 pm

Routing MCLK to P2[31] on MODM7AE70

Post by depwl9992 »

Right now I'm attempting to upgrade a MOD5282 design into the MODM7AE70, and specifically dealing with the EBI module to access static memory. Our hardware right now would prefer to have the MCLK signal used by the Static Memory Controller to generate the needed baudrate on our motherboard and save us time avoiding Manchester decoding within the low-level VHDL.

Right now, it looks like Pin 31 of P1 can be configured as "Programmable Clock Channel 0 Output (PCK0)". However anything past this, such as setting its write-enable or accessing its functionality in any high-level documentation or example programs, is unavailable as far as I can tell. I would LIKE to access the programmable clock module or the power management controller (PMC) referenced in Chapter 31 of the SAM E70/S70/V70/V71 datasheet, so that I can assign the master clock (PMC_MCKR, chapter 31.20.11) to this pin (PA6 Peripheral B).

Currently, though, I've tracked down a macro:

Code: Select all

#define PIO_PA6B_PCK0
And found reference to the file:

Code: Select all

arch\cortex-m7\cpu\same70\include\component\pmc.h
But past this, I have no idea what to do with these, nor am I sure I COULD do anything with them to configure that peripheral clock output aside from simply assigning the P1[31] functionality as-is using the PinIO. There's no indication as to the default state of the peripheral clock once that's set up.

Does anyone have any insight on this? Is this even possible? The MODM7AE70 doesn't seem to have documentation or good examples on using the sim library like Coldfire had, so direct access to these low level CPU registers has been mildly frustrating. Besides that, I remember digging into the ARM Cortex system library a few years ago when the RTC module and periodic interrupts were not yet implemented, and it was a huge pita, and something which I eventually gave up on.

Thanks!
Last edited by depwl9992 on Mon Jun 17, 2024 10:41 am, edited 3 times in total.
User avatar
TomNB
Posts: 555
Joined: Tue May 10, 2016 8:22 am

Re: Routing MCLK to P2[31] on MODM7AE70

Post by TomNB »

Hello,

Just doing a quick search I found the following table in the same section you referenced. So you can set the programmable clock to MCK. Also, each can be set independently (sorry about the formatting).

So I think this answers the "could" question.


31.12 Programmable Clock Output Controller

The PMC controls three signals to be output on the external pins PCKx. Each signal can be independently
programmed via the Programmable Clock registers (PMC_PCKx).

PCKx can be independently selected between SLCK, MAINCK, PLLACK, UPLLCKDIV and MCK by configuring
PMC_PCKx.CSS. Each output signal can also be divided by 1 to 256 by configuring PMC_PCKx.PRES.
Each output signal can be enabled and disabled by writing a ‘1’ to the corresponding bits PMC_SCER.PCKx and
PMC_SCDR.PCKx, respectively. The status of the active programmable output clocks is given in PMC_SCSR.PCKx.
The status flag PMC_SR.PCKRDYx indicates that PCKx is actually what has been programmed in registers
PMC_PCKx.

As the Programmable Clock Controller does not manage with glitch prevention when switching clocks, it is strongly
recommended to disable PCKx before any configuration change and to re-enable it after the change is performed.


Looking at pinconstans.h, P2.31 can be set to (https://www.netburner.com/NBDocs/Develo ... ource.html):

// Connector: P1 / Pin: 31 / CPU Port: PA6
#define PINP1_31_IN (PinIO::PIN_FN_IN) // GPIO Input
#define PINP1_31_OUT (PinIO::PIN_FN_OUT) // GPIO Output
#define PINP1_31_PCK0 (PinIO::PIN_FN_B) // Peripheral B: Programmable Clock 0 Output
#define PINP1_31_UTXD1 (PinIO::PIN_FN_C) // Peripheral C: UART 1 Transmit
#define PINP1_31_SER_TX3 (PinIO::PIN_FN_C) // Peripheral C: Serial Port 3 Transmit


So if you enable it to be the programmable clock output it will output whatever you set PCKx to.

*** I would first read the status register to ensure it was not being used, which it should not be. Screen shot attached as well.

Is the issue that you are having a problem reading/writing registers? There are so many peripherals and registers on this part; we do our best to cover the most common ones first.
Attachments
Screenshot 2024-06-14 165650.png
Screenshot 2024-06-14 165650.png (120.65 KiB) Viewed 1443 times
Screenshot 2024-06-14 164001.png
Screenshot 2024-06-14 164001.png (125.45 KiB) Viewed 1443 times
depwl9992
Posts: 3
Joined: Fri Jun 14, 2024 2:55 pm

Re: Routing MCLK to P2[31] on MODM7AE70

Post by depwl9992 »

Thanks for looking into this and finding that register. That should be exactly what I need, yes.
Is the issue that you are having a problem reading/writing registers? There are so many peripherals and registers on this part; we do our best to cover the most common ones first.
I believe that yes, it is the issue of reading and writing CPU registers without the necessity of recompiling the system library. On the old ColdFire platforms, sim.h had a pretty comprehensive list of straightforward structures and arrays that would let us hook into everything not reframed by Netburner's runtime library, but I am unsure what the proper equivalent is for the Cortex. I've dug through the core codebase a little bit, and found a lot that I can extract out (such as the PIO_PA6B_PCK0 definition in arch/cortex-m7/cpu/SAME70/include/pio/same70q21.h, peripheral handlers and that sort of thing), but when it comes to actually using them to send register values into the CPU, I'm not sure.

Thanks!
User avatar
TomNB
Posts: 555
Joined: Tue May 10, 2016 8:22 am

Re: Routing MCLK to P2[31] on MODM7AE70

Post by TomNB »

The ColdFire registers were organized in a way that we could write the sim structure ourselves, but for ARM, its so massive that we are using the sim structure from the manufacturer. If we re-wrote those, then things would change as they tend to do, and our port would be too difficult to maintain.

I am attaching the start of an example that does not do much at all at this point, but does show how to write the registers in case you want to work on it in parallel. Still need to add things like prescaler, source selection, etc., and a lot of documentation. One of the key points is that a Programmable Clock sim structure named Pmc is declared, then assigned to a base address in the register map named PMC. The registers are then accessed with
PMC-> pointer. The macros and structure names are in "\nburn\arch\cortex-m7\cpu\SAME70\include\component\pmc.h".
Attachments
main.cpp
(6.4 KiB) Downloaded 50 times
depwl9992
Posts: 3
Joined: Fri Jun 14, 2024 2:55 pm

Re: Routing MCLK to P2[31] on MODM7AE70

Post by depwl9992 »

This is super helpful. Yeah, I finally ran across pmc.h on my own, and looking through the EBI core code (to find the syntax to access those register mappings) and the example you provided just now, I think I've come up with something that might work.

Code: Select all

#include <sim.h>
#include <same70.h>
#include <pins.h>
#include <ebi.h>

/* ColdFire chip select base addresses
#define CS1_BASEADDRESS (0xA0000000)
#define CS2_BASEADDRESS (0xB0000000)
#define CS3_BASEADDRESS (0xC0000000)
volatile unsigned short * FPGA_BASE_1;
volatile unsigned short * FPGA_BASE_2;
volatile unsigned short * FPGA_BASE_3;
*/

EBI_CS_cfg_t cs_all_cfg {
	25, // NCS Setup Length in clock cycles
	15, // NRD Setup Length in clock cycles
	25, // NCS Write Setup Length in clock cycles
	15, // NWE Setup Length in clock cycles
	30, // NCS Pulse Length in clock cycles
	65, // NRD Pulse Length in clock cycles
	30, // NCS Write Pulse Length in clock cycles
	65, // NWE Pulse Length in clock cycles
	90, // NRD Cycle Length
	90, // NWE Cycle Length
	0,  // TDF Cycle Count (clock cycles to release data reqd. by ext. device; can be 0-15)
	EBI_BUS_WIDTH_16,
	EBI_BYTE_ACCESS_SELECT,
	EBI_NWAIT_DISABLED,
	EBI_WRITE_MODE_NCS,
	EBI_READ_MODE_NCS
};

extern volatile uint8_t ebi_2_base[];  // Chip select 2
extern volatile uint8_t ebi_0_base[];  // Chip select 0
extern volatile uint8_t ebi_3_base[];  // Chip select 3

void InitChipBoardSelect() {
	/* ColdFire enable/configure chip selects.
	sim.cs[1].csar = (CS1_BASEADDRESS >> 16);
	sim.cs[1].cscr = 0x2180;                     // 0010 0001 1000  0000
	sim.cs[1].csmr = 0x03FF0001;

	sim.cs[2].csar = (CS2_BASEADDRESS >> 16);
	sim.cs[2].cscr = 0x2180;                     // 0010 0001 1000  0000
	sim.cs[2].csmr = 0x03FF0001;

	sim.cs[3].csar = (CS3_BASEADDRESS >> 16);
	sim.cs[3].cscr = 0x2180;                     // 0010 0001 1000  0000
	sim.cs[3].csmr = 0x03FF0001;
	
	FPGA_BASE_1 = (unsigned short *) CS1_BASEADDRESS;
   	FPGA_BASE_2 = (unsigned short *) CS2_BASEADDRESS;
	FPGA_BASE_3 = (unsigned short *) CS3_BASEADDRESS;
	*/

	// Note: EBI #CS1 is not available to the user - reserved for chip select of the MODM7AE70 SDRAM (U2)
	P1[5].function(PINP1_5_NCS2); // FPGA #CS1
	P1[6].function(PINP1_6_NCS0); // FPGA #CS2
	P1[7].function(PINP1_7_NCS3); // FPGA #CS3
	P1[8].function(PINP1_8_NRD);

	ConfigureEBI_CS(2,cs_all_cfg); // FPGA #CS1
	ConfigureEBI_CS(0,cs_all_cfg); // FPGA #CS2
	ConfigureEBI_CS(3,cs_all_cfg); // FPGA #CS3

	EnableExtBusBuff(true); // Enable the on-module bus buffers

	/**** Route Master Clock to Programmable Clock 0 (P1[31])
	  Control peripheral clock 0 via Power Management Controller structure.
	  PMC->PMC_SCSR = System Clock Status Register (31.20.3)
	  PMC->PMC_PCER0 = Peripheral Clock Enable Register 0
	  PMC->PMC_PCDR0 = Peripheral Clock Disable Register 0
	  PMC->PMC_PCSR0 = Peripheral Clock Status Register 0
	  PMC->PMC_PCK[7] = Programmable Clock 0 Register (31.20.13)
	 ****/
	P1[31].function(PINP1_31_PCK0); // Configure P1[31] with the Peripheral B: Programmable Clock 0 Output
	
	PMC->PMC_WPMR = PMC_WPMR_WPKEY(PMC_WPMR_WPKEY_PASSWD) | 0; // Disable PMC write protect for all clock config operations.
	PMC->PMC_SCDR |= PMC_SCDR_PCK0; // Disable Programmable Clock 0
	PMC->PMC_PCK[0] = PMC_PCK_PRES(0) | PMC_PCK_CSS(PMC_PCK_CSS_MCK); // Set PMC_PCK[0] to master clock with prescalar 0.
	PMC->PMC_SCER |= PMC_SCER_PCK0; // Enable Programmable Clock 0
}
It includes my previous code as well, for reference.

Thank you Tom. I think at the very least you've gotten me unstuck!
User avatar
TomNB
Posts: 555
Joined: Tue May 10, 2016 8:22 am

Re: Routing MCLK to P2[31] on MODM7AE70

Post by TomNB »

This should help more. Covers the different inputs. The readme.txt is pretty helpful.
Attachments
main.cpp
(5.52 KiB) Downloaded 45 times
ReadMe.txt
(2.51 KiB) Downloaded 47 times
Post Reply