搜索
bottom↓
回复: 17

LGT的基本写入/读出已经分析完成,下个星期回家后分析FUSE

[复制链接]

出0入0汤圆

发表于 2012-9-16 00:07:23 | 显示全部楼层 |阅读模式
这里仅仅是一个实例程序。用计数值填充LGT的整个FLASH空间的程序。现在已经做好串口ISP,可以上马/自制脱机编程器了。只是熔丝会有点稍稍的麻烦。
这个是51代码。但是事实上只要更换IO操作函数是可以在别的机器上用的。
Test函数中有说明如何写入。
感谢bbsniua网友和goodcode的ISP(反汇编+逻辑分析仪发现退出编程的命令有点问题)以及官方ISP程序。
等到下次回家以后搞定熔丝位。毕竟现在熔丝位看起来很奇怪。貌似不是以明文形式表示的OSCCAL。
OK废话少说上代码:
  1. #include <hwconfig.h>//包含硬件配置
  2. #include <type-def.h>//包含一些定义

  3. BYTE OutBuf[5];//发送命令缓冲
  4. BYTE InBuf[5];//接收缓冲
  5. //BYTE ComBuf[36];// |SOT|CMD|Data(32bytes)|ChkSum|EOT|
  6. void SendSPI(BYTE nByte)//用MOSI串行发送命令的同时用MISO接收相关数据
  7. {
  8.         BYTE n;
  9.         for(n=0;n<nByte;n++)//发送nByte个字节
  10.         {
  11.                 //RESET=0;
  12.                 ACC=OutBuf[n];
  13.                 SCLK=0;
  14.                 MOSI=A_7;//低电平时输出一位
  15.                 SCLK=1;
  16.                 B_7=MISO;//高电平时接收一位
  17.                 SCLK=0;
  18.                 MOSI=A_6;
  19.                 SCLK=1;
  20.                 B_6=MISO;
  21.                 SCLK=0;
  22.                 MOSI=A_5;
  23.                 SCLK=1;
  24.                 B_5=MISO;
  25.                 SCLK=0;
  26.                 MOSI=A_4;
  27.                 SCLK=1;
  28.                 B_4=MISO;
  29.                 SCLK=0;
  30.                 MOSI=A_3;
  31.                 SCLK=1;
  32.                 B_3=MISO;
  33.                 SCLK=0;
  34.                 MOSI=A_2;
  35.                 SCLK=1;
  36.                 B_2=MISO;
  37.                 SCLK=0;
  38.                 MOSI=A_1;
  39.                 SCLK=1;
  40.                 B_1=MISO;
  41.                 SCLK=0;
  42.                 MOSI=A_0;
  43.                 SCLK=1;
  44.                 B_0=MISO;
  45.                 SCLK=0;
  46.                 InBuf[n]=B;
  47.                 //RESET=1;
  48.         }
  49. }
  50. void Delay(BYTE n)
  51. {//不精确延时
  52.         while(n--);
  53. }


  54. BOOL CheckAck() //检查
  55. {
  56.         if(InBuf[3]!=0x55) return FALSE;
  57.         if(InBuf[4]!=0xAA) return FALSE;
  58.         return TRUE;
  59. }

  60. BOOL Reset_Target()
  61. {//重启目标
  62.         SCLK=0;
  63.         MOSI=0;
  64.         MISO=1;
  65.         Delay(1);
  66.         RESET=0;
  67.         Delay(255);
  68.         OutBuf[0]=0xE0;//开启编程
  69.         OutBuf[1]=0x5A;
  70.         OutBuf[2]=0xA5;
  71.         OutBuf[3]=0xAA;
  72.         OutBuf[4]=0x00;
  73.         SendSPI(5);//发送数据
  74.         if(InBuf[4]!=0x5A) return FALSE;
  75.         return TRUE;
  76. }

  77. void Read_8F08(BYTE Bank,BYTE Addr)
  78. {
  79.         OutBuf[0]=0xB8;
  80.         OutBuf[1]=Addr;
  81.         OutBuf[2]=Bank;
  82.         OutBuf[3]=0x00;
  83.         OutBuf[4]=0x00;
  84.         SendSPI(5);
  85.         OutBuf[0]=0xBC;
  86.         SendSPI(5);       
  87.         //And you got it in InBuf[3],InBuf[4]
  88. }


  89. BOOL Write_8F08(BYTE Bank,BYTE Addr)
  90. {
  91.         OutBuf[0]=0x90;
  92.         OutBuf[1]=0xC0 | Addr ;//B1000 0000 Or Addr
  93.         OutBuf[2]=Bank;
  94.         //OutBuf[3]
  95.         //OutBuf[4]//送入数据
  96.         SendSPI(5);
  97.         if(!CheckAck()) return FALSE;
  98.         OutBuf[0]=0x98;
  99.         SendSPI(5);               
  100.         if(!CheckAck()) return FALSE;
  101.         OutBuf[0]=0x90;
  102.         SendSPI(5);
  103.         if(!CheckAck()) return FALSE;
  104.         return TRUE;
  105. }

  106. BOOL Erase_8F08()
  107. {
  108.        
  109.                 OutBuf[0]=0xB8;
  110.                 OutBuf[1]=0x3F;
  111.                 OutBuf[2]=0x07;
  112.                 OutBuf[3]=0x00;
  113.                 OutBuf[4]=0x00;
  114.                 SendSPI(5);
  115.                
  116.                 OutBuf[0]=0xBC;
  117.                 SendSPI(5);
  118.                
  119.                 OutBuf[0]=0xA0;
  120.                 OutBuf[1]=0x00;
  121.                 OutBuf[2]=0x00;               
  122.                 SendSPI(5);
  123.                 Delay(10);
  124.                 //清除标志位,RDY
  125.        
  126.         //----EARSE               
  127.         OutBuf[0]=0x93;
  128.         OutBuf[1]=0x00;
  129.         OutBuf[2]=0x00;
  130.         OutBuf[3]=0x00;
  131.         OutBuf[4]=0x00;
  132.         SendSPI(5);
  133.         if(!CheckAck()) return FALSE;       
  134.         OutBuf[1]=0x40;
  135.         SendSPI(5);
  136.         if(!CheckAck()) return FALSE;       
  137.         Delay(255);Delay(255);Delay(255);Delay(255);
  138.         OutBuf[0]=0x91;
  139.         SendSPI(5);
  140.         if(!CheckAck()) return FALSE;       
  141.         OutBuf[1]=0x00;
  142.         SendSPI(5);
  143.         if(!CheckAck()) return FALSE;       
  144.         OutBuf[0]=0x80;
  145.         SendSPI(5);
  146.         if(!CheckAck()) return FALSE;       
  147.         Delay(255);//保险延时
  148.         return TRUE;
  149. }

  150. BOOL Prep_W8F08(BYTE Bank,BYTE Addr)
  151. {
  152.         /*MOSI 90 80 00 00 00
  153.         MISO AA AA AA 55 AA
  154.         MOSI 90 C0 00 00 00
  155.         MISO AA AA AA 55 AA*/
  156.         OutBuf[0]=0x90;
  157.         OutBuf[1]=0x80 | Addr;
  158.         OutBuf[2]=Bank;
  159.         OutBuf[3]=0x00;
  160.         OutBuf[4]=0x00;
  161.         SendSPI(5);
  162.         if(!CheckAck()) return FALSE;       
  163.         //OutBuf[0]=0x90;
  164.         OutBuf[1]=0xC0 | Addr;
  165.         SendSPI(5);
  166.         if(!CheckAck()) return FALSE;
  167.         return TRUE;       
  168. }

  169. BOOL Stop_W8F08(BYTE Bank,BYTE Addr)
  170. {
  171.         /*MOSI 90 80 00 00 00
  172.         MISO AA AA AA 55 AA
  173.         MOSI 90 C0 00 00 00
  174.         MISO AA AA AA 55 AA*/
  175.         OutBuf[0]=0x90;
  176.         OutBuf[1]=Addr | 0x40;
  177.         OutBuf[2]=Bank;
  178.         //OutBuf[3]=0x00;
  179.         //OutBuf[4]=0x00;
  180.         SendSPI(5);
  181.         if(!CheckAck()) return FALSE;       
  182.         //OutBuf[0]=0x90;
  183.         OutBuf[1]=Addr;
  184.         SendSPI(5);
  185.         if(!CheckAck()) return FALSE;
  186.         OutBuf[0]=0x80;
  187.         SendSPI(5);
  188.         if(!CheckAck()) return FALSE;
  189.         return TRUE;       
  190. }

  191. void Stop_R8F08()
  192. {
  193.         OutBuf[0]=0xA0;
  194.         OutBuf[1]=0x00;
  195.         OutBuf[2]=0x00;
  196.         OutBuf[3]=0x00;
  197.         OutBuf[4]=0x00;
  198.         SendSPI(5);
  199. }

  200. void Test()
  201. {
  202.         BYTE addr,page,cyc,test=0;
  203.         if(!Reset_Target()) return;
  204.        
  205.                 OutBuf[0]=0xE5;
  206.                 OutBuf[1]=0x53;
  207.                 OutBuf[2]=0x35;
  208.                 OutBuf[3]=0x5E;
  209.                 OutBuf[4]=0x00;
  210.                 SendSPI(5);
  211.                 SendSPI(5);
  212.                 //写8K
  213.         /*       
  214.                 if(!Erase_8F08()) return;
  215.                 Delay(100);
  216.                 for(page=0;page<=0x7F;page++)
  217.                 {//
  218.                         for(cyc=0;cyc<8;cyc++)
  219.                         {
  220.                                 addr=0;
  221.                                 if(!Prep_W8F08(page,cyc*4)) return;
  222.                                 for(;addr<4;addr++)
  223.                                 {
  224.                                         OutBuf[3]=test+1;
  225.                                         OutBuf[4]=test;
  226.                                         test+=2;
  227.                                         if(!Write_8F08(page,cyc*4+addr)) return;
  228.                                 }
  229.                                 addr--;
  230.                                 if(!Stop_W8F08(page,cyc*4+addr)) return;
  231.                                 Delay(255);
  232.                         }
  233.                         Delay(255);
  234.                 }
  235.                 Delay(255);
  236.                 */
  237.         Delay(255);Delay(255);Delay(255);Delay(255);
  238.         Delay(255);Delay(255);Delay(255);Delay(255);
  239.         Delay(255);Delay(255);Delay(255);Delay(255);
  240.         Delay(255);Delay(255);Delay(255);Delay(255);
  241.         Delay(255);Delay(255);Delay(255);Delay(255);

  242.         //读8K
  243.         for(page=0;page<=0x7F;page++)
  244.         {//
  245.                 for(cyc=0;cyc<8;cyc++)
  246.                 {
  247.                         addr=0;
  248.                         for(;addr<4;addr++)
  249.                         {
  250.                                 Read_8F08(page,cyc*4+addr);       
  251.                         }
  252.                         addr--;
  253.                         Stop_R8F08();
  254.                         Delay(255);
  255.                 }
  256.                 Delay(255);
  257.         }
  258.         Delay(255);
  259.        

  260. }

  261. //=============主函数,无返回值与输入值
  262. void main()
  263. {//主函数
  264.         //OutBuf[0]=0x00;
  265.         //OutBuf[1]=0xFF;
  266.         Test();
  267.         RESET=1;
  268.         SCLK=1;
  269.         MOSI=1;
  270.         /*SCLK=0;
  271.         MOSI=0;
  272.         MISO=1;
  273.         //Delay(255);
  274.         RESET=0;
  275.         Delay(255);
  276.         OutBuf[0]=0xE0;
  277.         OutBuf[1]=0x5A;
  278.         OutBuf[2]=0xA5;
  279.         OutBuf[3]=0xAA;
  280.         OutBuf[4]=0x00;
  281.         SendSPI(5);
  282.         RESET=1;
  283.         SCLK=1;
  284.         MOSI=1;*/
  285.         /*OutBuf[0]=0xE5;
  286.         OutBuf[1]=0x53;
  287.         OutBuf[2]=0x35;
  288.         OutBuf[3]=0x5E;
  289.         OutBuf[4]=0x00;*/
  290.         while(1)
  291.         {
  292.                 //SendSPI(5);
  293.                 //Delay(100);
  294.         }
  295. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2012-9-16 00:18:12 | 显示全部楼层
本帖最后由 xwkm 于 2012-9-16 08:23 编辑

LGT的SPI口不同于AT89S52的。在复位拉下前SCLK必须拉低,否则会被认为是脉冲上升沿导致数据错位。(谢谢bbsniua的提醒)
这个错误折腾了我整整一个下午。
这个数据包比较简单和规律。每5个BYTE一个帧。前面第一BYTE位命令。第二为地址。第三为页。第四第五是数据。注意第四第五这个WORD值其实是用Middle-Endian表示的INT值。
那么实际上MCU返回的0x55AA就是0xAA55。一样的。
至于如果熔丝加锁以后的解锁办法也简单。初始化后,单单执行earse即可。
判断加了密的芯片,看返回值,如果是0xBD即可证明是加密的。如果在清除状态时发现0xBD的返回可以直接PASS掉芯片不用继续读。因为继续读还是0xBD。
我刚开始的时候是以为在E5 53 35 5E以后直接发送擦除命令即可实现擦除的。没有想到返回值全是F,根本没有成功。
后来发现需要发送这几个命令,可能是清除状态的命令:
B8 3F 07 00 00/BC 3F 07 00 00/A0 00 00 00 00
接着就是擦除命令了。在程序中有。
然后写入的话,使用0x90,0x98这个命令。连续写4次(8BYTES)要停下来,接着重复四次,然后换页继续写。一共是0x80个页,一个页是0x20个WORD,也就是64B,即8K的闪存。
至于EEPROM的话就很简单了。在起始的0x10个页中,其实地址范围从0x00~0x2F,0x00~0x1F给整个用户的flash用。至于0x20~0x2F这个地址是给EEPROM的。

出0入0汤圆

 楼主| 发表于 2012-9-16 00:21:01 | 显示全部楼层
至于读命令,就是命令字段为0xB8和0xBC。记住一定要执行两次。
第一次的结果是错误的。有可能是设置内部寄存器的指令,第二条才是真正读。
然后读出的2bytes还是middle-endian的。需要swap。并且每读8bytes(4次)要用0xA0命令停一下,然后继续往后读。
可以在读AP的时候顺带把EEP也读出来。

出0入0汤圆

 楼主| 发表于 2012-9-16 00:23:33 | 显示全部楼层
在使用Makefile的时候,LDFLAGS一定要设置堆栈。否则可能出现爆掉的状况。
并且把mcu类型设置为atmega164p。这样gcc才不会报错
LDFLAGS = -Wl,--defsym=__stack=0x8002ff #LGT设置堆栈2FF
MACHINE= atmega164p

出0入0汤圆

 楼主| 发表于 2012-9-16 00:37:20 | 显示全部楼层
至少对于LGT8F08A,如果能够长期供货保持如此低的价格的话。入门的门槛是很低的。
只要一块能写入程序的无论什么单片机,甚至有DTR和RTS的串口/EPP并口,就可以用来编程LGT。
找一块洞洞板废料,飞一点线就可以在面包板上做实验了。还是比较方便的。
因为这个最小系统只需要一个单片机和一个电容(甚至也可以不要)就可以了。
不过我强烈建议官方别在新的LGT上去掉ISP功能。第一会导致批量写入程序的麻烦。
第二就是,SWD协议远远比SPI复杂的多。一般的单片机模拟会有一些问题。
这样就会显著的提升入门的门槛。我认为这不是好事情。
另外就是LGT的IO口可以 直接和有弱上拉的5V IO连接,无需电平转换。

出0入0汤圆

发表于 2012-9-16 00:43:56 | 显示全部楼层
lz是高中生呢,好厉害了。

出0入0汤圆

发表于 2012-9-16 01:09:44 | 显示全部楼层
值得肯定的,很有潜力的牛人!

出0入0汤圆

 楼主| 发表于 2012-9-16 09:49:56 | 显示全部楼层
本帖最后由 xwkm 于 2012-9-16 10:14 编辑

FUSE->OSCCAL 已经找出:
读出FUSE的命令是:
B8 3C 07 00 00 BC 3C 07 00 00
返回的第二个字节即为OSCCAL值!

出0入0汤圆

 楼主| 发表于 2012-9-16 09:55:36 | 显示全部楼层
熔丝使能应该是在楼上第一个字节的低四位。

出0入0汤圆

发表于 2012-9-16 13:48:03 | 显示全部楼层
  1.         Delay(255);Delay(255);Delay(255);Delay(255);
  2.         Delay(255);Delay(255);Delay(255);Delay(255);
  3.         Delay(255);Delay(255);Delay(255);Delay(255);
  4.         Delay(255);Delay(255);Delay(255);Delay(255);
  5.         Delay(255);Delay(255);Delay(255);Delay(255);
复制代码


还不如弄多个delay_ms()函数算了!

出0入0汤圆

 楼主| 发表于 2012-9-16 16:06:02 | 显示全部楼层
chengzepeng 发表于 2012-9-16 13:48
还不如弄多个delay_ms()函数算了!

这个仅仅是测试代码

出0入0汤圆

发表于 2012-9-16 19:40:57 | 显示全部楼层
C6 F0 72 A6 0C 55 AA 55        
C6 11000110 OSCCAL – RC 精调控制寄存器
7:保留
6:RPEST R/W 只在 14 脚和 8 脚封装时有效 当设置 PRESETN位为“1”时,复用复位功能的引脚使能复位功能。 当设置 PRESETN位为“0”时,复用复位功能的引脚禁止复位功能。(ISP软件-外部复位使能位)

5:0 RCCAL[5:0] 16MHz RC 精调控制位 (ISP软件-RC时钟校准配置)
55 AA 55
F0 熔丝位 (ISP软件-ISP/LOCK 使能位, 熔丝配置使能位)
-FF 11111111 默认 ISP/LOCK 使能位 解锁 熔丝配置使能位 禁用
-F0 11110000 熔丝配置使能位 启用
72 A6 0C 55 GUID 十六进制0x550CA672
AA 55 未使用

出0入0汤圆

发表于 2012-9-16 19:43:12 | 显示全部楼层
要是5v弱上拉能兼容就可以试试手里的1602了

出0入0汤圆

发表于 2012-9-17 20:57:31 | 显示全部楼层
强大的代码,大家原来都睡那么晚

出0入0汤圆

发表于 2012-9-17 21:04:26 | 显示全部楼层
顶         

出0入0汤圆

发表于 2012-9-18 10:10:51 | 显示全部楼层
lz是高中生? 功力不错了。我高中的时候只能玩z80

出0入0汤圆

 楼主| 发表于 2012-9-22 14:37:24 | 显示全部楼层
goodcode 发表于 2012-9-16 19:43
要是5v弱上拉能兼容就可以试试手里的1602了


我试过直接接12232和1602,暂时没问题。
反正我现在直接用STC的上拉链接一点事都木有。

出0入0汤圆

发表于 2013-5-10 21:36:53 来自手机 | 显示全部楼层
佩服  佩服  牛人
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 12:13

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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