0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在DS80C400应用中使用SDCC编译器

星星科技指导员 来源:ADI 作者:ADI 2023-06-16 17:32 次阅读

介绍

DS80C400包含一个提供网络栈、内存管理和进程调度的ROM,可以灵活地用于由Java、C和8051汇编编程的应用中。SDCC为8051器件提供了一个免费、开放源码的编译器,并兼容DS80C400的24位寻址模式。用C编写的复杂应用程序在Dallas Semiconductor提供的库的帮助下,可以很容易地使用DS80C400 ROM功能创建。

本应用笔记阐述了如何使用SDCC工具来创建DS80C400应用程序。从一个HelloWorld应用程序开始,然后说明如何使用ROM库来实现一个简单的HTTP服务器。这里的应用程序是针对TINIm400参考模块编写和创建的,用于具有其它存储器配置的设计时必须进行相应修改。

从SDCC编译器开始

遵循以下步骤,使用SDCC编译器来完成您的第一个DS80C400的C应用程序:

  1. 安装SDCC编译器¹

    • 从SDCC网站上下载最新版本SDCC编译器的安装文件。
    • 遵循安装文件的指示(可能是sdcc/doc/INSTALL.txt)。
  2. 使用你喜欢的文本编辑器创建一个新文件"main.c"。在文件中写入以下代码:

    #include < stdio.h >
    void main ()
    {
    	printf("Hello Universe!!!!....Welcome to SDCC Tini Test Program");
    
    			while (1)
    			{
    }
    		}
    

    一定要保存文件内容。

  3. 从SDCC C库站点²中拷贝文件startup400.a51和reg400.inc (包含在启动代码下载中),并保存到您保存main.c文件的目录中。此文件包含startup_code函数,将在应用程序启动时调用该函数,从而对DS80C400芯片进行初始化。启动代码完成以下工作:

    • 将DS80C400配置成24位连续地址模式
    • 配置定时器2用来为串口产生115200的波特率
    • 初始化数据存储器
  4. 从SDCC C库站点拷贝ROM initialization库文件(从init库文件下载的rominit.lib和rom400.h),并将其解压缩至相同目录下。库文件是压缩的,使用WinZip或gunzip/tar解压缩包。

  5. 在编译我们的"Hello Universe"应用程序之前,我们需要在一个SDCC安装的支持文件中作一个小改动,覆盖缺省的DS80C400支持函数并使用Dallas Semiconductor的C库代替。进行以下改动:

    • 将\\SDCC\\lib\\ds400\\libds400.lib文件重命名为\\SDCC\\lib\\ds400\\libds400.lib.old
    • 建立一个名为\\SDCC\\lib\\ds400\\libds400.lib的空文件(使用touch命令或在您喜欢的文本编辑器中建立一个新文件)
  6. 构建"Hello Universe"应用程序...

    • 要由我们的startup400.a51文件创建一个目标文件(.rel),在命令行执行以下命令:

      asx8051 -losffgp startup400.a51
      

      asx8051是SDCC工具提供的汇编器。汇编器提供的参数选项有:| Option | Purpose |

      | -------- | ----------------------------------------------------- |

      | l | generates a list file |

      | o | generates an object file |

      | s | generates a symbol file |

      | ff | flag reolcatable references by mode in listing file |

      | g | make undefined symbols be global |

      | p | disables listing pagination |

      "los"参数是必须的,因为连接器需要列表、目标和符号文件来生成可执行文件。"ff"和"p"参数生成一个可读的列表文件。"g"参数通知汇编器在发现一个没有定义的符号且该符号未声明为外部变量时不报错。

    • 为了由main.c生成一个目标文件,执行以下命令:

      sdcc -c -mds400 --model-flat24 --stack-10bit --no-xinit-opt main.c
      

      sdcc为编译器。

      传递给编译器的参数选项为:

      Option Purpose
      -c compiles main.c and creates an object file
      -mds400 generates code for the DS80C400 processor
      --model-flat24 use the 24-bit contiguous memory model
      --stack-10bit use the 1024-byte extended stack (10 bit stack addresses)
      --no-xinit-opt don't initialize the external RAM memory area
      p disables listing pagination

      注意列表中最后三个参数是双破折号。

    • 为了连接目标文件并构建可执行文件,执行以下命令:

      sdcc -mds400 --model-flat24 --stack-10bit -Wl-r --xram-loc
      0x10000 --xram-size 0x3fff --code-loc 0x400000 main.rel startup400.rel -l
      rominit.lib
      

      这里使用的新参数为:| Option | Purpose |

      | ------------- | -------------------------------------------------------------- |

      | -WI | pass options through to the linker |

      | --xram-loc | external RAM start address (only RAM for SDCC variable use!) |

      | --xram-size | external RAM size (only RAM for SDCC variable use!) |

      | --code-loc | code starting address |

      | -l | include the specified libraries |

      | p | disables listing pagination |

      请注意xram-loc、 xram-size和code-loc参数为双破折号。也要注意给命令指定的RAM将会用来存储SDCC变量,不应该和init_rom函数中用来初始化DS80C400所使用的存储器范围冲突―此存储器用作网络栈和存储器管理。

    • 为了压缩可执行文件并生成一个十六进制文件,执行以下命令:

      packihx main.ihx>hellouniverse.hex

      packihx命令通过将连续数据记录累积至16个字节来压缩可执行文件。

