Hello my name is françois, I work on Kinetis K70 and I have a problem with LCDC module.
My problem is when I enable or disable the graphic window, the micro crashes and all its registers (R0..R15) are equal to zero. This bug occurs very rarely.
I enable or disable the graphic window when “the end of frame event” occurs. My steps in ISR to enable or disable the graphic window:
1 To set zero the LCDSTART bit in SIM_MCR register.
2 If I want to enable the graphic window to set one the GWE bit in LCDC_LGWCR register
else To disable the graphic window to set zero the GWE bit in LCDC_LGWCR register.
3 To set one the LCDSTART bit in SIM_MCR register.
After a few days of work I understood that the problem occurred just after to disable LCDSTART (to set zero LCDSTART bit in SIM_MCR register). I also noticed that if I used the graphic window end of frame event (GW_EOF) instead of the end of frame event to enable or disable the graphic window, the problem occurred quickly.
I do not know my problem solving
Can you help me please.
Thank you in advance for your reply
My configuration:
- K70 clock 18.4 MHz
- MCG is BLPE.
- LCD clock 6.13
- LCD 340x280
- LCD tft
- LCD 4bpp
- the frame buffer is in the sram
- the window frame buffer is in the sram
- address frame buffer : 0x1fff1800
- address window frame buffer: 0x1fff0400
init pin lcd function
/*--------------------------------------------
| Name: k70f120m_lcd_gpio
| Description:
| Parameters: none
| Return Type: none
| Comments:
| See:
----------------------------------------------*/
static void k70f120m_lcd_gpio (dev_panel_info_t* p_panel_info)
{
char NBPinData=0;
volatile unsigned int reg_val = 0;
int i;
//mettre la pin du reset en sortie
PinConf(LCD_RESET,LCD_RESET_PIN,1);
//mettre l'ecarn en reset n'activer le reset
k70f120m_lcd_reset_on();
//mettre la pin du baclight en sortie
PinConf(LCD_BLK,LCD_BKL_PIN,1);
//allumer le backlight
k70f120m_lcd_backlight_off();
//initiliser les pin pour la luminosite
//initialiser les pin du lcd
//HSYNC VSYNC DE ET DCLK
hal_set_pin_function(LCD_HSYNC);
hal_set_pin_function(LCD_VSYNC);
hal_set_pin_function(LCD_DCLK);
hal_set_pin_function(LCD_DE);
//init des data
//selon la represenation le nombre de pin à initilise n'est pas le même
switch(p_panel_info->vl_bpix)
{
case BPP_4:
NBPinData=18;
break;
case BPP_8:
NBPinData=18;
break;
case BPP_18:
NBPinData=18;
break;
case BPP_24:
NBPinData=24;
break;
default://mode de representation encore non traite
NBPinData=0;
break;
}//switch nombre pin active par réprensation
//pour les data de 0 à 11 et 17 à 23 compri mux = 7
//pour les pin de 12 à 16 mux =5
for(i=LCD_DATA0_PIN;i<(LCD_DATA0_PIN+NBPinData);i++)
{
if((i>LCD_DATA11_PIN) && (i<LCD_DATA17_PIN))
{
hal_set_pin_function(LCD_DATAX(i,5));
}
else
{
hal_set_pin_function(LCD_DATAX(i,7));
}
}
//le lcd utilise la clock bus
HAL_READ_UINT32(REG_SIM_SOPT2_ADDR, reg_val);
reg_val &=~REG_SIM_SOPT2_LCDCSRC_MASK;
HAL_WRITE_UINT32(REG_SIM_SOPT2_ADDR, reg_val);
//activer les clock des differnt peripherique et port concerné
//clock port F
HAL_READ_UINT32(REG_SIM_SCGC5_ADDR, reg_val);
reg_val |= REG_SIM_SCGC5_PORTF_MASK;
HAL_WRITE_UINT32(REG_SIM_SCGC5_ADDR, reg_val);
//clock LCD
HAL_READ_UINT32(REG_SIM_SCGC3_ADDR, reg_val);
reg_val |= REG_SIM_SCGC3_LCDC_MASK;
HAL_WRITE_UINT32(REG_SIM_SCGC3_ADDR, reg_val);
//initialisation du dac de controle de la luminosite
DACx_Init(&DAC_Luminosity_LCD);
//mettre à 100% la luminosity
k70f120m_lcd_set_luminosity(100);
}
Init lcd function:
/*--------------------------------------------
| Name: k70f120m_lcd_ctrl_init
| Description:
| Parameters: none
| Return Type: none
| Comments:
| See:
----------------------------------------------*/
int k70f120m_lcd_ctrl_init (dev_panel_info_t* p_panel_info)
{
unsigned int NbBitPerPixelRegistre;
volatile unsigned int reg_val = 0;
float CoefFreq;
int CoefFreqEntier;
if(!p_panel_info)
return -1;
g_panel_info=p_panel_info;
//init pin
k70f120m_lcd_gpio(g_panel_info);
//verifier existence d'un premier frame buffer
if(!g_panel_info->TabFrameBuffer[0])
return -1;
// set LCD Screen Start Address pour l'instant
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LSSAR, ((uint32_t)g_panel_info->TabFrameBuffer[0]));
//initialise les variables k70f120m_current_frame_buffer et k70f120m_shadow_frame_buffer
k70f120m_current_frame_buffer=0;
k70f120m_shadow_frame_buffer=1;
//set size screen
//Attention la largeur doit etre prealablement divise par 16
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LSR,(LCDC_LSR_XMAX(g_panel_info->vl_col/16)|LCDC_LSR_YMAX(g_panel_info->vl_row)));
// set LCD virtual page width
//explication de ce registre donne dans la doc
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LVPWR,LCDC_LVPWR_VPW(40));//(g_panel_info->vl_col*g_panel_info->vl_bpix)/32
//mettre a zero les registre curseur car on utilise
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LCPR,0);
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LCCMR,0);
//validation de la valeur du nombre de bit par pixel pour le registre
switch(g_panel_info->vl_bpix)
{
case BPP_4:
NbBitPerPixelRegistre=2;
break;
case BPP_8:
NbBitPerPixelRegistre=3;
break;
case BPP_18:
NbBitPerPixelRegistre=6;
break;
case BPP_24:
NbBitPerPixelRegistre=7;
break;
default://cas non gerer
NbBitPerPixelRegistre=0;
break;
}
CoefFreq=((float)CYGNUM_HAL_CORTEXM_KINETIS_MCG_FLL_PLL_REF_FREQ/(float)g_panel_info->vl_pixclock)+0.5;
CoefFreqEntier=(int)CoefFreq;
//registre de configuration du lcd
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LPCR,
(LCDC_LPCR_TFT_MASK | //validation du TFT
LCDC_LPCR_COLOR_MASK | //validation de la couleur
LCDC_LPCR_BPIX(NbBitPerPixelRegistre) | //bbp par pixel 4 ici
LCDC_LPCR_PIXPOL(g_panel_info->vl_dp) | //polarite des data
LCDC_LPCR_FLMPOL(g_panel_info->vl_vsp) | //polarite de vsync
LCDC_LPCR_LPPOL(g_panel_info->vl_hsp) | //polarite de hsync
LCDC_LPCR_CLKPOL(g_panel_info->vl_clkp) | //polarite de clock
LCDC_LPCR_OEPOL(g_panel_info->vl_oep) | //polarite de oep
//LCDC_LPCR_SCLKIDLE_MASK | //valide la clock lorsque VSync en idle attention voir si utile
//LCDC_LPCR_END_SEL_MASK | //Use big-endian mode (0xFFAA5500 means R=AA,G=55,B=00). ATTENTION depant de l'ecran
//LCDC_LPCR_REV_VS_MASK |
LCDC_LPCR_SWAP_SEL_MASK | //Set if needed for LCD data lines match up correctly with the LCD
LCDC_LPCR_SCLKSEL_MASK | //Always enable clock à voir si vraiment utile pour la conso
LCDC_LPCR_PCD(CoefFreqEntier-1))); //Clock micro / par clock lcd -1
//ATTENTION WAIT 2 est HB voir doc micro page 2233
//HSYNC configuration
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LHCR,
(LCDC_LHCR_H_WIDTH(g_panel_info->vl_hpw-1)| //largeur de la pulse HSYNC -1 en clock lcd
LCDC_LHCR_H_WAIT_2(g_panel_info->vl_blw-3)| // nombre de clk lcd entre OE et le debut de hsync -1
LCDC_LHCR_H_WAIT_1(g_panel_info->vl_elw-1) )); // nombre de clk lcd entre la fin d'une ligne et OE – 3
//MEME CHOSE POUR VSYNC
//VSYNC Configuration
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LVCR,
(LCDC_LHCR_H_WIDTH(g_panel_info->vl_vpw)| //largeur de la pulse VSYNC en clock lcd
LCDC_LHCR_H_WAIT_2(g_panel_info->vl_bfw)| // nombre de clk lcd entre OE et le debut debut d'une image
LCDC_LHCR_H_WAIT_1(g_panel_info->vl_efw))); // nombre de clk lcd entre la fin d'une image et OE
//le panning n'est pas utilise le mettre à zero
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LPOR,0);
//deconnecter tout les interrupt
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LICR,LCDC_LICR_INTSYN_MASK);
//deconnecter le mode graphique window peut etre utile pour un double frame buffer
// HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWCR,0);
//init la pallette
if((g_panel_info->vl_bpix==BPP_4)||(g_panel_info->vl_bpix==BPP_8))
k70f120m_lcd_set_lut((const PALETTEENTRY *)g_panel_info->palette,0,(1<<g_panel_info->vl_bpix));
//init du DMA mettre le DMA pour le background en mode burst mode dynamic
HAL_READ_UINT32(LCDC_BASE_PTR + LCDC_LDCR,reg_val);
reg_val&=~LCDC_LDCR_BURST_MASK;
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LDCR, reg_val);
//init buffer window
//initialisation par defaut
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWSAR, ((uint32_t)g_panel_info->TabFrameBuffer[1]));
//set size screen
//Attention la largeur doit etre prealablement divise par 16
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWSR,(LCDC_LGWSR_GWW(WIDHT_MAX_SCREEN_WINDOW/16)|LCDC_LGWSR_GWH(HEIGHT_MAX_SCREEN_WINDOW)));
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWVPWR,LCDC_LGWVPWR_GWVPW(8));
//position window buffer en 0 par defaut
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWPR,LCDC_LGWPR_GWXP(0)|LCDC_LGWPR_GWYP(0));
// set LCD window configuration
// not enable the lcd window
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWCR,LCDC_LGWCR_GWAV_MASK);//(g_panel_info->vl_col*g_panel_info->vl_bpix)/32
//init du DMA mettre le DMA pour le background en mode burst mode dynamic
HAL_READ_UINT32(LCDC_BASE_PTR + LCDC_LGWDCR,reg_val);
reg_val&=~LCDC_LGWDCR_GWBT_MASK;
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWDCR, reg_val);
//creation it
cyg_interrupt_create((cyg_vector_t)KINETIS_LCD_IRQ_NO,
KINETIS_LCD_IRQ_PRIORITY,
(cyg_addrword_t)&StateWindowFrameBuffer,
_kinetis_lcd_isr,
_kinetis_lcd_dsr,
&irq_handle_lcd,
&irq_it_lcd);
cyg_interrupt_attach(irq_handle_lcd);
cyg_interrupt_mask(KINETIS_LCD_IRQ_NO);
//start le lcd
HAL_READ_UINT32(REG_SIM_MCR,reg_val);
reg_val=SIM_MCR_LCDSTART_MASK;
HAL_WRITE_UINT32(REG_SIM_MCR,reg_val);
//desactiver le reset du lcd
//mettre l'ecarn en reset n'activer le reset
k70f120m_lcd_reset_off();
return 0;
}
isr function
cyg_uint32 _kinetis_lcd_isr(cyg_vector_t vector, cyg_addrword_t data) {
cyg_interrupt_mask(vector);
cyg_interrupt_acknowledge(vector);
volatile unsigned int reg_val = 0;
HAL_READ_UINT32(LCDC_BASE_PTR + LCDC_LISR,reg_val);
//dasactive les it
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LIER,0);
//init du DMA mettre le DMA pour le background en mode burst mode dynamic
//HAL_READ_UINT32(LCDC_BASE_PTR + LCDC_LGWDCR,reg_val);
//reg_val|=LCDC_LGWDCR_GWBT_MASK;
//HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWDCR, reg_val);
HAL_READ_UINT32(REG_SIM_MCR,reg_val);
reg_val&=~SIM_MCR_LCDSTART_MASK;
HAL_WRITE_UINT32(REG_SIM_MCR,reg_val);
if(StateWindowFrameBuffer)
{
//start window le lcd
HAL_READ_UINT32(LCDC_BASE_PTR + LCDC_LGWCR,reg_val);
reg_val|=(LCDC_LGWCR_GWE_MASK);
//reg_val|=LCDC_LGWCR_GWAV_MASK;
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWCR,reg_val);
debugfd=40;
}
else
{
HAL_READ_UINT32(LCDC_BASE_PTR + LCDC_LGWCR,reg_val);
reg_val&=~LCDC_LGWCR_GWE_MASK;
//
//reg_val&= ~LCDC_LGWCR_GWAV_MASK;
//reg_val|=(LCDC_LGWCR_GWE_MASK|LCDC_LGWCR_GWAV(0x00));
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWCR,reg_val);
}
//init du DMA mettre le DMA pour le background en mode burst mode dynamic
//HAL_READ_UINT32(LCDC_BASE_PTR + LCDC_LGWDCR,reg_val);
//reg_val&=~LCDC_LGWDCR_GWBT_MASK;
//HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LGWDCR, reg_val);
HAL_READ_UINT32(REG_SIM_MCR,reg_val);
reg_val|=SIM_MCR_LCDSTART_MASK;
HAL_WRITE_UINT32(REG_SIM_MCR,reg_val);
HAL_WRITE_UINT32(LCDC_BASE_PTR + LCDC_LRMCR, 0);
return(CYG_ISR_HANDLED | CYG_ISR_CALL_DSR);
}