硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2819|回复: 31
收起左侧

[emWin] emWIN存储设备绘图死机

[复制链接]

3

主题

32

回帖

41

积分

新手上路

积分
41
发表于 2017-11-6 09:32:10 | 显示全部楼层 |阅读模式
将SD卡上的图像文件读进RAM再绘制没有问题,测试BMP,JPG,GIF,PNG都正常,但在使用存储设备绘制图像时,进入HardFault_Handler死机。
GUIconf配置如下:
配置.png


调试发现如果使用下面方法出错:
#define SDRAM_APP_BUF  SDRAM_BANK_ADDR+8*1024*1024
aMemory = (U32*)SDRAM_APP_BUF;
此时直接在GUI_Init函数死机调试发现aMemory已经赋值为0xC1000000,直接越界了,但修改为上图中内容时EMWIN起跑。

此后使用存储设备绘制图片时又出现死机。
操作如下:

    GUI_JPEG_GetInfo(_acBuffer,flist.fsize,&JpegInfo);       //获取图片的尺寸

//    hMEMjpg = GUI_MEMDEV_CreateEx(0,0,JpegInfo.XSize,JpegInfo.XSize,GUI_MEMDEV_HASTRANS);     //创建内存设备
//    GUI_MEMDEV_Select(hMEMjpg);
    GUI_JPEG_Draw(_acBuffer,flist.fsize,px,py);          //绘制图像
//    GUI_MEMDEV_Select(0);

将图中的存储设备函数注释后绘图正常。几种格式的图片文件绘制都出现相同情况(将SD卡的图片文件读进RAM)
调试发现在绘图函数中死机,请问是怎么回事?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115749
QQ
发表于 2017-11-6 09:46:12 | 显示全部楼层
这样测试下看看,先将GUIConf.C文件中的动态内存改成使用芯片的内部SRAM,最好最少分配100KB。然后截图比较小的JPEG格式图片,也就20*20左右吧,然后绘制看看。
这样可以排查是不是SDRAM性能更不上,或者其他方面的问题。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 09:52:42 | 显示全部楼层
使用STM32内部RAM可以在使用存储设备时正常绘制,查了好久不明白哪里出了问题。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 09:53:33 | 显示全部楼层
并且在主函数中使用循环读写SDRAM正常
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 09:56:00 | 显示全部楼层
使用内部RAM时,绘制比较大的图片死机,但是绘制164*172的BMP没有问题,动态内存配置为100K
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115749
QQ
发表于 2017-11-6 10:00:11 | 显示全部楼层
内部SRAM会做比较大的JPG死机是正常的,因为动态内存不够。
可以这样修改下,你看看你的LTDC和SDRAM所涉及到GPIO的速度等级,现在将其统一降低一个速度等级看看。也许有效果。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 10:02:35 | 显示全部楼层
对了,是绘制jpg没有问题,绘制这么大的BMP死机(读进内存,再使用存储设备)

GUI_JPEG_GetInfo(_acBuffer,flist.fsize,&JpegInfo);       //获取图片的尺寸
   
hMEMjpg = GUI_MEMDEV_CreateEx(0,0,JpegInfo.XSize,JpegInfo.XSize,GUI_MEMDEV_HASTRANS);     //创建内存设备
GUI_MEMDEV_Select(hMEMjpg);
GUI_JPEG_Draw(_acBuffer,flist.fsize,px,py);          //绘制图像
GUI_MEMDEV_Select(0);
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 10:04:33 | 显示全部楼层
非常感谢,我试试看
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 10:12:35 | 显示全部楼层
将LTDC及SDRAM的GPIO速度降下来,问题照旧啊
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 10:18:53 | 显示全部楼层
我将SDRAM的初始化程序贴上来,硬汉大哥帮我看看是不是时序配置上出了什么问题