有了一个可执行文件后,我们需要将应用程序下载到TINIm400模块中并运行它。### 将示例应用程序加载到TINIm400模块

本节说明如何使用Maxim/Dallas Semiconductor提供的 微控制器工具包(MTK) 向TINIm400验证模块中加载由SDCC编译器生成的十六进制文件。目前可用的MTK版本只支持Windows®。

如果您的开发环境不是Windows,需要使用JavaKit应用程序来下载和执行应用程序。要使用JavaKit,您必须有Java运行环境³ (版本至少为1.2)并且安装Java Communications API ^4^ 。JavaKit工具包含在TINI软件开发包中。写本文的时候,发布的最新固件是固件版本1.13。运行JavaKit的指导说明可以在TINI SDK docs目录下的Running_JavaKit.txt文件中找到。如果您在运行MTK或JavaKit时遇到技术问题,可能其他人已经遇到过类似问题并且已经发表在Dallas Semiconductor的讨论区中。

最新版本的MTK应用软件可下载。要安装MTK,请运行安装文件并遵照提示操作。成功安装后,会增加一个新的菜单项: Start->All Programs->Dallas Semiconductor MTK。 MTK启动后,会出现图1所示的对话框。

图1. 启动时MTK选项

图1. 启动时MTK选项

选择选项TINI,以操作TINIm400评估板。

选择了TINI之后,会打开MTK主窗口。从Options->Configure Serial Port菜单选项中选择您将用来和TINIm400通讯的串口。然后,选择Tini->Tini Options菜单项,就会出现下面的对话框。选择DSTINIm400按钮,配置MTK用于和TINIm400板通讯。图2显示了带有DSTINIm400按钮的对话框。

图2. 选择TINIm400配置选项

图2. 选择TINIm400配置选项

选择Tini->Open COMx at xxx baud菜单选项打开串口。接着选择Tini->Reset选项复位评估板。会出现DS80C400的加载提示:

DS80C400 Silicon Software - Copyright (C) 2002 Maxim Integrated
Detailed product information available at http://www.maximintegrated.com

Welcome to the TINI DS80C400 Auto Boot Loader 1.0.1
>

从文件菜单中选择Load HEX File。找到我们刚刚生成的hellouniverse.hex文件并选中。一旦您的程序加载后有两种方法运行它。因为我们将程序加载到40区,您可以输入:

> B40 
 > X

要选择40区并运行那里的代码。您也可以输入:

> E

这会使ROM查找可执行的代码。它查找一个标识当前区具有可执行代码的特定标签。此标签由文本'TINI'组成,其后面紧跟着当前区的号码(或零),并位于当前区的0002h地址。SDCC编译器在生成的汇编代码中插入此标签。如果打开为hellouniverse工程生成的main.asm源代码,您会找到下面的代码段:

.area CSEG    (CODE)
interrupt_vect:
   ; DS80C400 IVT must be generated at runtime.
	sjmp	__sdcc_400boot
	.ascii	'TINI'	; required signature for 400 boot loader.
	.db	0	; selected bank or zero...
__sdcc_400boot:
	ljmp	__sdcc_gsinit_startup

注意sjmp__sdcc_400boot语句位于40区的0000h地址。其后跟随可执行标签{ 'T', 'I', 'N', 'I', 0h},由于simp语句为两个字节,因此该标签位于地址0002处。当您键入'E'时,ROM从C0h区开始向下搜索可执行代码。如果您键入'E'时,执行了其它的代码,则意味着ROM在一个比您的代码加载位置400000h更高的地址找到了一个可执行标签。您可能需要找到此标签的位置,并删除那个区的内容。### 和ROM以及SDCC ROM库接口

在高速微控制器用户指南DS80C400补充资料中说明了在汇编语言中调用ROM函数的过程。但是,在C中调用这些ROM函数会复杂一些。必须将参数从SDCC C编译器的规则转换成ROM使用的规则。SDCC编译器通过硬件堆栈、累加器和数据指针相结合的方式来传递参数。ROM函数采用许多不同的方式来接受参数。例如,socket函数接收存储在一个外部RAM缓冲区中的参数。相反地,许多功能函数接收由特殊功能寄存器或直接存储器位置传递的参数。为了从SDCC调用方式转换成ROM参数方式,Dallas Semiconductor已经编写了访问ROM函数的库。

在您的C程序中使用ROM函数只需包含一个头文件并与相应的库文件连接即可。用于SDCC编译器的ROM库包括:

  • ROM初始化程序
  • DHCP客户端
  • 进程调度
  • Sockets (TCP、UDP和Multicast)
  • TFTP客户端
  • 功能函数(CRC16, 随机数)

在写本文时,还没有为SDCC编译器提供包括如文件系统、邮件客户端和HTTP服务器之类的扩展库。请关注SDCC库主页上的DS80C400升级信息,我们会添加支持SDCC的库。### 简单应用:HTTP服务器

编写了一个简单的http服务器来说明如何使用一些ROM库函数,特别是socket和进程调度库。这个示例会偶尔通过网络时间服务器更新它的时间,并且通过它的web服务器提供这个信息。

示例应用程序由两个模块组成,一个HTTP服务器和SNTP客户端。主程序生成一个新的子任务来运行http服务器,用于处理80端口上的客户连接。父任务每60秒会试图通过时间服务器同步当前时间。

SNTP客户端模块

以下代码段实现SNTP客户端模块的核心功能。

socket_handle = socket(0, SOCKET_TYPE_DATAGRAM, 0);

// set a timeout of about 2 seconds
for (i=0;i< 256;i++)
    buffer[i] = 0;
buffer[0] = 0x0;
buffer[1] = 0x0;
buffer[2] = 0x8;
buffer[3] = 0x0;
setsockopt(socket_handle, 0, SO_TIMEOUT, buffer, 200);

buffer[2] = 0;       //reset since we used this in call to setsockopt
buffer[0] = 0x23;    // No warning/NTP Ver 4/Client

address.sin_addr[12] = TIME_NIST_GOV_IP_MSB;
address.sin_addr[13] = TIME_NIST_GOV_IP_2;
address.sin_addr[14] = TIME_NIST_GOV_IP_3;
address.sin_addr[15] = TIME_NIST_GOV_IP_LSB;
address.sin_port_high = (NTP_PORT/0x100); //higher byte of port number
address.sin_port_low = (NTP_PORT%0x100); //lower byte of port number

sendto(socket_handle, buffer, 48, 0, &address, sizeof(struct sockaddr));
recvfrom(socket_handle, buffer, 256, 0, &address, sizeof(struct sockaddr));

//SDCC uses little Endian for storing data, so reorganize the data before converting it to long
buffer[0]=buffer[43];
buffer[1]=buffer[42];
buffer[2]=buffer[41];
buffer[3]=buffer[40];

timeStamp = *(unsigned long *)(&buffer[0]);

formatTimeString(timestamp - (5 * SECONDS_PER_HOUR), "Tampa, USA",
                 last_time_reading_1);
