4114|2

1377

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

[十月DIY]我的ARM学习机 [复制链接]

本帖最后由 cruelfox 于 2015-10-31 21:37 编辑

  我对底层的东西特别感兴趣。十多年前有了自己的电脑,一直保留DOS用了好些年。喜欢汇编,讨厌Java。接触的第一个单片机是AT89S52,下程序是用串口CTS/RTS以及DSR/DTR控制线来模拟SPI,在DOS下把时钟中断调到几十kHz来定时确定时序。后来就用89S52做成了2051的编程器,再后来用2051做了串口转SPI下载器玩起AVR了,玩过最多的还是AVR.
  不过51、AVR这类Harvard结构MCU不能干的事情是自己Load程序来运行,只能从ROM执行啊(51可以有办法映射,但是51学习机计划没有实施)。我小时候听说过“中华学习机”,不同于小霸王学习机那样ROM固化死了的,人家是从软盘装载程序的。家里头的旧杂志上介绍过TD-I型8031的学习机,是用开关来二进制编程RAM然后执行的,倘若放到今天……
  我生活的时代已经不是穿孔纸带了,DIY还是玩现代的东西吧。言归正传,我的第一个“学习机”作品是ARM7TDMI的,尽管这个核已经早过时了。我选择了NXP的LPC2220作为处理器,它自带64kB的RAM,在单片机中算是大的了。核心比较简单,作为学习机适宜,而且有外部总线,比较方便扩展RAM,类似PC那样来玩。这个PCB做得比较早了,搁置没玩起来(手头没时间玩的板子多了,这是另外的问题),上面除了MCU还有一块16bit*256k的SRAM,一片8bit*128k的NOR Flash ROM,预留16-bit总线插针扩展,具备一个计算机的配置了(除了缺少DMA支持)。下面是线路图:
  PCB的顶层图

 PCB的底层:

  作为MCU自带的外设是可以引出来的,所以UART, SPI, I2C基本I/O通信用分组接到插针,再另外放了16个GPIO在一侧。核心部分先焊上就可以玩了。





  上面介绍的是硬件部分。LPC2220是为数不多的ROMless单片机,里面没有Flash哦,OTP也没有。这也是我选择它的原因,作为学习机不是做任何应用的原型板,烧写Flash尽量避免吧。虽然Flash的烧写次数已经够多了,能省一事算一事。NXP的ARM7 (LPC21xx系列)有个特点是可以从PC直接ISP下载到RAM,然后运行。我在第一次玩ARM (LPC2103)的时候发现Flash工具有这个功能。
  读NXP的手册,发现Bootloader是使用串口命令进行交互的,命令也不复杂。

  所以,只要连接MCU的UART0到PC的串口,上电或者复位就进入Bootloader里面的ISP程序(因为没有可执行的ROM嘛),就可以从PC把代码直接下载到ROM然后运行了。64kB的SRAM哦,可以实现不少东西了吧。
  当然,用NXP官方的FlashMagic来下载的效率太低了,不适应“学习机"要快速载入程序的要求。所以我自己做一个程序:
  1. #include<windows.h>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<stdlib.h>

  5. HANDLE dev;
  6. OVERLAPPED oWR = {0}, oRD={0};

  7. void errexit(char *s)
  8. {
  9.   fprintf(stderr,"%s",s);
  10.   exit(1);
  11. }

  12. struct ROM
  13. {
  14.   unsigned char b;
  15.   char oc;
  16. };


  17. int readcomm(unsigned char *buf, int maxlen, int timeout);
  18. int writecomm(unsigned char *buf, int len);

  19. int loadhexfile(char *fn,int szlimit,int *poff,struct ROM *rom);
  20. int showbinary(int szlimit, struct ROM *rom);
  21. int uuencode(int szlimit, struct ROM *rom, char *buf, int slen, int linelen);
  22. int checksum(int szlimit, struct ROM *rom);

  23. main(int argc, char *argv[])
  24. {

  25.    DCB dcb;
  26.    int i,r;
  27.    
  28.    if(argc<2)
  29.    {
  30.        printf("Supply a HEX file name.\n");
  31.        return;
  32.    }
  33.    
  34.    dev=CreateFile("COM3", GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,  FILE_FLAG_OVERLAPPED,0);
  35.    if(dev==INVALID_HANDLE_VALUE)
  36.    {
  37.        printf("Cannot open COM3 port.\n");
  38.        exit(1);
  39.    }
  40.    FillMemory(&dcb, sizeof(dcb), 0);
  41.    dcb.DCBlength = sizeof(dcb);
  42.    BuildCommDCB("57600,n,8,1",&dcb);
  43.    if (!SetCommState(dev, &dcb))
  44.    {
  45.        printf("Cannot set port parameters.\n");
  46.        exit(1);
  47.    }
  48.    oWR.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  49.    oRD.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  50.    for(i=0;i<1000;i++)
  51.    {
  52.        int len0;
  53.        char c, buf[32];
  54.        char done=0;

  55.        writecomm("?",1);
  56.        r=readcomm(buf,4,20);
  57.        if(r>0)
  58.        {
  59.            int j;
  60.            for(j=0;j<r;j++)
  61.            {
  62.                printf("%c",buf[j]);
  63.                if(buf[j]=='S')
  64.                {
  65.                    r=readcomm(buf+r,14-(4-j),20);
  66.                    if(r==14-(4-j) && strncmp(buf+j,"Synchronized\r\n",14)==0)
  67.                    {
  68.                        printf("SYNC\n");
  69.                        writecomm("Synchronized\r\n",14);
  70.                        r=readcomm(buf,32,50);
  71.                        if(r==18 && strncmp(buf,"Synchronized\r\nOK\r\n",18)==0)
  72.                        {
  73.                            printf("Synchronization done\n");
  74.                            done=1;
  75.                            break;
  76.                        }
  77.                        else
  78.                            printf("(%d) %s",r,buf);
  79.                    }
  80.                }
  81.            }
  82.            if(done) break;
  83.        }
  84.        else
  85.        {
  86.            printf(".");
  87.            continue;
  88.        }
  89.    }

  90.    {
  91.        char c;
  92.        writecomm("11095\r\n",7);
  93.        while(readcomm(&c,1,10)>0)
  94.        {
  95.            printf("%c",c);
  96.        }
  97.    }

  98.    {
  99.        char c;
  100.        writecomm("J\r\n",3);
  101.        while(readcomm(&c,1,10)>0)
  102.        {
  103.            printf("%c",c);
  104.        }
  105.    }

  106.    {
  107.        unsigned int progaddr=0x40000200;
  108.        char c;
  109.        char str[128];
  110.        char buf[512];
  111.        int slen;
  112.        int pgsize;
  113.        struct ROM rom[1024];
  114.        int offset=-1;
  115.        pgsize=loadhexfile(argv[1],1024,&offset,rom);

  116.        printf("Program Size: %d bytes from %X\n", pgsize, offset);

  117.        showbinary(1024,rom);

  118.        sprintf(str,"W %d %d\r\n",progaddr, pgsize);
  119.        slen=strlen(str);
  120.        writecomm(str,slen);
  121.        while(readcomm(&c,1,10)>0)
  122.        {
  123.            printf("%c",c);
  124.        }

  125.        slen=uuencode(1024, rom, buf, 512, 61);
  126.        writecomm(buf,slen);
  127.        sprintf(str,"%d\r\n",checksum(1024,rom));
  128.        slen=strlen(str);
  129.        writecomm(str,slen);

  130.        while(readcomm(&c,1,10)>0)
  131.        {
  132.            printf("%c",c);
  133.        }

  134.        writecomm("U 23130\r\n",9);
  135.        while(readcomm(&c,1,10)>0)
  136.        {
  137.            printf("%c",c);
  138.        }

  139.        sprintf(str,"G %d T\r\n",progaddr);

  140.        slen=strlen(str);
  141.        writecomm(str,slen);
  142.        while(readcomm(&c,1,10)>0)
  143.        {
  144.            printf("%c",c);
  145.        }

  146.    }

  147.    CloseHandle(oWR.hEvent);
  148.    CloseHandle(oRD.hEvent);
  149.    CloseHandle(dev);

  150. }



  151. int writecomm(unsigned char *buf, int len)
  152. {
  153.    int r;
  154.    int len0;

  155.    r=WriteFile(dev,buf,len,&len0, &oWR);
  156.    if(r==0)
  157.    {
  158.        if(GetLastError()!=ERROR_IO_PENDING)
  159.        {
  160.            printf("COM port access error!\n");
  161.            exit(1);
  162.        }
  163.        GetOverlappedResult(dev, &oWR, &len0, TRUE);
  164.    }
  165.    return len0;

  166. }


  167. int readcomm(unsigned char *buf, int maxlen, int tmout)
  168. {

  169.     static unsigned wait=0;
  170.     static unsigned char ch;
  171.     int i, len0, r;
  172.     if(tmout<=0)
  173.         return 0;

  174.     for(i=0;i<maxlen;i++)
  175.     {
  176.         if(!wait)
  177.         {
  178.             if(ReadFile(dev,&ch,1,&len0, &oRD))
  179.             {
  180.                 wait=0;
  181.                 buf[i]=ch;
  182.                 continue;
  183.             }
  184.             if(GetLastError()!=ERROR_IO_PENDING)
  185.             {
  186.                 printf("Read COM port error!\n");
  187.                 exit(1);
  188.             }
  189.         }
  190.         r=WaitForSingleObject(oRD.hEvent,1);
  191.         if(r==WAIT_TIMEOUT)
  192.         {
  193.             wait=1;
  194.             tmout--;
  195.             if(tmout==0)
  196.                 return i;
  197.             else
  198.             {
  199.                 i--;
  200.                 continue;  
  201.             }
  202.         }
  203.         if(r==WAIT_OBJECT_0)
  204.         {
  205.             wait=0;
  206.             buf[i]=ch;
  207.             continue;
  208.         }
  209.     }
  210.     return i;
  211. }



  212. int loadhexfile(char *fn,int szlimit,int *poff,struct ROM *rom)
  213. {
  214.     int i,j,n,count,addr,waddr,bsz;
  215.     char line[512];
  216.     unsigned char bb,sum,hex[256];
  217.     FILE *fp;

  218.     memset(rom,0,sizeof(struct ROM)*szlimit);

  219.     fp=fopen(fn,"r");
  220.     if(fp==NULL)
  221.     {
  222.         printf("Cannot open HEX file %s\n",fn);
  223.         return 0;
  224.     }
  225.     printf("Opening file %s for reading... ",fn);

  226.     count=0;
  227.     sum=0;
  228.     for(n=1;;n++)
  229.     {
  230.         if(!fgets(line,512,fp))
  231.             errexit("read error\n");
  232.         if(line[0]!=':')
  233.             errexit("FORMAT ERROR\n");
  234.         j=0;
  235.         for(i=1;;i+=2)  // convert ASCII to binary
  236.         {
  237.             switch(line[i])
  238.             {
  239.                 case 'A':  bb=0xa0;  break;
  240.                 case 'B':  bb=0xb0;  break;
  241.                 case 'C':  bb=0xc0;  break;
  242.                 case 'D':  bb=0xd0;  break;
  243.                 case 'E':  bb=0xe0;  break;
  244.                 case 'F':  bb=0xf0;  break;
  245.                 case '\0':  case '\r':  case '\n': bb=0x77;  break;
  246.                 default:  if(line[i]>='0' && line[i]<='9')
  247.                               bb=(line[i]-'0')<<4;
  248.                           else
  249.                               bb=0xff;
  250.             }
  251.             if(bb==0x77)
  252.                 break;
  253.             if(bb==0xff)
  254.                 errexit("INVALID CHARACTER\n");
  255.             switch(line[i+1])
  256.             {
  257.                 case 'A':  bb+=0xa;  break;
  258.                 case 'B':  bb+=0xb;  break;
  259.                 case 'C':  bb+=0xc;  break;
  260.                 case 'D':  bb+=0xd;  break;
  261.                 case 'E':  bb+=0xe;  break;
  262.                 case 'F':  bb+=0xf;  break;
  263.                 default:  if(line[i+1]>='0' && line[i+1]<='9')
  264.                               bb+=(line[i+1]-'0');
  265.                           else
  266.                               errexit("BAD BYTE\n");
  267.             }
  268.             sum+=bb;
  269.             hex[j]=bb;
  270.             j++;
  271.         } // converted ASCII to binary
  272.         if(sum!=0)
  273.             errexit("CHECKSUM ERROR\n");
  274.         if(j<5)
  275.             errexit("LINE TOO SHORT\n");
  276.         if(hex[0]!=j-5)
  277.             errexit("FORMAT ERROR\n");
  278.         bsz=j-5;
  279.         switch(hex[3])
  280.         {
  281.             case 0:   addr=hex[1];   addr<<=8;  addr+=hex[2];
  282.                       if(*poff==-1)
  283.                       {
  284.                           *poff=addr;
  285.                       }
  286.                       for(i=0;i<bsz;i++)
  287.                       {
  288.                           int waddr=addr-(*poff);
  289.                           if(waddr>szlimit)
  290.                           {
  291.                               printf("address %X beyond range (base %X) \n",addr, *poff);
  292.                           }
  293.                           else
  294.                           {
  295.                              rom[waddr].b=hex[4+i];
  296.                              rom[waddr].oc=1;
  297.                           }
  298.                           addr++;
  299.                           count++;
  300.                       }
  301.                       break;
  302.             case 1:   if(j!=5)
  303.                           errexit("UNEXPECTED END\n");
  304.                       fclose(fp);
  305.                       return count;
  306.             case 2:   if(hex[1]!=0 || hex[2]!=0 || hex[4]!=0 || hex[5]!=0)
  307.                           printf("UNSUPPORTED PARAGRAPH\n");
  308.                       break;
  309.             case 3:
  310.             default:  printf("UNSUPPORTED RECODE TYPE (%X)\n", hex[3]); break;
  311.         }
  312.     }
  313. }


  314. int showbinary(int szlimit, struct ROM *rom)
  315. {
  316.     int i;
  317.     for(i=0;i<szlimit;)
  318.     {
  319.         int j;
  320.         char blank=1;

  321.         for(j=0;j<16;j++)
  322.         {
  323.             if(rom[i+j].oc)
  324.             {
  325.                 blank=0;
  326.                 break;
  327.             }
  328.         }
  329.         if(blank)
  330.         {
  331.             i+=16;
  332.             continue;
  333.         }

  334.         printf("%04X: ",i);
  335.         for(j=0;j<16;j++)
  336.         {
  337.             if(rom[i+j].oc)
  338.                 printf("%02X",rom[i+j].b);
  339.             else
  340.                 printf("..");
  341.             if(j==7)
  342.                 printf(" - ");
  343.             else
  344.                 printf(" ");
  345.         }
  346.         printf(" | ");
  347.         for(j=0;j<16;j++)
  348.         {
  349.             if(rom[i+j].oc)
  350.             {
  351.                 if(rom[i+j].b>=0x20 && rom[i+j].b<=0x7f)
  352.                     printf("%c",rom[i+j].b);
  353.                 else
  354.                     printf("?");
  355.             }
  356.             else
  357.                 printf(".");
  358.         }

  359.         i+=16;
  360.         printf("\n");

  361.     }
  362. }


  363. int uuencode(int szlimit, struct ROM *rom, char *buf, int slen, int linelen)
  364. {
  365.     int i, sz=0,mem;
  366.     int lmax, lc, brem;
  367.     int index=0;
  368.     for(i=0;i<szlimit;i++)
  369.     {
  370.         if(rom[i].oc)
  371.             sz=i+1;
  372.     }
  373.     lmax=((linelen-1)/4)*3;
  374.     lc=sz/lmax;
  375.     brem=sz%lmax;
  376.     mem=lc*(((linelen-1)/4)*4+3)+3+(brem/3*4)+(brem%3+1);  // include CR LF
  377.     if(mem>=slen)
  378.     {
  379.         printf("UUEncode: buffer too small! need %d bytes\n",mem);
  380.         return 0;
  381.     }

  382.     for(i=0;i<sz;)
  383.     {
  384.         int j, len;
  385.         char r=0;
  386.         unsigned char b, a=0;

  387.         if(i+lmax<sz)
  388.             len=lmax;
  389.         else
  390.             len=brem;
  391.         buf[index++]=0x20+len;
  392.         for(j=0;j<len;j++)
  393.         {
  394.             if(rom[i+j].oc)
  395.                 b=rom[i+j].b;
  396.             else
  397.                 b=0xff;
  398.             a|=(b>>(2+r));
  399.             if(a) buf[index++]=0x20+a; else buf[index++]='`';
  400.             r+=2;
  401.             a=((b&((1<<r)-1))<<(6-r));
  402.             if(r==6)
  403.             {
  404.                 if(a) buf[index++]=0x20+a; else buf[index++]='`';
  405.                 r=0;
  406.                 a=0;
  407.             }
  408.         }
  409.         if(r!=0)
  410.         {
  411.             if(a) buf[index++]=0x20+a; else buf[index++]='`';
  412.         }
  413.         i+=lmax;
  414.         buf[index++]='\r';
  415.         buf[index++]='\n';

  416.     }

  417.     printf("MEM %d, actual %d\n",mem,index);
  418.     return index;
  419. }


  420. int checksum(int szlimit, struct ROM *rom)
  421. {
  422.     int i, sz, sum;
  423.     sz=0;
  424.     for(i=0;i<szlimit;i++)
  425.     {
  426.         if(rom[i].oc)
  427.             sz=i+1;
  428.     }
  429.     sum=0;
  430.     for(i=0;i<sz;i++)
  431.         sum+=rom[i].b;
  432.     return sum;
  433. }
复制代码

  这个程序做的工作是打开串口, 和单片机Bootloader ISP命令同步,然后读取指定的HEX文件,下载到LPC2220的RAM地址 0x40000200, 再解除锁定,最后发送执行程序的命令,单片机从 0x40000200 开始运行。如果要重新下载程序,把单片机Reset了,再运行以上的程序即可。命令行一步搞定,容易吧!

  注: LPC2220的RAM地址从 0x40000000 开始,但是BootLoader会用一部分RAM,所以为了避免冲突,程序下载从RAM的512字节之后起。NXP的Bootloader是用UUEncode编码传输二进制数据的,上面的程序包含编码的子程序。这个程序也写得不完善,还有比如代码长度检查都没有做进去,目前做到的只是能下载一小段并执行。

最新回复

点个赞。。。。  详情 回复 发表于 2015-11-1 09:45
点赞 关注
 

回复
举报

3416

帖子

0

TA的资源

纯净的硅(高级)

沙发
 
蛮好玩的样子
展示一下呀
个人签名

So TM what......?

 

 

回复

1891

帖子

2

TA的资源

纯净的硅(中级)

板凳
 
点个赞。。。。
个人签名
分享铸就美好未来。。。




 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表