static void SDRAM_InitSequence(void)
{
  FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
  uint32_t tmpr = 0;
  
/* Step 3 --------------------------------------------------------------------*/
  /* Configure a clock configuration enable command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;    //bank2-------
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);  
  
/* Step 4 --------------------------------------------------------------------*/
  /* Insert 100 ms delay */
  delay_ms(100);
   
/* Step 5 --------------------------------------------------------------------*/
  /* Configure a PALL (precharge all) command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;    //bank2-------
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
/* Step 6 --------------------------------------------------------------------*/
  /* Configure a Auto-Refresh command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;      //bank2------
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 4;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the  first command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the second command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
/* Step 7 --------------------------------------------------------------------*/
  /* Program the external memory mode register */
  tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2          |
                   SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                   SDRAM_MODEREG_CAS_LATENCY_3           |
                   SDRAM_MODEREG_OPERATING_MODE_STANDARD |
                   SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  
  /* Configure a load Mode register command*/
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;   //bank2--------
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
/* Step 8 --------------------------------------------------------------------*/

  /* Set the refresh rate counter */
  /* (7.81 us x Freq) - 20 */
  /* Set the device refresh counter */
  FMC_SetRefreshCount(683);
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)        //bank2------
  {
  }
}


static void SDRAM_Init(void)
{
  FMC_SDRAMInitTypeDef  FMC_SDRAMInitStructure;
  FMC_SDRAMTimingInitTypeDef  FMC_SDRAMTimingInitStructure;
  
  /* GPIO configuration for FMC SDRAM bank */
  SDRAM_GPIOConfig();
  
  /* Enable FMC clock */
  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);

/* FMC Configuration ---------------------------------------------------------*/
/* FMC SDRAM Bank configuration */   
  /* Timing configuration for 84 Mhz of SD clock frequency (168Mhz/2) */
  /* TMRD: 2 Clock cycles */
  FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;      
  /* TXSR: min=70ns (6x11.90ns) 最小75ns,*/
  FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;   
  /* TRAS: min=42ns (4x11.90ns) max=120k (ns) 最低44ns*/
  FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;      
  /* TRC:  min=63 (6x11.90ns) 最低66ns*/        
  FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 7;        
  /* TWR:  2 Clock cycles 写入稳定时间 最低1时钟周期+7.5ns*/
  FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;      
  /* TRP:  15ns => 2x11.90ns 预充电有效时间 最低20ns*/
  FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;               
  /* TRCD: 15ns => 2x11.90ns 读写命令间的延时 最低20ns*/
  FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;               

/* FMC SDRAM control configuration */
  FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank1_SDRAM;      //bank2--------------------------
  /* Row addressing: [7:0] */
  FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
  /* Column addressing: [11:0] */
  FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
  FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH;
  FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
/*  设置CAS值为3     */
  FMC_SDRAMInitStructure.FMC_CASLatency = SDRAM_CAS_LATENCY;
/*   禁止写保护     */
  FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
/*  FMC时钟频率为HCLK时钟2分频   */   
  FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDCLOCK_PERIOD;  
/*  禁止读模式时的突发模式   */
  FMC_SDRAMInitStructure.FMC_ReadBurst = SDRAM_READBURST;
/*  读管道延时时间为1个存储器时钟周期   */
  FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1;
  FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
  
  /* FMC SDRAM bank initialization */
  FMC_SDRAMInit(&FMC_SDRAMInitStructure);
  
  /* FMC SDRAM device initialization sequence */
  SDRAM_InitSequence();
}
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 10:20:47 | 显示全部楼层
#define  SDRAM_BANK_ADDR      0xC0000000
     
#define SDRAM_MEMORY_WIDTH    FMC_SDMemory_Width_32b
#define SDRAM_CAS_LATENCY     FMC_CAS_Latency_3
#define SDCLOCK_PERIOD        FMC_SDClock_Period_2
#define SDRAM_READBURST       FMC_Read_Burst_Disable

#define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200)
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 10:27:56 | 显示全部楼层
还有,我将STM时钟超频到了192M,实测超频到216M运行稳定
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 10:47:16 | 显示全部楼层
现在完全参照安富莱的例程修改SDRAM的初始化参数,并且将STM时钟降至180M,问题照旧[s:144]
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115749
QQ
发表于 2017-11-6 10:58:58 | 显示全部楼层

