📄 cs8900a.c
字号:
#include "cs8900a.h"
#include "2410lib.h"
#include <string.h>
#define IO_BASE 0x19000300 //IO映射基地址
#define MAX_COUNT 0x00100000 //发送检查芯片状态时,等到的最大循环数
#define MAX_LENGTH 1536
//mac地址,从高位到低位,索引从小变大.
unsigned char mac_addr_src[6] = { 0x01,0x02,0x03,0x04,0x05,0x06};
unsigned char mac_addr_des[6] = { 0x01,0x02,0x03,0x04,0x05,0x07};
#define DA mac_addr_des
#define SA mac_addr_src
#define io_write(addr, val) (*(volatile unsigned short *)(addr) = val)
#define io_read(addr) ((unsigned short)*(volatile unsigned short *)(addr))
inline void reg_write(unsigned short reg, unsigned short val)
{
io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
io_write(IO_BASE+IO_PACKETPAGE_DATA0, val);
}
inline unsigned short reg_read(unsigned short reg)
{
io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
return io_read(IO_BASE+IO_PACKETPAGE_DATA0);
}
set_mac_addr(unsigned char *mac)
{
reg_write(REG_IA, *(unsigned short *)(mac));
reg_write(REG_IA+2, *(unsigned short *)(mac+2));
reg_write(REG_IA+4, *(unsigned short *)(mac+4));
}
void cs_init()
{
unsigned short temp;
//配置 LineCTL ,cs8900a 数据手册的 p62
temp = reg_read(REG_LineCTL);
//8和9位清零,选择10BASE-T only
temp &= ~(AUIonly | AutoAUI_10BT);
//设置接受使能、发送使能、使用扩展的back off(退避,即发生冲突时的强制性重传延迟)算法
temp |= (SerRxON | SerTxON | ModBackOffE);
//把修改之后的寄存器的值更新。
reg_write(REG_LineCTL, temp);
//配置 RxCTL(接收控制寄存器),cs8900a 数据手册的 p54
//RxOKA:当被设置后,cs8900a接受有正确的CRC校验和合法长度(64B-1518B)的帧
//IdividualA:当被设置后,只接受目的地址(DA)和REG_IA(地址过滤寄存器,即之前设置的mac地址)相匹配的帧
//BroadcastA:接受地址为FFFF FFFF FFFF的帧,即接受广播消息
//RxCTL_LOW:0x05,用来标识这个寄存器的编号。
reg_write(REG_RxCTL, RxOKA | IdividualA | BroadcastA | RxCTL_LOW);
//配置 RxCFG (接收配置寄存器),cs8900a 数据手册的 p52
//如果配置RxOKiE[8]位为1,则收到一个正确的数据包之后,会产生一个RxOK的中断。这里使用查询方式
//RxCFG_LOW:0x04,RxCFG 芯片的内部编号,用来标识这个寄存器
reg_write(REG_RxCFG, RxCFG_LOW);
//配置 TxCFG (传送配置寄存器),cs8900a 数据手册的 p55
//TxCFG_LOW: 0x07, 芯片内部标号,用来标识这个寄存器
reg_write(REG_TxCFG, TxCFG_LOW);
}
//发送函数
//frame_data:发送数据的缓冲区,一帧数据
//length:发送数据(DA-data)的长度
int cs_transmit(unsigned char *frame_data, unsigned length)
{
int i;
unsigned short *buf;
//传送命令状态寄存器,cs8900a 数据手册的 p57
//TxStart: (3<<6),在一个完整的帧(即全部数据)写入缓冲区之后,再开始传送。
//TxCMD_LOW:芯片内部的该寄存器标识
io_write(IO_BASE+IO_TX_COMMAND, TxStart | TxCMD_LOW);
//数据长度寄存器,写入待发送数据长度
io_write(IO_BASE+IO_TX_LENGTH, (unsigned short)length);
// 检测芯片可以发送
for(i = 0; i < MAX_COUNT; i++)
{
//REG_BusST:总线状态寄存器,cs8900a 数据手册的 p67
unsigned short temp = reg_read(REG_BusST);
//Rdy4TxNOW:[8]位,如果芯片准备好接受一个帧,则设置该位为1,但是不会产生中断,适合轮询方式
if(temp & Rdy4TxNOW) break;
}
//如果等待时间超过了预设的最大值,则返回1
if(i >= MAX_COUNT)
return 1;
//往IO_RX_TX_DATA0指向的缓冲区以半字为单位,依次写入要发送的数据
buf = (unsigned short *)frame_data;
for(i=0; i<length; i+=2)
io_write(IO_BASE+IO_RX_TX_DATA0, *buf++);
//返回实际发送的数据
return 0;
}
//构建一帧
int cs_construct_frame(unsigned char *orig_data, unsigned short length, unsigned char *frame_data)
{
int i;
unsigned char *frame_p;
//unsigned short pad_length = 0;
frame_p = frame_data;
//检测数据长度是否合法
if(length > 1518)
{
uart_printf("Data is too long!!!\n");
return 0;
}
//uart_printf("write da\n");
//DA
//mac地址的高位放在低地址
for(i=0; i<6; i++,frame_p++)
*(frame_p) = DA[i];
//uart_printf("write sa\n");
//SA
//mac地址的高位放在低地址
for(i=0; i<6; i++,frame_p++)
*(frame_p) = SA[i];
//uart_printf("write length\n");
//Length Field
//length的高位放在高地址处,低位放在低地址处
*(frame_p) = length;
frame_p += 2;
//uart_printf("write data\n");
//LLC Data
for(i=0; i<length; i++,frame_p++)
*(frame_p) = *(orig_data + i);
//PR,SD,PAD,FCS这几个数据段不用填充 ,它是由网卡自动产生的
//Pad(如果数据长度不满46字节,用这段来补齐至少46字节,可以用000000)
//FCS(可以是CRC或者其他校验方式)
frame_p = NULL;
return 0;
}
int test_c8900_transmit(void)
{
int ret;
unsigned short length;
unsigned char frame_senddata[100]={0};
char pString[100];
while(1)
{
uart_printf("Enter a string:");
uart_getstring(pString);
length = strlen(pString);
set_mac_addr(mac_addr_src);
cs_init();
ret = cs_construct_frame(pString, length, frame_senddata);
if(ret != 0)
{
uart_printf("Make Frame error!!\n");
return 0;
}
ret = cs_transmit(frame_senddata, 14+length);
if(ret != 0)
{
uart_printf("Transmit error!!\n");
return 1;
}
uart_printf("Finish!!\n");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -