mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-22 10:10:45 +00:00
First ARP implementation ready for testing
This commit is contained in:
parent
5abfeb9e30
commit
befc45feba
12 changed files with 295 additions and 67 deletions
|
@ -2,7 +2,7 @@ CFILES = $(wildcard *.c lib/*.c kernel/*.c net/*.c)
|
||||||
SFILES = $(wildcard boot/*.S lib/*.S kernel/*.S)
|
SFILES = $(wildcard boot/*.S lib/*.S kernel/*.S)
|
||||||
OFILES = $(CFILES:.c=.o) $(SFILES:.S=.o)
|
OFILES = $(CFILES:.c=.o) $(SFILES:.S=.o)
|
||||||
LLVMPATH = /opt/homebrew/opt/llvm/bin
|
LLVMPATH = /opt/homebrew/opt/llvm/bin
|
||||||
CLANGFLAGS = -Wall -O2 -ffreestanding -nostdlib -mcpu=cortex-a72+nosimd
|
CLANGFLAGS = -Wall -O0 -ffreestanding -nostdlib -mcpu=cortex-a72+nosimd
|
||||||
|
|
||||||
all: clean kernel8.img
|
all: clean kernel8.img
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
CFILES = $(wildcard *.c lib/*.c kernel/*.c net/*.c)
|
CFILES = $(wildcard *.c lib/*.c kernel/*.c net/*.c)
|
||||||
SFILES = $(wildcard boot/*.S lib/*.S kernel/*.S)
|
SFILES = $(wildcard boot/*.S lib/*.S kernel/*.S)
|
||||||
OFILES = $(CFILES:.c=.o) $(SFILES:.S=.o)
|
OFILES = $(CFILES:.c=.o) $(SFILES:.S=.o)
|
||||||
GCCFLAGS = -Wall -O2 -ffreestanding -nostdlib -nostartfiles
|
GCCFLAGS = -Wall -O0 -ffreestanding -nostdlib -nostartfiles
|
||||||
GCCPATH = ../../gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin
|
GCCPATH = ../../gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin
|
||||||
|
|
||||||
all: clean kernel8.img
|
all: clean kernel8.img
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
void spi_init();
|
void spi_init();
|
||||||
void spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int size);
|
unsigned int spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int size);
|
||||||
void spi_send(unsigned char *data, unsigned int size);
|
void spi_send(unsigned char *data, unsigned int size);
|
||||||
void spi_recv(unsigned char *data, unsigned int size);
|
void spi_recv(unsigned char *data, unsigned int size);
|
||||||
void spi_send_no_selection(unsigned char command);
|
void spi_send_no_selection(unsigned char command);
|
||||||
|
|
201
part14-ethernet/kernel/arp.c
Normal file
201
part14-ethernet/kernel/arp.c
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
#include "../net/enc28j60.h"
|
||||||
|
#include "../include/fb.h"
|
||||||
|
|
||||||
|
// Structure for Ethernet header
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t DestAddrs[6];
|
||||||
|
uint8_t SrcAddrs[6];
|
||||||
|
uint16_t type;
|
||||||
|
} EtherNetII;
|
||||||
|
|
||||||
|
// Ethernet packet types
|
||||||
|
|
||||||
|
#define ARPPACKET 0x0806
|
||||||
|
#define IPPACKET 0x0800
|
||||||
|
|
||||||
|
// Structure for an ARP Packet
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EtherNetII eth;
|
||||||
|
uint16_t hardware;
|
||||||
|
uint16_t protocol;
|
||||||
|
uint8_t hardwareSize;
|
||||||
|
uint8_t protocolSize;
|
||||||
|
uint16_t opCode;
|
||||||
|
uint8_t senderMAC[6];
|
||||||
|
uint8_t senderIP[4];
|
||||||
|
uint8_t targetMAC[6];
|
||||||
|
uint8_t targetIP[4];
|
||||||
|
} ARP;
|
||||||
|
|
||||||
|
// ARP OpCodes
|
||||||
|
|
||||||
|
#define ARPREPLY 0x0002
|
||||||
|
#define ARPREQUEST 0x0001
|
||||||
|
|
||||||
|
// ARP hardware types
|
||||||
|
|
||||||
|
#define ETHERNET 0x0001
|
||||||
|
|
||||||
|
// MAC address to be assigned to the ENC28J60
|
||||||
|
|
||||||
|
uint8_t myMAC[6] = { 0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee };
|
||||||
|
|
||||||
|
// Router MAC is not known to start with, and requires an ARP reply to find out
|
||||||
|
|
||||||
|
uint8_t routerMAC[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
|
// IP address to be assigned to the ENC28J60
|
||||||
|
|
||||||
|
uint8_t deviceIP[4] = { 192, 168, 0, 66 };
|
||||||
|
|
||||||
|
// IP Address of the router, whose hardware address we will find using the ARP request
|
||||||
|
|
||||||
|
uint8_t routerIP[4] = { 192, 168, 0, 1 };
|
||||||
|
|
||||||
|
// HELPER FUNCTIONS
|
||||||
|
|
||||||
|
void *memset(void *dest, uint8_t val, uint16_t len)
|
||||||
|
{
|
||||||
|
uint8_t *ptr = dest;
|
||||||
|
while (len-- > 0)
|
||||||
|
*ptr++ = val;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memcpy(void *dest, const void *src, uint16_t len)
|
||||||
|
{
|
||||||
|
uint8_t *d = dest;
|
||||||
|
const uint8_t *s = src;
|
||||||
|
while (len--)
|
||||||
|
*d++ = *s++;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t memcmp(void *str1, void *str2, unsigned count)
|
||||||
|
{
|
||||||
|
uint8_t *s1 = str1;
|
||||||
|
uint8_t *s2 = str2;
|
||||||
|
|
||||||
|
while (count-- > 0)
|
||||||
|
{
|
||||||
|
if (*s1++ != *s2++)
|
||||||
|
return s1[-1] < s2[-1] ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAIN FUNCTIONS
|
||||||
|
|
||||||
|
void SendArpPacket(uint8_t *targetIP, uint8_t *deviceMAC)
|
||||||
|
{
|
||||||
|
/* Parameters:
|
||||||
|
* targetIP - The target IP Address for the ARP request (the one whose hardware
|
||||||
|
* address we want)
|
||||||
|
* deviceMAC - The MAC address of the ENC28J60, i.e. the source MAC for the ARP
|
||||||
|
* request
|
||||||
|
*/
|
||||||
|
|
||||||
|
ARP arpPacket;
|
||||||
|
|
||||||
|
// The source of the packet will be the ENC28J60 MAC address
|
||||||
|
memcpy(arpPacket.eth.SrcAddrs, deviceMAC, 6);
|
||||||
|
|
||||||
|
// The destination is broadcast - a MAC address of FF:FF:FF:FF:FF:FF */
|
||||||
|
memset(arpPacket.eth.DestAddrs, 0xFF, 6);
|
||||||
|
|
||||||
|
arpPacket.eth.type = ARPPACKET;
|
||||||
|
arpPacket.hardware = ETHERNET;
|
||||||
|
|
||||||
|
// We want an IP address resolved
|
||||||
|
|
||||||
|
arpPacket.protocol = IPPACKET;
|
||||||
|
arpPacket.hardwareSize = 0x06; // sizeof(deviceMAC);
|
||||||
|
arpPacket.protocolSize = 0x04; // sizeof(deviceIP);
|
||||||
|
arpPacket.opCode = ARPREQUEST;
|
||||||
|
|
||||||
|
// Target MAC is set to 0 as it is unknown
|
||||||
|
memset(arpPacket.targetMAC, 0, 6);
|
||||||
|
|
||||||
|
// Sender MAC is the ENC28J60's MAC address
|
||||||
|
memcpy(arpPacket.senderMAC, deviceMAC, 6);
|
||||||
|
|
||||||
|
// The target IP is the IP address we want resolved
|
||||||
|
memcpy(arpPacket.targetIP, targetIP, 4);
|
||||||
|
|
||||||
|
// Check if the last reply has come from an IP address that we want i.e. someone else is already using it
|
||||||
|
if (!memcmp(targetIP, deviceIP, 4)) {
|
||||||
|
// Yes, someone is using our IP so set the sender IP to 0.0.0.0
|
||||||
|
memset(arpPacket.senderIP, 0, 4);
|
||||||
|
} else {
|
||||||
|
// No, nobody is using our IP so we can use it confidently
|
||||||
|
memcpy(arpPacket.senderIP, deviceIP, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the packet
|
||||||
|
ENC_WriteBuffer((unsigned char*)&arpPacket, sizeof(ARP));
|
||||||
|
}
|
||||||
|
|
||||||
|
void arp_test(void)
|
||||||
|
{
|
||||||
|
unsigned int tries = 0;
|
||||||
|
ARP checkPacket;
|
||||||
|
|
||||||
|
debugstr("Sending ARP request... ");
|
||||||
|
|
||||||
|
SendArpPacket(routerIP, myMAC);
|
||||||
|
|
||||||
|
debugstr("done.");
|
||||||
|
debugcrlf();
|
||||||
|
|
||||||
|
debugstr("Waiting for ARP response... ");
|
||||||
|
debugcrlf();
|
||||||
|
|
||||||
|
while (tries < 1000) {
|
||||||
|
if (ENC_ReadBuffer((unsigned char *)&checkPacket, sizeof(ARP)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!memcmp(checkPacket.senderIP, routerIP, 4)) {
|
||||||
|
// Success! We have found our router's MAC address
|
||||||
|
|
||||||
|
memcpy(routerMAC, checkPacket.senderMAC, 6);
|
||||||
|
debugstr("Router MAC is ");
|
||||||
|
debughex(routerMAC[0]);
|
||||||
|
debughex(routerMAC[1]);
|
||||||
|
debughex(routerMAC[2]);
|
||||||
|
debughex(routerMAC[3]);
|
||||||
|
debughex(routerMAC[4]);
|
||||||
|
debughex(routerMAC[5]);
|
||||||
|
debugcrlf();
|
||||||
|
}
|
||||||
|
tries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugstr("Timed out.");
|
||||||
|
debugcrlf();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_network(void)
|
||||||
|
{
|
||||||
|
ENC_HandleTypeDef handle;
|
||||||
|
|
||||||
|
debugstr("Setting MAC address to C0:FF:EE:C0:FF:EE.");
|
||||||
|
debugcrlf();
|
||||||
|
|
||||||
|
handle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
|
||||||
|
handle.Init.MACAddr = myMAC;
|
||||||
|
handle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
|
||||||
|
handle.Init.InterruptEnableBits = 0;
|
||||||
|
|
||||||
|
debugstr("Starting network up.");
|
||||||
|
debugcrlf();
|
||||||
|
|
||||||
|
if (!ENC_Start(&handle)) {
|
||||||
|
debugstr("Could not initialise network card.");
|
||||||
|
} else {
|
||||||
|
debugstr("Network card successfully initialised.");
|
||||||
|
}
|
||||||
|
debugcrlf();
|
||||||
|
}
|
|
@ -1,4 +1,27 @@
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
#include "../include/fb.h"
|
||||||
|
|
||||||
|
char *entry_error_messages[] = {
|
||||||
|
"SYNC_INVALID_EL1t",
|
||||||
|
"IRQ_INVALID_EL1t",
|
||||||
|
"FIQ_INVALID_EL1t",
|
||||||
|
"ERROR_INVALID_EL1T",
|
||||||
|
|
||||||
|
"SYNC_INVALID_EL1h",
|
||||||
|
"IRQ_INVALID_EL1h",
|
||||||
|
"FIQ_INVALID_EL1h",
|
||||||
|
"ERROR_INVALID_EL1h",
|
||||||
|
|
||||||
|
"SYNC_INVALID_EL0_64",
|
||||||
|
"IRQ_INVALID_EL0_64",
|
||||||
|
"FIQ_INVALID_EL0_64",
|
||||||
|
"ERROR_INVALID_EL0_64",
|
||||||
|
|
||||||
|
"SYNC_INVALID_EL0_32",
|
||||||
|
"IRQ_INVALID_EL0_32",
|
||||||
|
"FIQ_INVALID_EL0_32",
|
||||||
|
"ERROR_INVALID_EL0_32"
|
||||||
|
};
|
||||||
|
|
||||||
void enable_interrupt_controller() {
|
void enable_interrupt_controller() {
|
||||||
REGS_IRQ->irq0_enable_0 = SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3;
|
REGS_IRQ->irq0_enable_0 = SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3;
|
||||||
|
@ -8,6 +31,14 @@ void disable_interrupt_controller() {
|
||||||
REGS_IRQ->irq0_enable_0 = 0;
|
REGS_IRQ->irq0_enable_0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void show_invalid_entry_message(int type, unsigned long esr, unsigned long address) {
|
||||||
|
debugstr(entry_error_messages[type]);
|
||||||
|
debugstr(" ESR: ");
|
||||||
|
debughex(esr);
|
||||||
|
debugstr("Addr: ");
|
||||||
|
debughex(address);
|
||||||
|
}
|
||||||
|
|
||||||
void handle_irq() {
|
void handle_irq() {
|
||||||
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
||||||
|
|
||||||
|
|
|
@ -67,11 +67,7 @@
|
||||||
mov x0, #\type
|
mov x0, #\type
|
||||||
mrs x1, esr_el1
|
mrs x1, esr_el1
|
||||||
mrs x2, elr_el1
|
mrs x2, elr_el1
|
||||||
|
bl show_invalid_entry_message
|
||||||
// We could pass this to a function to print an error here
|
|
||||||
// e.g. bl show_invalid_entry_message
|
|
||||||
//
|
|
||||||
// For now we'll just hang
|
|
||||||
|
|
||||||
b err_hang
|
b err_hang
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
void initProgress(void)
|
void initProgress(void)
|
||||||
{
|
{
|
||||||
drawRect(0, 0, 301, 50, 0x0f, 0);
|
drawRect(0, 0, 301, 50, 0x0f, 0);
|
||||||
drawString(309, 21, "Core 0", 0x0f, 1);
|
drawString(309, 21, "Core 1", 0x0f, 1);
|
||||||
|
|
||||||
drawRect(0, 60, 301, 110, 0x0f, 0);
|
drawRect(0, 60, 301, 110, 0x0f, 0);
|
||||||
drawString(309, 81, "Core 1", 0x0f, 1);
|
drawString(309, 81, "Core 2", 0x0f, 1);
|
||||||
|
|
||||||
drawRect(0, 120, 301, 170, 0x0f, 0);
|
drawRect(0, 120, 301, 170, 0x0f, 0);
|
||||||
drawString(309, 141, "Timer 1", 0x0f, 1);
|
drawString(309, 141, "Timer 1", 0x0f, 1);
|
||||||
|
@ -28,21 +28,24 @@ void drawProgress(unsigned int core, unsigned int val) {
|
||||||
if (val > 0) drawRect(1, (60 * core) + 1, (val * 3), (60 * core) + 49, col, 1);
|
if (val > 0) drawRect(1, (60 * core) + 1, (val * 3), (60 * core) + 49, col, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void core0_main(void)
|
unsigned int c2_done = 0;
|
||||||
{
|
|
||||||
unsigned int core0_val = 0;
|
|
||||||
|
|
||||||
while (core0_val <= 100) {
|
void core2_main(void)
|
||||||
|
{
|
||||||
|
unsigned int core2_val = 0;
|
||||||
|
|
||||||
|
clear_core2(); // Only run once
|
||||||
|
|
||||||
|
while (core2_val <= 100) {
|
||||||
wait_msec(0x100000);
|
wait_msec(0x100000);
|
||||||
drawProgress(0, core0_val);
|
drawProgress(1, core2_val);
|
||||||
core0_val++;
|
core2_val++;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugstr("Core 0 done.");
|
debugstr("Core 2 done.");
|
||||||
debugcrlf();
|
debugcrlf();
|
||||||
|
|
||||||
irq_disable();
|
c2_done = 1;
|
||||||
disable_interrupt_controller();
|
|
||||||
|
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +58,7 @@ void core1_main(void)
|
||||||
|
|
||||||
while (core1_val <= 100) {
|
while (core1_val <= 100) {
|
||||||
wait_msec(0x3FFFF);
|
wait_msec(0x3FFFF);
|
||||||
drawProgress(1, core1_val);
|
drawProgress(0, core1_val);
|
||||||
core1_val++;
|
core1_val++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,37 +135,6 @@ unsigned int HAL_GetTick(void) {
|
||||||
return timer_get_ticks();
|
return timer_get_ticks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_network(void)
|
|
||||||
{
|
|
||||||
ENC_HandleTypeDef handle;
|
|
||||||
|
|
||||||
unsigned char macaddr[6];
|
|
||||||
macaddr[0] = 0xc0;
|
|
||||||
macaddr[1] = 0xff;
|
|
||||||
macaddr[2] = 0xee;
|
|
||||||
macaddr[3] = 0xc0;
|
|
||||||
macaddr[4] = 0xff;
|
|
||||||
macaddr[5] = 0xee;
|
|
||||||
|
|
||||||
debugstr("Setting MAC address to C0:FF:EE:C0:FF:EE.");
|
|
||||||
debugcrlf();
|
|
||||||
|
|
||||||
handle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
|
|
||||||
handle.Init.MACAddr = macaddr;
|
|
||||||
handle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
|
|
||||||
handle.Init.InterruptEnableBits = 0;
|
|
||||||
|
|
||||||
debugstr("Starting network up.");
|
|
||||||
debugcrlf();
|
|
||||||
|
|
||||||
if (!ENC_Start(&handle)) {
|
|
||||||
debugstr("Could not initialise network card.");
|
|
||||||
} else {
|
|
||||||
debugstr("Network card successfully initialised.");
|
|
||||||
}
|
|
||||||
debugcrlf();
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
fb_init();
|
fb_init();
|
||||||
|
@ -172,20 +144,35 @@ void main(void)
|
||||||
|
|
||||||
initProgress();
|
initProgress();
|
||||||
|
|
||||||
|
// Kick it off on core 1&2
|
||||||
|
|
||||||
|
start_core1(core1_main);
|
||||||
|
start_core2(core2_main);
|
||||||
|
|
||||||
// Kick off the timers
|
// Kick off the timers
|
||||||
|
|
||||||
irq_init_vectors();
|
irq_init_vectors();
|
||||||
enable_interrupt_controller();
|
enable_interrupt_controller();
|
||||||
irq_enable();
|
irq_enable();
|
||||||
timer_init();
|
timer_init();
|
||||||
|
|
||||||
|
// Test the network card
|
||||||
|
|
||||||
spi_init();
|
spi_init();
|
||||||
init_network();
|
init_network();
|
||||||
|
arp_test();
|
||||||
|
|
||||||
// Kick it off on core 1
|
// The work is done - wait for timers to get done
|
||||||
|
|
||||||
start_core1(core1_main);
|
debugstr("Core 0 done.");
|
||||||
|
debugcrlf();
|
||||||
|
|
||||||
// Loop endlessly
|
while (!c2_done);
|
||||||
|
|
||||||
core0_main();
|
// Disable IRQs and loop endlessly
|
||||||
|
|
||||||
|
irq_disable();
|
||||||
|
disable_interrupt_controller();
|
||||||
|
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,3 +49,6 @@ unsigned long timer_get_ticks();
|
||||||
void timer_sleep(unsigned int ms);
|
void timer_sleep(unsigned int ms);
|
||||||
void HAL_Delay(volatile unsigned int Delay);
|
void HAL_Delay(volatile unsigned int Delay);
|
||||||
unsigned int HAL_GetTick(void);
|
unsigned int HAL_GetTick(void);
|
||||||
|
|
||||||
|
void init_network(void);
|
||||||
|
void arp_test(void);
|
||||||
|
|
|
@ -52,7 +52,7 @@ void spi_chip_select(unsigned char chip_select) {
|
||||||
REGS_SPI0->cs = (REGS_SPI0->cs & ~CS_CS) | (chip_select << CS_CS__SHIFT);
|
REGS_SPI0->cs = (REGS_SPI0->cs & ~CS_CS) | (chip_select << CS_CS__SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int size) {
|
unsigned int spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int size) {
|
||||||
REGS_SPI0->data_length = size;
|
REGS_SPI0->data_length = size;
|
||||||
REGS_SPI0->cs = REGS_SPI0->cs | CS_CLEAR_RX | CS_CLEAR_TX | CS_TA;
|
REGS_SPI0->cs = REGS_SPI0->cs | CS_CLEAR_RX | CS_CLEAR_TX | CS_TA;
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ void spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int
|
||||||
}
|
}
|
||||||
|
|
||||||
REGS_SPI0->cs = (REGS_SPI0->cs & ~CS_TA);
|
REGS_SPI0->cs = (REGS_SPI0->cs & ~CS_TA);
|
||||||
|
return read_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spi_send(unsigned char *data, unsigned int size) {
|
void spi_send(unsigned char *data, unsigned int size) {
|
||||||
|
|
|
@ -993,7 +993,7 @@ void ENC_WriteBuffer(void *buffer, uint16_t buflen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: enc_rdbuffer
|
* Function: ENC_ReadBuffer
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Read a buffer of data.
|
* Read a buffer of data.
|
||||||
|
@ -1003,15 +1003,17 @@ void ENC_WriteBuffer(void *buffer, uint16_t buflen)
|
||||||
* buflen - The number of bytes to read
|
* buflen - The number of bytes to read
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None
|
* read_count - Number of bytes received
|
||||||
*
|
*
|
||||||
* Assumptions:
|
* Assumptions:
|
||||||
* Read pointer is set to the correct address
|
* Read pointer is set to the correct address
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void enc_rdbuffer(void *buffer, int16_t buflen)
|
uint8_t ENC_ReadBuffer(void *buffer, uint16_t buflen)
|
||||||
{
|
{
|
||||||
|
uint8_t read_count = 0;
|
||||||
|
|
||||||
/* Select ENC28J60 chip */
|
/* Select ENC28J60 chip */
|
||||||
|
|
||||||
ENC_SPI_Select(true);
|
ENC_SPI_Select(true);
|
||||||
|
@ -1022,9 +1024,11 @@ static void enc_rdbuffer(void *buffer, int16_t buflen)
|
||||||
|
|
||||||
/* Then read the buffer data */
|
/* Then read the buffer data */
|
||||||
|
|
||||||
ENC_SPI_SendBuf(NULL, buffer, buflen);
|
read_count = ENC_SPI_SendBuf(NULL, buffer, buflen);
|
||||||
|
|
||||||
/* De-select ENC28J60 chip: done in ENC_SPI_SendBuf callback */
|
/* De-select ENC28J60 chip: done in ENC_SPI_SendBuf callback */
|
||||||
|
|
||||||
|
return read_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -1187,7 +1191,7 @@ void ENC_Transmit(ENC_HandleTypeDef *handle)
|
||||||
enc_wrbreg(handle, ENC_ERDPTL, addtTsv4 & 0xff);
|
enc_wrbreg(handle, ENC_ERDPTL, addtTsv4 & 0xff);
|
||||||
enc_wrbreg(handle, ENC_ERDPTH, addtTsv4 >> 8);
|
enc_wrbreg(handle, ENC_ERDPTH, addtTsv4 >> 8);
|
||||||
|
|
||||||
enc_rdbuffer(&tsv4, 1);
|
ENC_ReadBuffer(&tsv4, 1);
|
||||||
regval = enc_rdgreg(ENC_EIR);
|
regval = enc_rdgreg(ENC_EIR);
|
||||||
if (!(regval & EIR_TXERIF) || !(tsv4 & TSV_LATECOL)) {
|
if (!(regval & EIR_TXERIF) || !(tsv4 & TSV_LATECOL)) {
|
||||||
break;
|
break;
|
||||||
|
@ -1242,7 +1246,7 @@ bool ENC_GetReceivedFrame(ENC_HandleTypeDef *handle)
|
||||||
* and wrap to the beginning of the read buffer as necessary)
|
* and wrap to the beginning of the read buffer as necessary)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enc_rdbuffer(rsv, 6);
|
ENC_ReadBuffer(rsv, 6);
|
||||||
|
|
||||||
/* Decode the new next packet pointer, and the RSV. The
|
/* Decode the new next packet pointer, and the RSV. The
|
||||||
* RSV is encoded as:
|
* RSV is encoded as:
|
||||||
|
@ -1281,7 +1285,7 @@ bool ENC_GetReceivedFrame(ENC_HandleTypeDef *handle)
|
||||||
* end_rdbuffer (above).
|
* end_rdbuffer (above).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enc_rdbuffer(handle->RxFrameInfos.buffer, handle->RxFrameInfos.length);
|
ENC_ReadBuffer(handle->RxFrameInfos.buffer, handle->RxFrameInfos.length);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,10 +98,10 @@ void ENC_SPI_Send(uint8_t command);
|
||||||
* Implement SPI buffer send and receive. Must be provided by user code
|
* Implement SPI buffer send and receive. Must be provided by user code
|
||||||
* param master2slave: data to be sent from host to ENC28J60, can be NULL if we only want to receive data from slave
|
* param master2slave: data to be sent from host to ENC28J60, can be NULL if we only want to receive data from slave
|
||||||
* param slave2master: answer from ENC28J60 to host, can be NULL if we only want to send data to slave
|
* param slave2master: answer from ENC28J60 to host, can be NULL if we only want to send data to slave
|
||||||
* retval none
|
* retval read_count: number of bytes read (if applicable)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ENC_SPI_SendBuf(uint8_t *master2slave, uint8_t *slave2master, uint16_t bufferSize);
|
unsigned int ENC_SPI_SendBuf(uint8_t *master2slave, uint8_t *slave2master, uint16_t bufferSize);
|
||||||
|
|
||||||
/* Exported types ------------------------------------------------------------*/
|
/* Exported types ------------------------------------------------------------*/
|
||||||
/** @defgroup ETH_Exported_Types ETH Exported Types
|
/** @defgroup ETH_Exported_Types ETH Exported Types
|
||||||
|
@ -686,6 +686,7 @@ int8_t ENC_RestoreTXBuffer(ENC_HandleTypeDef *handle, uint16_t len);
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void ENC_WriteBuffer(void *buffer, uint16_t buflen);
|
void ENC_WriteBuffer(void *buffer, uint16_t buflen);
|
||||||
|
uint8_t ENC_ReadBuffer(void *buffer, uint16_t buflen);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: ENC_Transmit
|
* Function: ENC_Transmit
|
||||||
|
|
|
@ -4,10 +4,14 @@ void ENC_SPI_Select(unsigned char truefalse) {
|
||||||
spi_chip_select(!truefalse); // If it's true, select 0 (the ENC), if false, select 1 (i.e. deselect the ENC)
|
spi_chip_select(!truefalse); // If it's true, select 0 (the ENC), if false, select 1 (i.e. deselect the ENC)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ENC_SPI_SendBuf(unsigned char *master2slave, unsigned char *slave2master, unsigned short bufferSize) {
|
unsigned int ENC_SPI_SendBuf(unsigned char *master2slave, unsigned char *slave2master, unsigned short bufferSize) {
|
||||||
|
unsigned int read_count = 0;
|
||||||
|
|
||||||
spi_chip_select(0);
|
spi_chip_select(0);
|
||||||
spi_send_recv(master2slave, slave2master, bufferSize);
|
read_count = spi_send_recv(master2slave, slave2master, bufferSize);
|
||||||
spi_chip_select(1); // De-select the ENC
|
spi_chip_select(1); // De-select the ENC
|
||||||
|
|
||||||
|
return read_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ENC_SPI_Send(unsigned char command) {
|
void ENC_SPI_Send(unsigned char command) {
|
||||||
|
|
Loading…
Reference in a new issue