回 passteen 的帖子

passteen:现在完全参照安富莱的例程修改SDRAM的初始化参数,并且将STM时钟降至180M,问题照旧[s:144]  (2017-11-06 10:47) 
还有一招,你降低你的LTDC输出时钟看看,现在配置的多少,降低一半看看。
降低并重新下载程序后,等到一分钟重新开机看。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 11:28:32 | 显示全部楼层
LTDC时钟只有25M
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 21:02:28 | 显示全部楼层
将LTDC时钟降低为20M,修改 GUI_BLOCKSIZE  为0x200 ,依旧。将STM时钟恢复至192M(实际可稳超216,更高未测试,待解决此问题后超至240M测试,由于有GIF动画,观察长时间运行是否出问题,此后话),继续查找原因。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 23:36:54 | 显示全部楼层
在MAIN函数中作如下操作:

GUI_Init();
   
    GUI_SetFont(&GUI_Font8x16);
   
    GUI_SelectLayer(1);   //STemWin默认操作图层1的,如开启F429的双层,则在此需设置为layer2。对于touch也有类似情况
   
    res_sd = f_mount(&fs, "0:",1);         //挂载SD卡
   
    if(res_sd==FR_OK)
        GUI_DispStringAt("SD Card Files Sysrem Loading is OK !", 16,16);
    else GUI_DispStringAt("SD Card Files Sysrem Loading is Failed !", 16,16);
   
    Ps = (u32*)0xC0000000;
    for(TCUN=0;TCUN<0x400000;TCUN++)
    {
        *Ps = TCUN+1;
        Ps++;
    }
   
    delay_ms(2000);
   
    sum_sta=0;
    Ps = (u32*)0xC0000000;
    for(TCUN=0;TCUN<0x400000;TCUN++)
    {
        Tdata = *Ps ;
        if(Tdata != (TCUN+1))  
            sum_sta++;             //检测出错数据量
        Ps++;
    }
   
    Ps = (u32*)0xC0000000;
    for(TCUN=0;TCUN<0x400000;TCUN++)
    {
        *Ps = 0x400000-TCUN;
        Ps++;
    }
   
    delay_ms(2000);
   
    sum_sta=0;
    Ps = (u32*)0xC0000000;
    for(TCUN=0;TCUN<0x400000;TCUN++)
    {
        Tdata = *Ps ;
        if(Tdata != (0x400000-TCUN))  
            sum_sta++;             //检测出错数据量
        Ps++;
    }

实测证明16M SDRAM读写毫无问题。由于操作SDRAM时直接改写了EMWIN的管理存储器,因为后续有EMWIN的函数,这些操作完成后死机。(这里延时函数不可使用GUI_Delay)

使用了三种操作,先全空间递增写,延时2S读,而后全空间递减写,延时2s读,随后全空间递减写再读,检测的错误为0,证明SDRAM毫无问题。

再查一查,实在不行只好先放弃。改用文件不加载至内存解码图片试试。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-6 23:50:04 | 显示全部楼层
关于为何测试SDRAM,是因为调试过程中,查找到死机中断处的指令定位,而后再汇编窗口调试N久,发现在一处B指令段N多次循环,强行跳出改循环后死机(N久实在受不了)。观察到寄存器中经常出现给EMWIN分配的SDRAM地址段内容出现(多次出现首地址偏移量为8,0x28,0x30,这应该是EMWIN的内存链表。还多次出险偏移量很大的好几个地址),应该是解码过程,怀疑运行过程中可能有数据内容丢失,因而测试。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115749
QQ
发表于 2017-11-7 02:01:27 | 显示全部楼层
手头就做了这一个板子么,还有新版本的话可以测试下。以前有网友遇到过这种问题,降低下GPIO速度等级解决了。两位你可以降低你的SDRAM时钟看看。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-7 10:30:17 | 显示全部楼层
非常感谢硬汉大哥不厌其烦指导

将GPIO速率降低为25M(SDRAM及LTDC),依旧。降至2M黑屏。