formatTimeString(timeStamp - (3 * SECONDS_PER_HOUR), "Sao Paulo, Brazil",
                 last_time_reading_2);
formatTimeString(timeStamp + (1 * SECONDS_PER_HOUR),"Marseille, France",
                 last_time_reading_3);
formatTimeString(timeStamp + (5 * SECONDS_PER_HOUR) + (30 *
                 SECONDS_PER_MINUTE), "Bangalore, India",
                 last_time_reading_4);
formatTimeString(timeStamp +  (8 * SECONDS_PER_HOUR), "Hsinchu, Taiwan",
                 last_time_reading_5);
last_reading_seconds = getTimeSeconds();
closesocket(socket_handle);

SNTP客户端模块同样是通过RFC 1361实现的。SNTP模块通过使用UDP协议和time.nist.gov通讯,并请求一个时间戳。需注意编写这个应用笔记时还不提供SDCC编译器的DNS支持,因此time.nist.gov的IP地址是手工设定的。

首先,创建一个数据包socket并分配一个大约2秒(0x800==2048 milliseconds)的超时。这样会保证如果和我们选择的服务器通讯失败,我们不会无休止地等待响应。

接下来的一行用来设置请求的参数。在RFC 1361的第3节对这些位进行了说明。值0x23在一个跳秒时不要求产生警告,要求使用版本4的NTP,并声明模式为"Client"。我们使用普通数据包函数sendto和recvfrom发送请求和接收响应之后,将时间戳数值的秒部分赋予变量timeStamp,然后调整至参考日期1970年1月1日。用函数formatTimeString将时间戳转换成一个可读的字符串,比如说"In Marseille, France it is 9:37:37 on September 3, 2000。"

用getTimeSeconds函数来确定基于DS80C400内部时钟的最后一次更新的时间。由于程序只是大约每60秒更新一次,HTML网页time.html将会使用这一数值来报告上一次时间更新后已经过了多长时间。最后,socket关闭并且SNTP客户端进入另一个60秒的休眠期。

简易的HTTP服务器

这个时间服务器应用程序的另一个子模块为一个web服务器。此应用程序中的服务器实现了一个RFC 2068中描述的HTTP服务器简易版本。只支持"GET"方法--忽略输入包头,并且几乎不给出输出包头。当编写这个应用笔记时尚未提供文件系统库,因此示例应用程序动态地生成HTML页面。

通过调用Berkley-style socket函数来创建服务器soket。这使得建立一个服务器socket十分容易。下面的代码给出了我们的简易HTTP服务器如何创建、绑定和接收新的连接。

struct sockaddr local;
unsigned int socket_handle, new_socket_handle, temp;

socket_handle = socket(0, SOCKET_TYPE_STREAM, 0);
local.sin_port = 80;
bind(socket_handle, &local, sizeof(local));
listen(socket_handle, 5);

