移植:
- RL-ARM是Keil MDK自带的Real-Time Library,其中包括RTX 内核(Real-Time eXecutive,实时操作系统)、RL-FlashFS(文件系统)、RL-TCPnet(TCP/IP协议栈)、RL-CAN(CAN总线函数库)和RL-USB(USB总线函数库)。虽然说不开源,而且用的人也比较少。但是我觉得封装性比较好,有一个好的中文用户指南,然后移植也比较简单。不过师兄说RL-TCPnet不稳定,好吧,我还是转向了uIP。
- 从Keil安装目录先找到TCP_CM3.lib,这个库文件是适用于STM32的。再找到Net_Config.c,这是TCPnet的配置文件,如果不重新定义的话都会使用这里面的默认值。除此之外,还需要Net_config.h,Net_lib.c,RTL.h。这些编译器会自动在安装目录下找到,不过为了移动方便(有些机器可能没有装RL-ARM)最好还是复制到工程目录下。
- 我使用的网络控制模块是ENC28J60,网络上有很多此模块的驱动。
- 接着就是让RL-tcpnet与ENC28J60联系起来,其实就3个函数,初始化,发送与接收。当初我在这儿总出现问题,其实都是指针的事。指向了一个局部变量的地址。指针确实很强大,但使用的时候也必须很小心。
*---------------------------------------------------------------------------*/
static U8 pdata[ETH_MTU]; //用于数据交换
void init_ethernet(void)
{
enc28j60Init(own_hw_adr);
}
void send_frame (OS_FRAME *frame)
{
U32 len = 0;
U32 *dp,*sp;
sp = (U32 *)&frame->data[0];
dp = (U32 *)&pdata[0];
for (len = (frame->length + 3) >> 2; len; len--)
{
*dp++ = *sp++;
}
enc28j60PacketSend(frame->length,pdata);
}
void poll_ethernet (void)
{
OS_FRAME *frame;
U32 RxLen = 0;
U32 *dp,*sp;
RxLen = enc28j60PacketReceive(ETH_MTU, pdata);
sp = (U32 *)&pdata[0];
if(RxLen!=0)
{
frame = alloc_mem (RxLen);
RxLen = (RxLen + 3) >> 2;
dp = (U32 *)&frame->data[0];
for ( ; RxLen; RxLen--)
{
*dp++ = *sp++;
}
frame->length=RxLen-1;
put_in_queue (frame);
}
else return;
}
应用:
- 基本上移植到这就差不多了,修改一下错误。要使RL-tcpnet运行还需要时间轮询。在Net_Config.c中默认#define TICK_INTERVAL 100为100毫秒。由于我使用了uCOS-II操作系统,系统时钟就是1毫秒,因此我在其钩子函数设置每毫秒加1.如果不适用uCOS-II,可以开一个定时器让其100毫秒给一个标志。
void timer_poll (void)
{
/* System tick timer running in poll mode */
if (rl_time > 100)
{
/* Timer tick every 100 ms */
rl_time = 0;
timer_tick ();
tick = __TRUE;
}
}
- uCOS-II的钩子函数在os_cpu_c.c文件,需要在os_cfg.h中打开#define OS_TIME_TICK_HOOK_EN 1 /* Include code for OSTimeTickHook() */
volatile INT8U rl_time = 0;
#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0)
void OSTimeTickHook (void)
{
#if OS_APP_HOOKS_EN > 0
App_TimeTickHook();
#endif
rl_time++;
#if OS_TMR_EN > 0
OSTmrCtr++;
if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) {
OSTmrCtr = 0;
OSTmrSignal();
}
#endif
}
#endif
- 接下来就可以写有关的应用函数了,我只做过UDP的连接,TCP还没测试。不过可以照着用户指南很容易写出。
- 如果不重新写MAC和IP,就会使用配置里面的默认值。
void IP_Init(void)
{
mem_copy (own_hw_adr, mac_adr, 6); //设置MAC地址
if(dhcp_mode == 0)
{
dhcp_disable (); //禁止DHCP服务
}
str_copy (lhost_name, dev_name); //设置主机名
mem_copy (&localm[NETIF_ETH], &ip_config, sizeof(ip_config));//设置IP信息
}
- 如果采用DHCP自动分配IP,就不必设置IP。只需要循环调用dhcp_check ();
void dhcp_check (void) {
/* Monitor DHCP IP address assignment. */
if (tick == __FALSE || dhcp_tout == 0) {
return;
}
if (mem_test (&MY_IP, 0, IP_ADRLEN) == __FALSE && !(dhcp_tout & 0x80000000)) {
/* Success, DHCP has already got the IP address. */
dhcp_tout = 0;
return;
}
if (--dhcp_tout == 0) {
/* A timeout, disable DHCP and use static IP address. */
dhcp_disable ();
dhcp_tout = 30 | 0x80000000;
return;
}
if (dhcp_tout == 0x80000000) {
dhcp_tout = 0;
}
}
下载:
- RL_TCPnet源码和使用指南下载请点击。
- STM32移植RL_TCPnet工程下载请点击。
如果使用HG的话,那么用命令吧 clone https://zouw96@bitbucket.org/zouw96/rl_tcpnet