但是发现一个新问题,将PLLSAI的N值修改为80,R为4,如此LTDC时钟为20M,下载后LCD竟然不闪动了,之前都是有大约1S左右时间逐渐改善的闪动现象。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-7 10:34:39 | 显示全部楼层
之前有网友遇到这种问题修改GPIO速率解决,应该是PCB设计存在信号问题导致高速信号畸变和时序不整齐。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-7 18:40:09 | 显示全部楼层
终于搞清楚了。

先操作一个很小的图片(30*20),不死机了,但是LCD上没有出现图片。

于是:

GUI_JPEG_GetInfo(_acBuffer,flist.fsize,&JpegInfo);       //获取图片的尺寸

hMEMjpg = GUI_MEMDEV_CreateEx(0,0,JpegInfo.XSize,JpegInfo.XSize,GUI_MEMDEV_HASTRANS);     //创建内存设备,并将图像绘制进去
GUI_MEMDEV_Select(hMEMjpg);
GUI_JPEG_Draw(_acBuffer,flist.fsize,0,0);          //绘制图像                           这里需要将坐标设置为0,0,否则显示会偏移
GUI_MEMDEV_CopyToLCDAt(hMEMjpg,px,py);                                             //添加了这个函数      
GUI_MEMDEV_Select(0);
再测试,一切正常。改用大图片(720*450),正常。
因此,在使用存储设备绘制图像时,不要忘了添加GUI_MEMDEV_CopyToLCD函数。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-7 19:38:02 | 显示全部楼层
回头又想了一下,觉得很奇怪,为何会死在GUI_JPEG_Draw函数内
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115749
QQ
发表于 2017-11-8 01:55:28 | 显示全部楼层

回 passteen 的帖子

passteen:终于搞清楚了。

先操作一个很小的图片(30*20),不死机了,但是LCD上没有出现图片。

于是:
....... (2017-11-07 18:40) 
不是的,这样使用的话,属于用法错误了。你要先绘制到存储设备里面,然后才可以调用存储设备的API函数进行显示。

另外,你将你的程序中三缓冲使能函数注释掉,如果开启了窗口使用存储设备函数,也将其注释掉。然后测试,看看是否有问题。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-8 21:02:42 | 显示全部楼层

回 eric2013 的帖子

eric2013:

不是的,这样使用的话,属于用法错误了。你要先绘制到存储设备里面,然后才可以调用存储设备的API函数进行显示。

另外,你将你的程序中三缓冲使能函数注释掉,如果开启了窗口使用存储设备函数,也将其注释掉。然后测试,看看是否有问题。
回头又想了一下,觉得很奇怪,为何会死在GUI_JPEG_Draw函数内

我现在是这样操作的:

GUI_HMEM  _ShowJpg(const char *sFilename, int px, int py)
{
    GUI_HMEM  PicMem;
    GUI_MEMDEV_Handle  hMEMjpg;
    GUI_JPEG_INFO JpegInfo;
    if(GetAlocMem(sFilename,PicMem))                        //将SD卡jpg文件加载至内存
    {
        GUI_JPEG_GetInfo(_acBuffer,flist.fsize,&JpegInfo);       //获取图片的尺寸
        hMEMjpg = GUI_MEMDEV_CreateEx(0,0,JpegInfo.XSize,JpegInfo.YSize,GUI_MEMDEV_HASTRANS);     //创建内存设备
        GUI_MEMDEV_Select(hMEMjpg);                        //激活(手册上说的)
        GUI_JPEG_Draw(_acBuffer,flist.fsize,0,0);          //绘制图像
        GUI_MEMDEV_CopyToLCDAt(hMEMjpg,px,py);             //显示
        GUI_MEMDEV_Delete(hMEMjpg);                        //释放内存
    }
    GUI_ALLOC_Free(PicMem);                  //释放动态内存
    f_close(&flist);                         //关闭文件,flist是全局变量
    return     hMEMjpg;
}
这里应该是先绘制进存储设备吧?
对于GUI_MEMDEV_Selec(0)函数,是激活LCD,但是不明白,向新申请的存储设备绘制图像,完成后使用该函数,而后是否要释放存储设备?还有,我这里先前也是这个用法,不是死机就是不显示。
另外,是否该函数表明申请存储设备时,EMWIN已经将已存在的LCD图像拷贝进存储设备了,否则会有现有图像(背景)不显示。