printf("Ready to accept HTTP connections...\\r
");

// here is the main loop of the HTTP server
while (1)
{
    new_socket_handle = accept(socket_handle, &address, sizeof(address));
    handleRequest(new_socket_handle);
    closesocket(new_socket_handle);
}

要注意当接收一个新的socket时,这个简易应用程序不会启动一个新的线程或进程来对请求进行处理,而是在同一进程中处理请求。任何优于演示品质的HTTP服务器都会在一个新的线程中处理到来的请求,允许同时发生多个连接并能进行处理。请求处理完毕后我们关闭socket并等待下一个到来的连接。

HandleRequest方法从接入的请求中解析出文件名并且检查验证请求方法为'GET'。不允许使用其它的方法(即使是'POST'、 'HEAD'或'OPTIONS')。

为SDCC编译器编写DS80C400汇编函数的注意事项

虽然SDCC提供了丰富的库函数集合,但是有时我们会想用汇编语言编写优化的模块,或将现有的8051汇编模块移植到我们的应用程序中。若8051汇编语言函数由SDCC编译器编写的C程序来调用时,在编写这些汇编函数时需切记以下要点:

  1. 函数参变量传递约定:下表说明了重入函数的变量传递方式

    Argument position Character Integer Long Address
    First argument Dpl Dph:dpl B:dpx:dph:dpl B:dpx:dph:dpl
    Second argument onwards the values will be passed through hardware stack from right to left

    函数void sample_func(long x, long y,int z) reentrant;的参数传递如下:

  2. 数据类型存储规则:

    SDCC遵循低字节在前(Little Endian)的存储规则。换句话说,SDCC使用最低有效字节在前的二进制数据存储格式。
    例如,一个32位长的数值0xDEADBEEF将会按如下方式存储:

  3. 地址指针大小

    SDCC使用四个字节来保存存储器地址。下表给出了存储器地址的格式:

    Most significant byte 3^rd^ byte 2^nd^ Byte Least significant byte
    address type (possible values for ds80c400: 0-near, 1-far, 2-code) MSB of address 2^nd^ byte of address LSB of address

    近距离地址指针使用间接寻址、内部RAM存储器(idata)来进行存储,并且其地址大小只有一个字节。原地址的高16位不用。

    远距离地址指针用于访问外部存储器,为24位。

    有关SDCC ASx8051汇编器的更多信息,请参考ASxxxx assembler reference manual (ASxxxx汇编器参考手册)。所有SDCC文档可以从http://sdcc.sourceforge.net/snap.php#Docs/处下载。

局限性以及开发问题

以下是我们使用4.0版本的SDCC编译器时发现的局限性:

  1. 编译器不支持递归函数
  2. 库程序未优化
  3. 编译器不支持宏指令
  4. 像printf和sprintf之类的函数存在一些问题,在一些参数组合下不能正常工作。例如,以下代码会导致应用程序挂起:
    char temp[50];
    sprinf(temp,"%d",234234);
    
  5. 带有长常量的算术表达式不能正常工作。
  6. 用于数组初始化('int[] values={1, 2, 3, 4, 5};')所生成的汇编代码不能正确初始化存储器区域。

由于SDCC一直处于飞速发展之中,如果在你的SDCC工具现有版本中发现任何的缺陷或者你的版本比当前发布的版本早很久时,请下载最新版本。### 结论

Dallas Semiconductor为SDCC编译器提供的DS80C400 ROM库为嵌入式网络应用设计者们寻找低成本网络微控制器解决方案提供了更多的选择。和TINI Java运行环境相比,使用C语言的DS80C400开发者将能够编写精巧的应用程序,赋予系统足够的速度、能力和代码空间来解决任何问题。Dallas Semiconductor正致力于将所有目前工作于Keil编译器的DS80C400库移植到SDCC。请经常访问DS80C400 SDCC库主页来获得升级。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储器
    +关注

    关注

    38

    文章

    7151

    浏览量

    162005
  • ROM
    ROM
    +关注

    关注

    4

    文章

    525

    浏览量

    84832
  • 编译器
    +关注

    关注

    1

    文章

    1577

    浏览量

    48627
收藏 人收藏

    评论

    相关推荐

    用IAR编译器开发DS80C400

    本应用笔记阐述了如何开始使用8051 IAR Embedded Workbench™来创建DS80C400的C语言应用程序。通过一个简单的HTTP服务器演示如何使用DS80C400的ROM功能。所有开发都采用TINIm400验证
    发表于 12-07 09:35 2640次阅读
    用IAR<b class='flag-5'>编译器</b>开发<b class='flag-5'>DS80C400</b>

    基于SDCC编译器和FreeRTOS操作系统怎么C8051F340上移植?

    MCS-51系列单片机应用广泛,我国学习研究的人较多。使用C语言单片机上开发程序可提高开发效率,目前针对该内核兼容单片机开发的C语言编译器
    发表于 09-17 08:24

    Xilinx SDK中使DS-5编译器吗?

    Platform Cable USB II(DLC10)将其加载到我的zc702板上。如何在SDK中成功编译它?我应该在Xilinx SDK中使DS-5编译器吗?但是,我不知道如何
    发表于 03-27 07:43

    如何在音视频范例网络多媒体系统中应用DS80C400网络型微控制

    本文对如何在音视频范例网络多媒体系统中应用DS80C400网络型微控制进行分析与讨论。
    发表于 06-02 06:24

    安装编译器SDCC的方法

    STC单片机+SDCC+Stcgal(MAC环境)1. 安装编译器SDCC:我们Mac上通常使用 brew 这个包管理工具,通过 brew 来安装
    发表于 11-25 08:12

    DS80C400评估板中文资料pdf

    DS80C400评估板
    发表于 04-15 17:42 50次下载

    采用DS80C400创建网络多媒体应用

    采用DS80C400建立网络多媒体应用令人振奋的多媒体应用——包括有线广播(PA)系统、网络门、MP3播放器以及安全摄像机等——可以采用一种低成本的网络型微处理器建立。本
    发表于 07-21 00:47 16次下载

    DS80C400在嵌入式智能网桥中的应用

    文章提出了以DS80C400 为核心处理器将多路CAN 网络与多路以太网互连的嵌入式智能网桥实现方案。给出了 DS80C400 MII 与外部物理设备之间的连接,详细阐述JAVAKIT 在WINDOWS 开发平台下的
    发表于 06-03 08:51 7次下载

    使用免费的SDCC C编译器开发DS89C430/450系列

    摘要:SDCC (小型设备C编译器)是为8位微控制器开发的免费C编译器。本应用笔记演示如何使用SDCC来开发DS89C430/450系列超高
    发表于 04-23 13:55 5984次阅读
    使用免费的<b class='flag-5'>SDCC</b> C<b class='flag-5'>编译器</b>开发<b class='flag-5'>DS</b>89C430/450系列

    SDCC编译器和FreeRTOS在C8051F上的开发的应用

    SDCC编译器和FreeRTOS在C8051F上的开发的应用(通讯电源技术2020年15期)-SDCC编译器和FreeRTOS在C8051F上的开发应用         
    发表于 08-31 11:38 4次下载
    <b class='flag-5'>SDCC</b><b class='flag-5'>编译器</b>和FreeRTOS在C8051F上的开发的应用

    SDCC编译器和FreeRTOS在C8051F上的开发应用

    SDCC编译器和FreeRTOS在C8051F上的开发应用(肇庆理士电源技术有限公司怎么样)-引言MCS-51系列单片机应用广泛,在我国学习研究的人较多。使用C语言在单片机上开发程序可提高开发效率
    发表于 09-17 12:53 8次下载
    <b class='flag-5'>SDCC</b><b class='flag-5'>编译器</b>和FreeRTOS在C8051F上的开发应用

    SDCC编译器和FreeRTOS在C8051F上的开发应用

    SDCC编译器和FreeRTOS在C8051F上的开发应用(核达中远通电源技术有限公司招聘信息)-SDCC编译器和FreeRTOS在C8051F上的开发应用              
    发表于 09-18 17:14 21次下载
    <b class='flag-5'>SDCC</b><b class='flag-5'>编译器</b>和FreeRTOS在C8051F上的开发应用

    利用DS16C32/DS80C390加速80/400位数学运算

    Maxim DS80C390/DS80C400高速微控制器为最终用户提供专用的硬件16/32位数学加速器。访问数学加速器是通过使用五个专用的特殊函数寄存器来完成的。DS16C32/DS80
    的头像 发表于 02-21 10:36 788次阅读
    利用<b class='flag-5'>DS</b>16C32/<b class='flag-5'>DS80</b>C390加速<b class='flag-5'>80</b>/<b class='flag-5'>400</b>位数学运算

    采用DS80C400芯片软件的互联网扬声器

    DS80C400 是支持互联网的扬声器的完美选择。DS80C400的ROM使应用能够以传输原始音频数据的速度通过网络进行通信。通过增加一个16位DAC、一些电阻和少量的焊接工作,DS80C400成为互联网扬声器。
    的头像 发表于 06-13 15:41 372次阅读
    采用<b class='flag-5'>DS80C400</b>芯片软件的互联网扬声器

    SDCC-Linux下的51 MCU编译器

    SDCC (小型设备C编译器)是为8位微控制器开发的免费C编译器。尽管兼容多种不同体系结构,但SDCC C编译器更适合8051内核。
    的头像 发表于 06-16 15:19 3690次阅读