This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem initializing analog subsystem on F28M35x

On developing for the F28M35x chip I'm noticing strange behavior in trying to initialize the analog subsystem so I can use the ADC functionality. 

The odd part is that it works correctly when loading the exact same binaries via jtag and running from there, but on power reset with the programs loaded into flash, it is unable to successfully run the provided InitAnalogSystemClock function. Specifically the C28 is calling this from main: 

	int Analog1_Config, Analog2_Config;
	
	DINT;			// Global Disable all Interrupts
	IER = 0x0000;	// Disable CPU interrupts
	IFR = 0x0000;	// Clear all CPU interrupt flags

	PieCntlInit();		
	PieVectTableInit();

	EALLOW; // below registers are "protected", allow access.

	SysCtrlRegs.LOSPCP.all = 0x0002;		// Sysclk / 4

	(**ReadAnalogClockStatus)(AnalogConfig2);
	int successCode  = 0;
        while(successCode == 0) {
            *(unsigned int*)0x4E58 = 7;             //added for errata workaround dmh 11/25/2013
            successCode = (**InitAnalogSystemClock)(ACLKDIV2); //(ACLKDIV2);  //(ACLKDIV4);
        }

Note that I'm also doing the following in M3: 

    HWREG(SYSCTL_MWRALLOW) = 0xA5A5A5A5;

    // Sets up PLL, M3 running at 75MHz and C28 running at 150MHz
    SysCtlClockConfigSet(SYSCTL_USE_PLL | (SYSCTL_SPLLIMULT_M & 0xf) |
                         SYSCTL_SYSDIV_1 | SYSCTL_M3SSDIV_2 |
                         SYSCTL_XCLKDIV_4);

    SysCtlSubSystemReset(SYSCTL_ANALOG_SYSTEM_RES_CNF);

before later booting from flash. 

Digging more into it, InitAnalogSystemClock tries to edit memory at the reserved section directly after the IPC registers, and this memory seems immutable when ran from flash. When I then reload the image via jtag and run the M3, it can write to some of these locations. 

Additionally, I have commented out most of the initialization/setup code out of the gel file for the M3 in case one of those was making it work. Unfortunately this had no effect. 