我也怀疑配置有问题,今天也仔细核对,没有发现问题。
相关配置如下:

#define emWin_Optimize   0

//
// Physical display size
//
#define XSIZE_PHYS 800
#define YSIZE_PHYS 480                               //根据实际屏的像素尺寸定义

/* 2. 多缓冲 / 虚拟屏,多缓冲和虚拟屏不可同时大于1使用,emWin不支持 */
#define NUM_BUFFERS      2 /* 定义多缓冲个数,仅可以设置1,2和3,也就是最大支持三缓冲 */
#define NUM_VSCREENS     1 /* 定义虚拟屏个数 */

/* 3. 没有图层激活时,背景色设置, 暂时未用到 */
#define BK_COLOR         GUI_DARKBLUE

/*
   4. 重定义图层数,对于STM32F429/439,用户可以选择一个图层或者两个图层,不支持三图层
      (1). 设置GUI_NUM_LAYERS = 1时,即仅使用图层1,默认触摸值是发送给图层1的。
      (2). 设置GUI_NUM_LAYERS = 2时,即图层1和图层2都已经使能,此时图层2是顶层,
           用户需要根据自己的使用情况设置如下两个地方。
           a. 需要将触摸数据发送给图层2
           b. 调用GUI_Init函数后,调用函数GUI_SelectLayer(1), 设置当前操作的是图层2。
*/
#undef  GUI_NUM_LAYERS
#define GUI_NUM_LAYERS    1

#define COLOR_MODE_0      _CM_RGB565                           //定义为_CM_ARGB8888时,大图像显示不正常,貌似LTDC显存地址配置错误,且解码后的颜色格式有问题

GUIConf配置如下:
#define USE_EXRAM    1          //使用外部存储器则配置位1

#if USE_EXRAM
    #define GUI_NUMBYTES  (1024*1024*8)                //使用外部存储器,此处需根据实际情况修改
#else
    #define GUI_NUMBYTES  (100*1024)                   //使用芯片内部RAM
#endif
#define  GUI_BLOCKSIZE  0x200                           //定义emWin使用的存储块的平均尺寸

void GUI_X_Config(void) {
#if    USE_EXRAM
    static  U32  *aMemory;  
    aMemory = (U32*)(SDRAM_BANK_ADDR+8*1024*1024);           //使用外部存储器时需要定义该缓冲地址
    /*  Assign memroy to emWin */
    GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);           //配置STemWIN使用的存储区及大小
    GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);                 //配置存储块的平均尺寸
#else
  /* 32 bit aligned memory area */
    static U32 aMemory[GUI_NUMBYTES / 4];
    /*  Assign memroy to emWin */
    GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
    GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
#endif
  /* Set default font  */
  GUI_SetDefaultFont(GUI_FONT_6X8);
}
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-8 21:12:30 | 显示全部楼层
GUI_HMEM  _ShowJpg(const char *sFilename, int px, int py)
{
    GUI_HMEM  PicMem;
    GUI_MEMDEV_Handle  hMEMjpg;
    GUI_JPEG_INFO JpegInfo;
    if(GetAlocMem(sFilename,PicMem))                        //将SD卡jpg文件加载至内存
    {
        GUI_JPEG_GetInfo(_acBuffer,flist.fsize,&JpegInfo);       //获取图片的尺寸
        hMEMjpg = GUI_MEMDEV_CreateEx(0,0,JpegInfo.XSize,JpegInfo.YSize,GUI_MEMDEV_HASTRANS);     //创建内存设备
        GUI_MEMDEV_Select(hMEMjpg);                        //激活(手册上说的)
        GUI_JPEG_Draw(_acBuffer,flist.fsize,0,0);          //绘制图像
        GUI_MEMDEV_Select(0);             //显示
        GUI_MEMDEV_Delete(hMEMjpg);                        //释放内存
    }
    GUI_ALLOC_Free(PicMem);                  //释放动态内存
    f_close(&flist);                         //关闭文件,flist是全局变量
    return     hMEMjpg;
}
这样操作,使用GUI_MEMDEV_Select(0);不死机了,但是LCD上没有显示出来应该出现的图像(没有使用窗口,但是配置里面打开了)
#define GUI_WINSUPPORT                (1)    难道与这个有关?

