MCF5329: Disabling LCDC can crash the CPU

Discussion created by TomE on Nov 7, 2011
Latest reply on Nov 14, 2011 by TomE



If you stop the LCDC clock to power down or change the settings it may crash the CPU.




The MCF5329 LCDC (LCD Controller) doesn't have any "master enable" bits in the controller itself. Neither does it have any "graceful start" or "graceful stop" bits or commands like some of the other complex controllers do. The chip does have an "LCDCHEN" bit, but it is in the "Miscellaneous" register (MISCCR) in the CCM module. This "Selects whether the internal clock input to the LCD controller is enabled."

The ONLY mention of this bit in the LCDC chapter is the bit that warns "The graphic window can only be enabled while the clock to the LCD controller is disabled (MISCCR[LCDCHEN] is cleared).". No other mention is made.

Some registers in the LCDC are designed to be changed while the controller is running, like the LCD_SSAR (Screen Start Address), LCD_CPR (Cursor Position), LCD_POR (Panning Offset) and others. Other registers probably can't be changed safely on the fly. The Clock Divider, and the registers that define the Panel Width and so on would be ones in this category. Nothing says which registers can be changed "live" and which ones can't.

There is nothing in the chapter detailing initialisation. I assume I have to set up all the registers appropriately for the panel, enable the clock and then leave it alone. I also assume that if I want to change anything out of the ordinary then I should probably stop the clock by clearing the LCDCHEN bit before making any changes. Setting the LCD_GWCR[GWE] is documented to require this, but nothing else is.

I'm currently changing video modes (to a sort of multisync monitor) on the fly and so have been stopping the clock, reprogramming and starting again.

You might also want to stop the clock if going into a low power mode or if blanking a screen and powering off the LCD panel.

If the LCDC is currently performing a DMA transfer when LCDCHEN is disabled, the DMA controller appears to "lock on" and won't let go. The SDRAM bus is now performing back-to-back cycles for the LCDC and the CPU can't get in to read or write the SDRAM. Changing the Crossbar priorities doesn't help. Nothing seems to be able to break out of this problem short of reenabling the LCDC clock, and since the the CPU is currently locked out it can't do that. If you have the watchdog enabled it will reset the whole thing. If you don't have the watchdog enabled you'll need to manually power cycle to recover from this.

I've told Freescale via our account rep and they've confirmed this problem.




I don't have anything back from Freescale yet, but I've worked out the following.

if you stop the clock when the LCDC DMA controller isn't accessing memory then it won't lock up the bus. The obvious point is during the vertical blanking interval. The trick is finding out when this is. There aren't any registers that can be read that monitor where the LCDC controller currently is (what line or memory address it is scanning). There is the LCD_ISR Interrupt Status Register, but that one has a bug that causes problems:


If the CPU is polling this register, waiting for a status bit to be set and it reads the register at the same time that the hardware is trying to set a status bit then it won't be set. So if the code is waiting for the BOF or EOF bit it may miss it, and have to wait a few more frame periods until it manages to read it without clearing it. I'd advise limiting the rate this register is read to once every 10us or so. That still doesn't guarantee it will be read properly though, so your code may still fail.

The BOF/EOF flags don't signal that the DMA has stopped. They happen sometime during or before the last transfer or transfers. There's no documentation giving this timing, and Freescale don't seem to have these details either (I've asked). It also depends on the clock divider and the DMA burst programming. And on other DMA in your system. You'll have to reverse-engineer the timing for your own design, but I found a 20us wait after EOF sets before clearing LCDCHEN worked with my design.

You might be better off setting up an LCDC interrupt and turning the clock off a fixed time after the interrupt happens. You'll also have to guarantee the interrupt can't be delayed by any other code or interrupts in the entire system. You also need to pick the right LCD_ICR settings to get the right BOF and/or EOF, which might be different to your preferred buffer-switch interrupt settings.