Could I get information on what conditions could cause this issue? Is there any data source on what is in the reserved block and how it pertains to the analog subsystem? 

  • David,

    I'm honestly not sure why the write isn't working. When do you release the Control subsystem to execute? Do you still receive a return value from InitAnalogSystemClock?

    The reserved address is a general purpose register that is used by the analog ROM functions for temporary data storage.

    I do notice a couple of things that can be cleaned up:
    1) The C28x is configured for 150MHz clock, but the Analog System clock is set to DIV2, which would make the analog clock 75MHz. The maximum supported frequency is 37.5MHz so DIV4 should be used here.
    2) InitAnalogSystemClock() should be the first analog function executed, but ReadAnalogClockStatus() is executed first. I wouldn't expect this to be a problem, but just want to point it out.


    -Tommy
  • Hi Tommy,

    Thanks for the quick reply. 

    I release it after configuring some other peripherals; full listing below:

    void setup() {
    	//int i;
        // Allow writes to protected registers.
        HWREG(SYSCTL_MWRALLOW) = 0xA5A5A5A5;
    
        // Sets up PLL, M3 running at 75MHz and C28 running at 150MHz
        SysCtlClockConfigSet(SYSCTL_USE_PLL | (SYSCTL_SPLLIMULT_M & 0xf) |
                             SYSCTL_SYSDIV_1 | SYSCTL_M3SSDIV_2 |
                             SYSCTL_XCLKDIV_4);
    
        SysCtlSubSystemReset(SYSCTL_ANALOG_SYSTEM_RES_CNF);
    
        SysCtlPeripheralDisable(SYSCTL_PERIPH_WDOG1);
        SysCtlPeripheralDisable(SYSCTL_PERIPH_WDOG0);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
    
        RAMMReqSharedMemAccess((S0_ACCESS | S1_ACCESS | S2_ACCESS | S3_ACCESS | S4_ACCESS | S5_ACCESS | S6_ACCESS | S7_ACCESS), C28_MASTER);
    
        // Enable Pullups on EPWM(1-8)A/B capable pins
        GPIOPadConfigSet(GPIO_PORTA_BASE, 0xFF, GPIO_PIN_TYPE_STD_WPU);
        GPIOPadConfigSet(GPIO_PORTB_BASE, 0xFF, GPIO_PIN_TYPE_STD_WPU);
    
    
        GPIOPinConfigureCoreSelect(GPIO_PORTA_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTB_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTC_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTD_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTE_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTF_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTG_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTH_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
        GPIOPinConfigureCoreSelect(GPIO_PORTJ_BASE, 0xFF, GPIO_PIN_C_CORE_SELECT);
    
    
        // Assign UART pins to M3
        GPIOPinConfigureCoreSelect(GPIO_PORTG_BASE, 0x03, GPIO_PIN_M_CORE_SELECT);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
    
        // Unlock the register to change the commit register value for Port B Pin 7
        // This disables the NMI functionality on the pin and allows other muxing
        // options to be used
        HWREG(GPIO_PORTB_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;
        // Write to commit register
        HWREG(GPIO_PORTB_BASE+GPIO_O_CR) |= 0x000000FF;
        // Delay
        volatile int i;
        for (i=0;i<20;i++){};
    
        //Enable processor interrupts.
        IntMasterEnable();
    
    }
    
    void setupUart() {
       // Enable the UART peripherals
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    
    	// Set GPIO E4 and E5 as UART pins.
    	GPIOPinTypeUART(GPIO_PORTG_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    	GPIOPinConfigure(GPIO_PG0_U2RX);
    	GPIOPinConfigure(GPIO_PG1_U2TX);
    
    	// Configure the UART for 115,200, 8-N-1 operation.
    	UARTConfigSetExpClk(UART2_BASE, SysCtlClockGet(SYSTEM_CLOCK_SPEED), 115200,
    						(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    						 UART_CONFIG_PAR_NONE));
    
    	// Enable the UART interrupt.
    	IntRegister(INT_UART2, UARTIntHandler);
    	IntEnable(INT_UART2);
    	UARTIntEnable(UART2_BASE, UART_INT_RX | UART_INT_RT);
    }
    
    int main(void) {
        volatile int i = 0;
    	setup();
    
    	setupUart();
    
    
    #ifdef _STANDALONE
    #ifdef _FLASH
        //  Send boot command to allow the C28 application to begin execution
        IPCMtoCBootControlSystem(CBROM_MTOC_BOOTMODE_BOOT_FROM_FLASH);
    #else
        //  Send boot command to allow the C28 application to begin execution
        IPCMtoCBootControlSystem(CBROM_MTOC_BOOTMODE_BOOT_FROM_RAM);
    #endif
    #endif
    
    ...
    }
    

    Looking through the assembly for the init call, I don't think all that memory is just scratch storage -- the value it loads at 0x139*0x40+0x1e which it uses as the return value appears for no discernible reason, after it writes that same return value to 0x1c. I imagine the analog subsystem must be tied in here, and writes to the former address as an acknowledgement of its clock being changed. 

    As to your other points

    1) I'll have to look into why we are using that value then. In any case, DIV4 also does not work. 

    2) I added that line after reading the erratas on the subsystem. Removing that line doesn't work either. 

    It's maybe worth mentioning that I can watch CCIBSTATUS and see ASYSCLKCNT change. APGOODSTS is always 1, and I haven't seen READY be anything but zero, even when the ADC is functional. I have verified that nothing is setting CLOCK on me, and (CCLKCTL) is reporting the number given to it in all cases. 

  • David,

    An incrementing ASYSCLKCNT is good, APGOODSTS=1 is good, READY=0 is good.

    Let's do some quick sanity checking before we get too far.

    Can you confirm that you are using the Flash-Standalone build configuration when compiling the program?

    Are other C28x memory writes working as expected?  If the C28x is misbehaving in other ways, try to reset the control subsystem along with the analog subsystem reset:  SysCtlSubSystemReset(SYSCTL_ANALOG_SYSTEM_RES_CNF | SYSCTL_CONTROL_SYSTEM_RES_CNF);

    When you say that the value at 0x4E58 is unchanged after a write, are you observing this through emulation memory read?  If so, are you able to poke the contents manually?  Can you add in a C28x read-back-verify of the register into a variable to make sure that the writes are really lost and it's not some emulation artifact?

    -Tommy

  • Yes, this is using the Flash standalone build configuration. I made the appropriate modifications to the gel file so I could connect and pause execution on both cores without triggering a reset on the C28. 

    Everything else appears to be writing and reading correctly. Resetting both subsystems seems to have no effect. I'm doing this right before the IPCMtoCBootControlSystem call, which I assume is correct. 

    Yes, unchanged according to the emulator. When the analog system comes up correctly, the emulator lets me read and write to that location, showing me my change. 

    The read-back-verify check might be unnecessary. I think I've narrowed it down to a hardware issue. This is a custom board, and we have ARS and XRS tied together per the manual. However, instead of having a resistor before the external signal, we have a diode which disallows the XRS reset from effecting the rest of our hardware on that line. The issue here is possibly that the signal from/to XRS and ARS hovers around .25V when we try to pull it low, and I'm thinking now that this cleanly brings up the M3 and C28, but the analog subsystem state is invalid from this signal configuration.

    Right now there is a hack in place which stops clearing the watchdog if we detect that the analog system is not coming online, allowing a full system reset. I'm still investigating whether just doing this multiple times in a row corrects the issue, or if the external power on line is asserted high when the reset happens it just works. Either way though, this reliably works. These are dev boards for now, and for our next spin we are going to change that hardware, likely giving it a dedicated GPIO and using the resistor as originally designed. 

    For now I'm going to mark this issue as resolved, and re-investigate when we have new development boards with a more stable signal configuration. Thank you for your help resolving this though!

  • David,

    Thank you very much for reporting back your findings.

    I hadn't considered checking the ARS reset for this fail mode.  Your post will be invaluable for anyone else that encounters the same issue.

    -Tommy

  • According to the data sheet, the max voltage for input pins to be considered low is .3 * V_DDIO = .99. Does this also apply to the XRS pin? As far as I can see, holding the XRS/ARS pins at .270 should hold everything in reset, however it seems like its letting the M3/C28 run and keeping the analog subsystem in reset.
  • David,

    I would agree that 270mV should qualify as low for reset. It may be worthwhile to try extending the low duration of the reset signal to see if it helps.

    I suppose that loading the program for RAM execution will most likely trigger a device reset through emulation. Are you powering the board off/on when executing from flash?

    -Tommy