原创连载+AM335X学习笔记(9月25日更新到105楼:触摸屏工程分析

[复制链接]
楼主: 阿南
手机看帖
扫描二维码
随时随地手机跟帖
阿南|  楼主 | 2015-8-26 13:49 | 显示全部楼层
gongjian32 发表于 2015-8-26 13:22
基于什么内核来讲? 老的platform类型的,还是设备树类型的。最好还是设备树的吧。 ...

还在熟悉中,欢迎给建议

使用特权

评论回复
阿南|  楼主 | 2015-8-27 10:15 | 显示全部楼层
Boot源代码分析2

3.bl_main.c主函数分析
25.jpg
从main()知,主要做3件事:BlPlatformConfig()对平台进行配置;ImageCopy()从flash或TF卡中将APP映像文件复制到RAM中;(*appEntry)( )从RAM中执行APP。
BlPlatformConfig()
26.jpg
BoardInfoInit()主要是先从板上的EEPROM中读取板的名称、版本和id等板子信息,后续在根据不同的板作相应的初始化工作。
DeviceVersionGet()读取板上主处理器的器件版本。
ConfigVddOpVoltage()控制板上PMIC设定电源Vdd电压值。
BootMaxOppGet()获取处理器所支持的最大OPP(工作性能点,OPP是处理器电压和频率的组合,用户可对其进行控制以实现最佳处理器功耗,从而满足所有给定性能要求)
SetVdd1OpVoltage(oppTable[oppMaxIdx].pmicVolt)设置电源Vdd1电压值。
27.jpg
上述为关闭看门狗定时器,可以从AM335x技术手册上找到:
28.jpg
PLLInit()锁相环时钟初始化。
29.jpg
使能sleep时软件唤醒的控制模块。
EMIFInit()为EMIF存储接口初始化。
DDRVTTEnable()使能DDR的VTT,VTT主要为DDR的地址、控制线等信号的信号完整性而提供的终端电阻电源。
DDR3Init()为DDR3存储器初始化。
UARTSetup()设置UART0为调试端口。
ImageCopy()
30.jpg
我们使用的是AM335x Starter Kit,用的MMCSD接口引导
31.jpg
上述对MMCSD接口初始化后,最终调用HSMMCSDImageCopy()将APP映像文件复制到DDR中运行:
32.jpg
这里先是打开app文件,再读取8个字节的文件头,文件头中4个字节的文件大小,还有4个字节的装载地址。然后再将文件中的映像读到缓冲区,再从缓冲区复制到装载地址区,读完后返回。
main()函数最后是跳转到DDR执行app程序
33.jpg

使用特权

评论回复
東南博士| | 2015-8-27 10:34 | 显示全部楼层
阿南 发表于 2015-8-19 09:38
裸奔,只要能发挥出其价值,没什么可惜的,反而还很有意义。裸奔就能搞定的事情,为何要上系统呢? ...

我崇尚裸奔。
感觉上系统的话,实时性不是很强吧?
水平不高的话,还会死机。
对吗?

使用特权

评论回复
東南博士| | 2015-8-27 10:37 | 显示全部楼层
阿南 发表于 2015-8-25 20:39
Linux不是实时性的操作系统,如果对实时性要求很高,建议选择实时性更强的,TI应该有第三方的实时操作系 ...

南哥!
您好。
AM335X有多少路PWM啊?
我想控制4个伺服电机,脉冲加方向的那种。
另外还需要接6个串口。
来做4路PID运算。

使用特权

评论回复
阿南|  楼主 | 2015-8-27 10:55 | 显示全部楼层
東南博士 发表于 2015-8-27 10:34
我崇尚裸奔。
感觉上系统的话,实时性不是很强吧?
水平不高的话,还会死机。

裸奔处理单任务应该是实时性最好的
如果第一次在Linux下玩,特别在内核态下编程,死机是正常的,不要怕:lol,死了再救活嘛,多死几次就有经验了,关键是要反复测试,不要把死机留给用户就好。

使用特权

评论回复
阿南|  楼主 | 2015-8-27 10:56 | 显示全部楼层
東南博士 发表于 2015-8-27 10:37
南哥!
您好。
AM335X有多少路PWM啊?

这个要查下数据手册

使用特权

评论回复
阿南|  楼主 | 2015-8-27 11:11 | 显示全部楼层
34.jpg
这里不知道是3+3,还是3.你需要研究一下,我没有细看,但从Starter Kit EVM的原理图上看好像是3+3。
另外,还需要注意他和UART的一些管脚是复用的。

使用特权

评论回复
阿南|  楼主 | 2015-8-27 11:12 | 显示全部楼层
或者直接利用定时器+GPIO测试下,是否可以满足要求

使用特权

评论回复
我爱你的吻123| | 2015-8-27 13:51 | 显示全部楼层
阿南 发表于 2015-8-27 11:12
或者直接利用定时器+GPIO测试下,是否可以满足要求

持续跟进中。。。。。。

使用特权

评论回复
hexenzhou| | 2015-8-28 13:18 | 显示全部楼层
好贴,安南兄很给力啊。

使用特权

评论回复
東南博士| | 2015-8-28 14:28 | 显示全部楼层
好的!
多发一些哦!
话说TI的AMP方案在GSM时代是无冕之王啊……

使用特权

评论回复
我爱你的吻123| | 2015-8-28 18:56 | 显示全部楼层
持续关注。。。。。。

使用特权

评论回复
lvyunhua| | 2015-9-1 15:17 | 显示全部楼层
不错,向楼主学习中!

使用特权

评论回复
阿南|  楼主 | 2015-9-2 14:48 | 显示全部楼层
LCD显示例程分析
在CCS左边的Project Explorer中,右键单击选择Import->CCS Projects打开Import CCS Eclipse Projects对话框,点Browse按钮选择目录
C:\ti\AM335X_StarterWare_02_00_01_01\build\armv7a\cgt_ccs\am335x\evmskAM335x\raster,将导入rasterDisplay项目例程,如下图所示:
1.jpg
项目中只有rasterDisplay.c源文件,但会调用其它目录下的一些文件,如system_config、platform等目录下的一些文件。main()主函数中,基本都是初始化调用,MMUConfigAndEnable()函数配置使能MMU内存管理单元,CacheEnable()函数使能Cache高速缓冲区,IntMasterIRQEnable()函数使能ARM处理器的IRQ中断。IntAINTCInit()函数初始化AM335x ARM处理器的中断控制器,通常在使用中断控制器之前完成调用。
2.jpg
#define INTC_SYSCONFIG_SOFTRESET    (0x00000002u)
3.jpg
如上图所示,IntAINTCInit()函数的第一条语句进行软件复位,而第二条语句等待软件复位完成。
4.jpg
而第三条语句则禁止中断优先级。最后一个for循环是初始化各个中断处理函数,即将其设置为进去就出来的空函数。
5.jpg
fnRAMVectors[]被定义为函数型数组,相当于中断向量表,专门用于保存处理器各个中断源的中断处理函数。
LCDAINTCConfigure()为LCD中断配置函数
6.jpg
IntRegister(SYS_INT_LCDCINT, LCDIsr)将LCDIsr()函数作为LCD中断处理函数存入中断向量表fnRAMVectors[]数组中:
7.jpg
RasterIntStatus()函数读取中断状态标志位,RasterClearGetIntStatus()函数清除中断状态标志位,同时返回中断状态标志位。
8.jpg
接着两个if语句分别判断是否为LCD的缓冲区0及1的DMA写结束产生的中断,是则重新配置对应缓冲区的基地址和结束地址。
9.jpg
IntPrioritySet(SYS_INT_LCDCINT, 0, AINTC_HOSTINT_ROUTE_IRQ )函数调用设定LCD中断的优先级
10.jpg
上述是将LCD控制器设置成IRQ中断且优先级为最高的0
IntSystemEnable(SYS_INT_LCDCINT)使能LCD中断。
11.jpg
#define INTC_MIR_CLEAR(n) (0x88 + ((n) * 0x20))
#define REG_IDX_SHIFT                  (0x05)
这里为何要(n)*0x20呢?原来是因为INTC_MIR_CLEAR0、INTC_MIR_CLEAR1和INTC_MIR_CLEAR2分别相差0x20。而2的5次方等于32,所以REG_IDX_SHIFT被定义为0x05。
12.jpg
总的来说就是中断向量号对应的mask位按顺序分别从小到大排列在INTC_MIR_CLEAR0、INTC_MIR_CLEAR1和INTC_MIR_CLEAR2的每位中。
LCDBackLightEnable()函数调用使能LCD背光,LCD背光原理图:
13.jpg
由上图知LCD背光使能由GPIO3_17控制,低电平使能,高电平禁止。
14.jpg
GPIO3ModuleClkConfig()配置GPIO3的时钟模块
GPIO_PMUX_OFFADDR_VALUE(3, 17, PAD_FS_RXE_PD_PUPDE(7))配置GPIO3_17的管脚复用功能为mode 7,CONTROL_CONF_RXACTIVE使能GPIO3_17的输入功能和选择内部电阻下拉,
15.jpg
GPIOModuleReset(SOC_GPIO_3_REGS)软件复位GPIO3模块
GPIOModuleEnable(SOC_GPIO_3_REGS)使能GPIO3模块
GPIODirModeSet(SOC_GPIO_3_REGS,GPIO_INSTANCE_PIN_NUMBER,GPIO_DIR_OUTPUT)函数设置GPIO3_17为输出口
#define  GPIO_INSTANCE_PIN_NUMBER      (17u)
#define GPIO_DIR_OUTPUT               0
16.jpg
GPIOPinWrite(SOC_GPIO_3_REGS, GPIO_INSTANCE_PIN_NUMBER,GPIO_PIN_LOW)函数设置GPIO3_17输出低电平
#define GPIO_PIN_LOW                  0
17.jpg
SetUpLCD()设置LCD
18.jpg
LCDModuleClkConfig()配置LCD模块时钟
LCDPinMuxSetup()配置LCD所使用的管脚复用功能
RasterClocksEnable(LCDC_INSTANCE)使能LCD模块时钟
RasterDisable(LCDC_INSTANCE)禁止LCD模块
RasterClkConfig(LCDC_INSTANCE, 23040000, 192000000)配置LCD从PLL输入的时钟PCLK分频数
RasterDMAConfig(LCDC_INSTANCE, RASTER_DOUBLE_FRAME_BUFFER,
                    RASTER_BURST_SIZE_16, RASTER_FIFO_THRESHOLD_8,
                    RASTER_BIG_ENDIAN_DISABLE)配置LCD的DMA模块方式
RasterModeConfig(LCDC_INSTANCE, RASTER_DISPLAY_MODE_TFT_UNPACKED,
                     RASTER_PALETTE_DATA, RASTER_COLOR, RASTER_RIGHT_ALIGNED)配置LCD支持的模式类型颜色等
19.jpg
RasterTiming2Configure(LCDC_INSTANCE, RASTER_FRAME_CLOCK_LOW |
                                            RASTER_LINE_CLOCK_LOW  |
                                            RASTER_PIXEL_CLOCK_HIGH|
                                            RASTER_SYNC_EDGE_RISING|
                                            RASTER_SYNC_CTRL_ACTIVE|
                                            RASTER_AC_BIAS_HIGH     , 0, 255)配置LCD的驱动时序,不同的屏需要作些调整
20.jpg
RasterHparamConfig(LCDC_INSTANCE, 480, 4, 8, 43)和 RasterVparamConfig(LCDC_INSTANCE, 272, 10, 4, 12)分别配置LCD屏的水平、垂直象素及时序
RasterFIFODMADelayConfig(LCDC_INSTANCE, 128)配置DMA FIFO延时时间
RasterDMAFBConfig()函数,
21.jpg
该函数将要显示的image1数组的首地址转给LCD DMA缓冲区的基地址寄存器(Frame Buffer 0 Base Address pointer),将image1数组末地址转给LCD DMA缓冲区的结束地址寄存器(Frame Buffer 0 Ceiling Address pointer)。另外,AM335x共有两块LCD DMA缓冲区,通过flag标志确定image1转给哪一块。
RasterIntEnable(LCDC_INSTANCE, RASTER_END_OF_FRAME0_INT |
                                     RASTER_END_OF_FRAME1_INT);
使能了LCD DMA End-of-Frame中断,即当LCD缓冲区FB0和FB1的DMA写完成后将发出各自的中断信号。
#define RASTER_END_OF_FRAME0_INT            LCDC_IRQENABLE_SET_EOF0
#define RASTER_END_OF_FRAME1_INT            LCDC_IRQENABLE_SET_EOF1
#define LCDC_IRQENABLE_SET_EOF1   (0x00000200u)
#define LCDC_IRQENABLE_SET_EOF0   (0x00000100u)
22.jpg
主函数中RasterEnable函数使能LCD控制器。
23.jpg
最后是while(1)死循环。
当运行后将在目标板的LCD屏上显示下述图像
24.jpg

使用特权

评论回复
仙人球W| | 2015-9-6 09:48 | 显示全部楼层
学习中...

使用特权

评论回复
阿南|  楼主 | 2015-9-6 10:29 | 显示全部楼层
CCS6+TMDSSK3358仿真调试StarterWare中rasterDisplay是时单步进入外部函数时提示错误的问题解决:
1.jpg
如上图所示,在程序中会调用很多项目目录之外的函数,而此时仿真调试如果想单步进入这些函数就会出错:
Debug.jpg
TI技术工程师给出如下解答:
2.jpg
解决方法:选择下图中的Locate File
3.jpg
此时就能正确进入raster.c的函数RasterDMAFaConfig()函数执行单步运行了:
4.jpg

使用特权

评论回复
Xin飞扬| | 2015-9-6 21:34 | 显示全部楼层
跟着南哥 学习AM335X  给力

使用特权

评论回复
阿南|  楼主 | 2015-9-8 20:48 | 显示全部楼层
LCD显示问题一
因为我们要自己掌握LCD的显示规律及各相关的知识,所以最好自己修改下代码来调试一下。
开发板用的是TI官方TMDXEVM3358,我在原来的rasterDisplay.c中定义了一个数据缓冲区:
#define LCD_WIDTH 480
#define LCD_HEIGHT 272
unsigned int LCDBuffer[LCD_WIDTH*LCD_HEIGHT+8];

然后在程序中将原来的显示代码去掉,修改成自己加的代码,如下:
memcpy(LCDBuffer, image1, sizeof(LCDBuffer));
RasterDMAFBConfig(LCDC_INSTANCE, (unsigned int)LCDBuffer, (unsigned int)LCDBuffer+sizeof(LCDBuffer)-2, 0);
RasterDMAFBConfig(LCDC_INSTANCE, (unsigned int)LCDBuffer, (unsigned int)LCDBuffer+sizeof(LCDBuffer)-2, 1);
用意就是将原来显示的image1数组中数据全部复制到新定义的LCDBuffer中,再将LCDBuffer指针传给LCD DMA的起始和终此缓冲区寄存器。
但在开发板中运行后,显示的LCD屏中有部分乱码,如下:
display1.jpg

将上面三行语句换回下述语句时就显示正常:
RasterDMAFBConfig(LCDC_INSTANCE, (unsigned int)image1, (unsigned int)image1+sizeof(LCDBuffer)-2, 0);
RasterDMAFBConfig(LCDC_INSTANCE, (unsigned int)image1, (unsigned int)image1+sizeof(LCDBuffer)-2, 1);
display2.jpg

经过反复的实验发现,如果在主函数中再次引用LCDBuffer如下图所示,显示能够正常。
display3.jpg
我原以为是程序优化问题,所以我设置了编译器的优化,将其所有优化都去掉:
display4.jpg
但是经过实验后发现依然存在着问题,所以不是编译器优化问题。

使用特权

评论回复
阿南|  楼主 | 2015-9-14 11:46 | 显示全部楼层
LCD显示问题二
上次提到“如果在主函数中再次引用LCDBuffer如下图所示,显示能够正常”,但后来经过反复实现发现,只是好一些,但还是会出现不正常。所以需要深入研究调试,还好在DEMO工程中,也有显示的例子,而且也有定义LCD缓冲区,所以我们需要对比rasterDisplay,测试DEMO工程中的显示效果及深入分析、调试源代码。

demoMain.c的main()主函数中,关于LCD的语句有:
LCD.jpg

Raster0IntRegister()函数:
LCD1.jpg

LCD1.jpg
这里LCD的中断处理函数Raster0Isr()与rasterDisplay里的LCD中断处理函数LCDIsr()相比,不同点只是LCD DMA缓存的起始地址和结束地址不同。
LCD3.jpg
g_pucBuffer为二维数组,每维包含480*272*4+8*4+4=(482*272+8)*4+4
而LCD DMA缓存的
起始地址就等于g_pucBuffer+4,
结束地址就等于g_pucBuffer+4+(482*272+8)*4 -1
另,g_pucBuffer的最前面4个字节为调色板数据
IntPrioritySet(SYS_INT_LCDCINT, 0, AINTC_HOSTINT_ROUTE_IRQ);
IntSystemEnable(SYS_INT_LCDCINT);这两个函数和rasterDisplay是一样的。
Raster0Init()函数和rasterDisplay里的SetUpLCD()函数是一样的。
Raster0EOFIntEnable()函数:
LCD3.jpg
该函数需要和bannerImage数据结构对比进行分析,如bannerImage中的一个数据0x02f1f1fe,它表示2个相同的数据0x00f1f1fe,所以在执行完该函数时,将0x00f1f1fe、0x00f1f1fe存入目标地址的连续两个存储单元中。
CacheDataCleanBuff((unsigned int) &g_pucBuffer[0]+PALETTE_OFFSET, GrOffScreen24BPPSize(LCD_WIDTH, LCD_HEIGHT, PIXEL_24_BPP_UNPACKED));
CacheDataCleanBuff((unsigned int) &g_pucBuffer[1]+PALETTE_OFFSET, GrOffScreen24BPPSize(LCD_WIDTH, LCD_HEIGHT, PIXEL_24_BPP_UNPACKED));
该两个函数调用清除g_pucBuffer[]对应的D-Cache缓冲区段
LCD4.jpg
CP15DCacheCleanBuff()函数为汇编实现的代码
Raster0Start()显示图像


哈哈问题就在于CacheDataCleanBuff()函数,raster工程中是没有调用的,所以经过反复测试,当在rasterDisplay.c的写LCD缓冲区后,再调用一次该函数时,LCD就不会出现花瓶现象了。
LCD6.jpg

使用特权

评论回复
阿南|  楼主 | 2015-9-25 16:47 | 显示全部楼层
LCD颜色值问题
我们想自己写一个LCD测试程序,用自己定义的RGB颜色值,把硬件上LCD的数据线关联起来,而不是DEMO提供的现成的一幅图像值,只有这样才能真正理解LCD显示部分的使用。
定义如下RGB颜色值:
//FRM8:8:8(红:绿:蓝)
#define clWhite      0x00FFFFFF                      //白色
#define clBlack      0x00000000                      //黑色
#define clDRed       0x00800000                      //浅红色,为全色的一半
#define clLRed       0x00FF0000                      //深红色
#define clDMagenta   0x00800080                      //暗紫色
#define clLMagenta   0x00FF00FF                      //亮紫色
#define clGreen      0x0000FF00                      //绿色
#define clDBlue      0x00000080                      //暗蓝色
#define clLBlue      0x000000FF                      //亮蓝色
#define clDCyan      0x00008800                      //暗青色
#define clLCyan      0x0000FFFF                      //亮青色
#define clDYellow    0x00808000                      //暗黄色
#define clLYellow    0x00FFFF00                      //亮黄色
#define clDGray      0x00808080                      //暗灰色
#define clLGray      0x00FCFCFC                      //亮灰色
#define clLArgent    0x00E3E3E3                      //亮银色

增加一个显示背景色的函数:
void DisplayBackground(unsigned int *destPtr, unsigned long color)
{
          unsigned int i;
    for (i = 0; i < 130560; i++)
    {
            destPtr = color;
    }
    CacheDataCleanBuff((unsigned int)destPtr, LCD_WIDTH*LCD_HEIGHT*4);
}

再在main()函数的while(1)中增加各种颜色的测试代码如下:
    while(1)
    {
        delay(50000000);
        DisplayBackground((unsigned int*)LCDBuffer, clWhite);
        delay(50000000);
        DisplayBackground((unsigned int*)LCDBuffer, clBlack);
        delay(50000000);
//        DisplayBackground(clDRed);
//        delay(500000000);
        DisplayBackground((unsigned int*)LCDBuffer, clLRed);
        delay(50000000);
//        DisplayBackground(clDMagenta);
//        delay(500000000);
//        DisplayBackground(clLMagenta);
//        delay(500000000);
        DisplayBackground((unsigned int*)LCDBuffer, clGreen);
        delay(50000000);
//        DisplayBackground(clDBlue);
//        delay(500000000);
        DisplayBackground((unsigned int*)LCDBuffer, clLBlue);
        delay(50000000);
//        DisplayBackground(clDCyan);
//        delay(500000000);
        DisplayBackground((unsigned int*)LCDBuffer, clLCyan);
        delay(50000000);
        DisplayBackground((unsigned int*)LCDBuffer, clDYellow);
        delay(50000000);
        DisplayBackground((unsigned int*)LCDBuffer, clLYellow);
        delay(50000000);
        DisplayBackground((unsigned int*)LCDBuffer, clDGray);
        delay(50000000);
        DisplayBackground((unsigned int*)LCDBuffer, clLGray);
        delay(50000000);
        DisplayBackground((unsigned int*)LCDBuffer, clLArgent);
    }

之前由于DisplayBackground()函数有问题,所以没能正确显示想要的背景颜色,所以第一反映是想到LCD数据问题,查看了StarterKit的原理图,发现如下:
LCD原理图.jpg

从图中可以看出RGB数据线是乱序的,但我在StarterWare中根据乱序来调整测试发现并没有正确,但是StarterWare中demo和raster工程中的图片显示又都是正确的。
后来在TI代理商的提示下从AM335x 勘误表中查到如下信息:
image001(09-25-16-22-59).png

这也消除了为什么StarterKit原理图的LCD数据线为何接成我所认为的乱序情况!同时我也在数据手册中找到下图:
image001(09-25-16-22-48).jpg

因此,我按上述的数据格式去定义数据:
#define clLRed          0x0025001F                      //红色
#define clGreen            0x004807E0                      //绿色
#define clLBlue            0x0092F800                   //蓝色

但依然显示有问题。后来经过反复的实验发现,问题在于DisplayBackground()函数后,将数据定义修改成原来的定义就成功了:
#define clLRed          0x00FF0000                      //红色
#define clGreen             0x0000FF00                      //绿色
#define clLBlue     0x000000FF                      //蓝色

使用特权

评论回复
发新帖 本帖赏金 33.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则