将这个窗口的开关设置为0,依旧没有应有的图像出现

而后将绘图函数内的坐标赋值(x=60,y=20,图片大小720*450),其余一切不变,死机。
看来是申请的内存不够用导致,小图片不会死机(emwin分配的内存估计是按照图片大小给了一点余量的,SDRAM给emwin使用的内存空间可是有8M的,算是土豪吧)。
至于为何使用GUI_MEMDEV_Select(0)不能在LCD上显示应有的图片,还得查下去。

硬汉大哥,你怎么看?
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-8 21:30:30 | 显示全部楼层
今天超频至240M,相应的LTDC时钟,以及其他诸如SDIO及外设时钟维持正常。(外设不可随意超频,已经测试过会有问题)
下载后任其运行,而后去查代码等等,大概两三小时后工作依然正常,STM32无温升现象(可能不是夏天吧,但武汉这两天的温度不算低)。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-8 22:31:42 | 显示全部楼层
自认为可以下结论了,使用存储设备绘图,申请的尺寸是10*10,但是绘图时添加了偏移量(可能emwin保留有少量的余量,偏移较小时时可能会勉强通过),相当于加大了尺寸,绘图时内存不溢出才怪。(分段模式除外)
对于GUI_MEMDEV_Select(0),仅仅只是将绘图操作的指针指向了LCD存储区首地址,并没有其它动作,所以绘制在存储设备中的图像不会在LCD中显示,而要显示出来的话,则必须拷贝至LCD,或者将LCD控制器的指针指向存储设备。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115749
QQ
发表于 2017-11-9 02:14:20 | 显示全部楼层

回 passteen 的帖子

passteen:GUI_HMEM  _ShowJpg(const char *sFilename, int px, int py)
{
    GUI_HMEM &#160icMem;
    GUI_MEMDEV_Handle  hMEMjpg;
    GUI_JPEG_INFO JpegInfo;
....... (2017-11-08 21:12) 
这个函数GUI_MEMDEV_Delete(hMEMjpg);                        //释放内存
得删掉,你不能释放你申请的存储设备,因为每次调用存储设备的API函数显示都还得要用到。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-9 10:53:57 | 显示全部楼层

回 eric2013 的帖子

eric2013:这个函数GUI_MEMDEV_Delete(hMEMjpg);                        //释放内存
得删掉,你不能释放你申请的存储设备,因为每次调用存储设备的API函数显示 .. (2017-11-09 02:14) 
非常感谢指点。

但是有个疑问,hMEMjpg是在函数内部声明的,是不是要申明为全局的?
我理解的是该函数完毕后,hMEMjpg就不存在了,但是内存空间还存在。所以就加了释放。
再次调用这个函数还会重新你申请。如果在函数外部再次使用这个hMEMjpg,是不是有问题?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115749
QQ
发表于 2017-11-10 01:16:29 | 显示全部楼层

回 passteen 的帖子

passteen:非常感谢指点。

但是有个疑问,hMEMjpg是在函数内部声明的,是不是要申明为全局的?
我理解的是该函数完毕后,hMEMjpg就不存在了,但是内存空间还存在。所以就加了释放。
....... (2017-11-09 10:53) 
推荐放在外部,你想释放的时候,随时可以释放。
回复

使用道具 举报

3

主题

32

回帖

41

积分

新手上路

积分
41
 楼主| 发表于 2017-11-10 10:19:28 | 显示全部楼层
明白了,感谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-5-15 23:52 , Processed in 0.395691 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表