mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-22 02:00:40 +00:00
Added part15-tcpip - same as part14-ethernet, but replies to pings now
This commit is contained in:
parent
ababff0e38
commit
bc2ecc934d
29 changed files with 6081 additions and 0 deletions
20
part15-tcpip/Makefile
Normal file
20
part15-tcpip/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
|||
CFILES = $(wildcard *.c lib/*.c kernel/*.c net/*.c tcpip/*.c)
|
||||
SFILES = $(wildcard boot/*.S lib/*.S kernel/*.S)
|
||||
OFILES = $(CFILES:.c=.o) $(SFILES:.S=.o)
|
||||
LLVMPATH = /opt/homebrew/opt/llvm/bin
|
||||
CLANGFLAGS = -Wall -O0 -ffreestanding -nostdlib -mcpu=cortex-a72+nosimd
|
||||
|
||||
all: clean kernel8.img
|
||||
|
||||
%.o: %.c
|
||||
$(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.S
|
||||
$(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@
|
||||
|
||||
kernel8.img: $(OFILES)
|
||||
$(LLVMPATH)/ld.lld -m aarch64elf -nostdlib $(OFILES) -T boot/link.ld -o kernel8.elf
|
||||
$(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img
|
||||
|
||||
clean:
|
||||
/bin/rm kernel8.elf */*.o *.img > /dev/null 2> /dev/null || true
|
20
part15-tcpip/Makefile.gcc
Normal file
20
part15-tcpip/Makefile.gcc
Normal file
|
@ -0,0 +1,20 @@
|
|||
CFILES = $(wildcard *.c lib/*.c kernel/*.c net/*.c tcpip/*.c)
|
||||
SFILES = $(wildcard boot/*.S lib/*.S kernel/*.S)
|
||||
OFILES = $(CFILES:.c=.o) $(SFILES:.S=.o)
|
||||
GCCFLAGS = -Wall -O0 -ffreestanding -nostdlib -nostartfiles
|
||||
GCCPATH = ../../gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin
|
||||
|
||||
all: clean kernel8.img
|
||||
|
||||
%.o: %.c
|
||||
$(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.S
|
||||
$(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@
|
||||
|
||||
kernel8.img: $(OFILES)
|
||||
$(GCCPATH)/aarch64-none-elf-ld -nostdlib $(OFILES) -T boot/link.ld -o kernel8.elf
|
||||
$(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img
|
||||
|
||||
clean:
|
||||
/bin/rm kernel8.elf */*.o *.img > /dev/null 2> /dev/null || true
|
114
part15-tcpip/boot/boot.S
Normal file
114
part15-tcpip/boot/boot.S
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include "sysregs.h"
|
||||
|
||||
#define LOCAL_CONTROL 0xff800000
|
||||
#define LOCAL_PRESCALER 0xff800008
|
||||
#define OSC_FREQ 54000000
|
||||
#define MAIN_STACK 0x400000
|
||||
|
||||
.section ".text.boot" // Make sure the linker puts this at the start of the kernel image
|
||||
|
||||
.global _start // Execution starts here
|
||||
|
||||
_start:
|
||||
ldr x0, =LOCAL_CONTROL // Sort out the timer
|
||||
str wzr, [x0]
|
||||
mov w1, 0x80000000
|
||||
str w1, [x0, #(LOCAL_PRESCALER - LOCAL_CONTROL)]
|
||||
|
||||
ldr x0, =OSC_FREQ
|
||||
msr cntfrq_el0, x0
|
||||
msr cntvoff_el2, xzr
|
||||
|
||||
// Check processor ID is zero (executing on main core), else hang
|
||||
mrs x1, mpidr_el1
|
||||
and x1, x1, #3
|
||||
cbz x1, 2f
|
||||
|
||||
// We're not on the main core, so hang in an infinite wait loop
|
||||
adr x5, spin_cpu0
|
||||
1: wfe
|
||||
ldr x4, [x5, x1, lsl #3]
|
||||
cbz x4, 1b
|
||||
|
||||
ldr x2, =__stack_start // Get ourselves a fresh stack - location depends on CPU core asking
|
||||
lsl x1, x1, #9 // Multiply core_number by 512
|
||||
add x3, x2, x1 // Add to the address
|
||||
mov sp, x3
|
||||
|
||||
mov x0, #0
|
||||
mov x1, #0
|
||||
mov x2, #0
|
||||
mov x3, #0
|
||||
br x4
|
||||
b 1b
|
||||
2: // We're on the main core!
|
||||
// First enable the FPU
|
||||
|
||||
mov x0, #0x33ff
|
||||
msr cptr_el3, x0 // Disable coprocessor traps to EL3
|
||||
mov x0, #3 << 20
|
||||
msr cpacr_el1, x0 // Enable FP/SIMD at EL1
|
||||
|
||||
// Now get ready to switch from EL3 down to EL1
|
||||
|
||||
ldr x0, =SCTLR_VALUE_MMU_DISABLED
|
||||
msr sctlr_el1, x0
|
||||
|
||||
ldr x0, =HCR_VALUE
|
||||
msr hcr_el2, x0
|
||||
|
||||
ldr x0, =SCR_VALUE
|
||||
msr scr_el3, x0
|
||||
|
||||
ldr x0, =SPSR_VALUE
|
||||
msr spsr_el3, x0
|
||||
|
||||
adr x0, el1_entry
|
||||
msr elr_el3, x0
|
||||
|
||||
eret
|
||||
el1_entry:
|
||||
// We're in EL1
|
||||
// Clean the BSS section
|
||||
ldr x1, =__bss_start // Start address
|
||||
ldr w2, =__bss_size // Size of the section
|
||||
3: cbz w2, 4f // Quit loop if zero
|
||||
str xzr, [x1], #8
|
||||
sub w2, w2, #1
|
||||
cbnz w2, 3b // Loop if non-zero
|
||||
|
||||
// Set stack to start somewhere safe
|
||||
mov sp, #MAIN_STACK
|
||||
|
||||
// Jump to our main() routine in C (make sure it doesn't return)
|
||||
4: bl main
|
||||
// In case it does return, halt the master core too
|
||||
b 1b
|
||||
|
||||
.ltorg
|
||||
|
||||
.org 0x110
|
||||
.globl spin_cpu0
|
||||
spin_cpu0:
|
||||
.quad 0
|
||||
|
||||
.org 0x118
|
||||
.globl spin_cpu1
|
||||
spin_cpu1:
|
||||
.quad 0
|
||||
|
||||
.org 0x120
|
||||
.globl spin_cpu2
|
||||
spin_cpu2:
|
||||
.quad 0
|
||||
|
||||
.org 0x128
|
||||
.globl spin_cpu3
|
||||
spin_cpu3:
|
||||
.quad 0
|
||||
|
||||
.globl get_el
|
||||
get_el:
|
||||
mrs x0, CurrentEL
|
||||
lsr x0, x0, #2
|
||||
ret
|
35
part15-tcpip/boot/link.ld
Normal file
35
part15-tcpip/boot/link.ld
Normal file
|
@ -0,0 +1,35 @@
|
|||
SECTIONS
|
||||
{
|
||||
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
|
||||
PROVIDE(_data = .);
|
||||
.data : { *(.data .data.* .gnu.linkonce.d*) }
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(16);
|
||||
__bss_start = .;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
__bss_end = .;
|
||||
__bss_size = (__bss_end - __bss_start)>>3;
|
||||
}
|
||||
.cpu1Stack :
|
||||
{
|
||||
. = ALIGN(16);
|
||||
__stack_start = .;
|
||||
. = . + 512;
|
||||
__cpu1_stack = .;
|
||||
}
|
||||
.cpu2Stack :
|
||||
{
|
||||
. = . + 512;
|
||||
__cpu2_stack = .;
|
||||
}
|
||||
.cpu3Stack :
|
||||
{
|
||||
. = . + 512;
|
||||
__cpu3_stack = .;
|
||||
}
|
||||
_end = .;
|
||||
|
||||
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
|
||||
}
|
44
part15-tcpip/boot/sysregs.h
Normal file
44
part15-tcpip/boot/sysregs.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef _SYSREGS_H
|
||||
#define _SYSREGS_H
|
||||
|
||||
// ***************************************
|
||||
// SCTLR_EL1, System Control Register (EL1), Page 2654 of AArch64-Reference-Manual.
|
||||
// ***************************************
|
||||
|
||||
#define SCTLR_RESERVED (3 << 28) | (3 << 22) | (1 << 20) | (1 << 11)
|
||||
#define SCTLR_EE_LITTLE_ENDIAN (0 << 25)
|
||||
#define SCTLR_EOE_LITTLE_ENDIAN (0 << 24)
|
||||
#define SCTLR_I_CACHE_DISABLED (0 << 12)
|
||||
#define SCTLR_D_CACHE_DISABLED (0 << 2)
|
||||
#define SCTLR_I_CACHE_ENABLED (1 << 12)
|
||||
#define SCTLR_D_CACHE_ENABLED (1 << 2)
|
||||
#define SCTLR_MMU_DISABLED (0 << 0)
|
||||
#define SCTLR_MMU_ENABLED (1 << 0)
|
||||
|
||||
#define SCTLR_VALUE_MMU_DISABLED (SCTLR_RESERVED | SCTLR_EE_LITTLE_ENDIAN | SCTLR_I_CACHE_ENABLED | SCTLR_D_CACHE_ENABLED | SCTLR_MMU_DISABLED)
|
||||
|
||||
// ***************************************
|
||||
// HCR_EL2, Hypervisor Configuration Register (EL2), Page 2487 of AArch64-Reference-Manual.
|
||||
// ***************************************
|
||||
|
||||
#define HCR_RW (1 << 31)
|
||||
#define HCR_VALUE HCR_RW
|
||||
|
||||
// ***************************************
|
||||
// SCR_EL3, Secure Configuration Register (EL3), Page 2648 of AArch64-Reference-Manual.
|
||||
// ***************************************
|
||||
|
||||
#define SCR_RESERVED (3 << 4)
|
||||
#define SCR_RW (1 << 10)
|
||||
#define SCR_NS (1 << 0)
|
||||
#define SCR_VALUE (SCR_RESERVED | SCR_RW | SCR_NS)
|
||||
|
||||
// ***************************************
|
||||
// SPSR_EL3, Saved Program Status Register (EL3) Page 389 of AArch64-Reference-Manual.
|
||||
// ***************************************
|
||||
|
||||
#define SPSR_MASK_ALL (7 << 6)
|
||||
#define SPSR_EL1h (5 << 0)
|
||||
#define SPSR_VALUE (SPSR_MASK_ALL | SPSR_EL1h)
|
||||
|
||||
#endif
|
14
part15-tcpip/include/fb.h
Normal file
14
part15-tcpip/include/fb.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
void fb_init();
|
||||
void drawPixel(int x, int y, unsigned char attr);
|
||||
void drawChar(unsigned char ch, int x, int y, unsigned char attr, int zoom);
|
||||
void drawString(int x, int y, char *s, unsigned char attr, int zoom);
|
||||
void drawRect(int x1, int y1, int x2, int y2, unsigned char attr, int fill);
|
||||
void drawCircle(int x0, int y0, int radius, unsigned char attr, int fill);
|
||||
void drawLine(int x1, int y1, int x2, int y2, unsigned char attr);
|
||||
void moveRect(int oldx, int oldy, int width, int height, int shiftx, int shifty, unsigned char attr);
|
||||
void wait_msec(unsigned int n);
|
||||
void debugstr(char *str);
|
||||
void debugcrlf(void);
|
||||
void debugch(unsigned char b);
|
||||
void debughex(unsigned int d);
|
||||
int strlen(const char *str);
|
19
part15-tcpip/include/io.h
Normal file
19
part15-tcpip/include/io.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#define PERIPHERAL_BASE 0xFE000000
|
||||
#define LEGACY_BASE 0x7E000000
|
||||
#define SAFE_ADDRESS 0x00400000 // Somewhere safe to store a lot of data
|
||||
|
||||
void uart_init();
|
||||
void uart_writeText(char *buffer);
|
||||
void uart_loadOutputFifo();
|
||||
unsigned char uart_readByte();
|
||||
unsigned int uart_isReadByteReady();
|
||||
void uart_writeByteBlockingActual(unsigned char ch);
|
||||
void uart_update();
|
||||
void mmio_write(long reg, unsigned int val);
|
||||
unsigned int mmio_read(long reg);
|
||||
void gpio_useAsAlt0(unsigned int pin_number);
|
||||
void gpio_useAsAlt3(unsigned int pin_number);
|
||||
void gpio_setPinOutputBool(unsigned int pin_number, unsigned int onOrOff);
|
||||
void gpio_initOutputPinWithPullNone(unsigned int pin_number);
|
||||
void uart_hex(unsigned int d);
|
||||
void uart_byte(unsigned char b);
|
34
part15-tcpip/include/mb.h
Normal file
34
part15-tcpip/include/mb.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
extern volatile unsigned int mbox[36];
|
||||
|
||||
enum {
|
||||
MBOX_REQUEST = 0
|
||||
};
|
||||
|
||||
enum {
|
||||
MBOX_CH_POWER = 0,
|
||||
MBOX_CH_FB = 1,
|
||||
MBOX_CH_VUART = 2,
|
||||
MBOX_CH_VCHIQ = 3,
|
||||
MBOX_CH_LEDS = 4,
|
||||
MBOX_CH_BTNS = 5,
|
||||
MBOX_CH_TOUCH = 6,
|
||||
MBOX_CH_COUNT = 7,
|
||||
MBOX_CH_PROP = 8 // Request from ARM for response by VideoCore
|
||||
};
|
||||
|
||||
enum {
|
||||
MBOX_TAG_SETPOWER = 0x28001,
|
||||
MBOX_TAG_SETCLKRATE = 0x38002,
|
||||
|
||||
MBOX_TAG_SETPHYWH = 0x48003,
|
||||
MBOX_TAG_SETVIRTWH = 0x48004,
|
||||
MBOX_TAG_SETVIRTOFF = 0x48009,
|
||||
MBOX_TAG_SETDEPTH = 0x48005,
|
||||
MBOX_TAG_SETPXLORDR = 0x48006,
|
||||
MBOX_TAG_GETFB = 0x40001,
|
||||
MBOX_TAG_GETPITCH = 0x40008,
|
||||
|
||||
MBOX_TAG_LAST = 0
|
||||
};
|
||||
|
||||
unsigned int mbox_call(unsigned char ch);
|
11
part15-tcpip/include/multicore.h
Normal file
11
part15-tcpip/include/multicore.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
extern unsigned int spin_cpu0;
|
||||
extern unsigned int spin_cpu1;
|
||||
extern unsigned int spin_cpu2;
|
||||
extern unsigned int spin_cpu3;
|
||||
|
||||
void start_core1(void (*func)(void));
|
||||
void start_core2(void (*func)(void));
|
||||
void start_core3(void (*func)(void));
|
||||
void clear_core1(void);
|
||||
void clear_core2(void);
|
||||
void clear_core3(void);
|
6
part15-tcpip/include/spi.h
Normal file
6
part15-tcpip/include/spi.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
void spi_init();
|
||||
void spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int size);
|
||||
void spi_send(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_chip_select(unsigned char chip_select);
|
253
part15-tcpip/include/terminal.h
Normal file
253
part15-tcpip/include/terminal.h
Normal file
|
@ -0,0 +1,253 @@
|
|||
unsigned int vgapal[] = {
|
||||
0x000000,
|
||||
0x0000AA,
|
||||
0x00AA00,
|
||||
0x00AAAA,
|
||||
0xAA0000,
|
||||
0xAA00AA,
|
||||
0xAA5500,
|
||||
0xAAAAAA,
|
||||
0x555555,
|
||||
0x5555FF,
|
||||
0x55FF55,
|
||||
0x55FFFF,
|
||||
0xFF5555,
|
||||
0xFF55FF,
|
||||
0xFFFF55,
|
||||
0xFFFFFF
|
||||
};
|
||||
|
||||
enum {
|
||||
FONT_WIDTH = 8,
|
||||
FONT_HEIGHT = 8,
|
||||
FONT_BPG = 8, // Bytes per glyph
|
||||
FONT_BPL = 1, // Bytes per line
|
||||
FONT_NUMGLYPHS = 224
|
||||
};
|
||||
|
||||
unsigned char font[FONT_NUMGLYPHS][FONT_BPG] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
|
||||
{ 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
|
||||
{ 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
|
||||
{ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
|
||||
{ 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
|
||||
{ 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
|
||||
{ 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
|
||||
{ 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
|
||||
{ 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
|
||||
{ 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
|
||||
{ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
|
||||
{ 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
|
||||
{ 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
|
||||
{ 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
|
||||
{ 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
|
||||
{ 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
|
||||
{ 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
|
||||
{ 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
|
||||
{ 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
|
||||
{ 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
|
||||
{ 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
|
||||
{ 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
|
||||
{ 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
|
||||
{ 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
|
||||
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
|
||||
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (;)
|
||||
{ 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
|
||||
{ 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
|
||||
{ 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
|
||||
{ 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
|
||||
{ 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
|
||||
{ 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
|
||||
{ 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
|
||||
{ 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
|
||||
{ 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
|
||||
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
|
||||
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
|
||||
{ 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
|
||||
{ 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
|
||||
{ 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
|
||||
{ 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
|
||||
{ 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
|
||||
{ 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
|
||||
{ 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
|
||||
{ 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
|
||||
{ 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
|
||||
{ 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
|
||||
{ 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
|
||||
{ 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
|
||||
{ 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
|
||||
{ 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
|
||||
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
|
||||
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
|
||||
{ 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
|
||||
{ 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
|
||||
{ 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
|
||||
{ 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
|
||||
{ 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
|
||||
{ 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
|
||||
{ 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
|
||||
{ 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
|
||||
{ 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
|
||||
{ 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
|
||||
{ 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
|
||||
{ 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
|
||||
{ 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
|
||||
{ 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
|
||||
{ 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
|
||||
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
|
||||
{ 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
|
||||
{ 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
|
||||
{ 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
|
||||
{ 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
|
||||
{ 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
|
||||
{ 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
|
||||
{ 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
|
||||
{ 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
|
||||
{ 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
|
||||
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
|
||||
{ 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
|
||||
{ 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
|
||||
{ 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
|
||||
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
|
||||
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
|
||||
{ 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
|
||||
{ 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
|
||||
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
|
||||
{ 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
|
||||
{ 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
|
||||
{ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
|
||||
{ 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
|
||||
{ 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007F
|
||||
{ 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x18, 0x30, 0x1E}, // U+00C7 (C cedille)
|
||||
{ 0x00, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FC (u umlaut)
|
||||
{ 0x38, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E9 (e aigu)
|
||||
{ 0x7E, 0xC3, 0x3C, 0x60, 0x7C, 0x66, 0xFC, 0x00}, // U+00E2 (a circumflex)
|
||||
{ 0x33, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E4 (a umlaut)
|
||||
{ 0x07, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E0 (a grave)
|
||||
{ 0x0C, 0x0C, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E5 (a ring)
|
||||
{ 0x00, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+00E7 (c cedille)
|
||||
{ 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00}, // U+00EA (e circumflex)
|
||||
{ 0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00EB (e umlaut)
|
||||
{ 0x07, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E8 (e grave)
|
||||
{ 0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EF (i umlaut)
|
||||
{ 0x3E, 0x63, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EE (i circumflex)
|
||||
{ 0x07, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EC (i grave)
|
||||
{ 0x63, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x00}, // U+00C4 (A umlaut)
|
||||
{ 0x0C, 0x0C, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x00}, // U+00C5 (A ring)
|
||||
{ 0x07, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C8 (E grave)
|
||||
{ 0x00, 0x00, 0xFE, 0x30, 0xFE, 0x33, 0xFE, 0x00}, // U+00E6 (ae)
|
||||
{ 0x7C, 0x36, 0x33, 0x7F, 0x33, 0x33, 0x73, 0x00}, // U+00C6 (AE)
|
||||
{ 0x1E, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F4 (o circumflex)
|
||||
{ 0x00, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F6 (o umlaut)
|
||||
{ 0x00, 0x07, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F2 (o grave)
|
||||
{ 0x1E, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FB (u circumflex)
|
||||
{ 0x00, 0x07, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00F9 (u grave)
|
||||
{ 0x00, 0x33, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+00FF (y umlaut)
|
||||
{ 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+00D6 (O umlaut)
|
||||
{ 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+00DC (U umlaut)
|
||||
{ 0x18, 0x18, 0x7E, 0x03, 0x03, 0x7E, 0x18, 0x18}, // U+00A2 (dollarcents)
|
||||
{ 0x1C, 0x36, 0x26, 0x0F, 0x06, 0x67, 0x3F, 0x00}, // U+00A3 (pound sterling)
|
||||
{ 0x33, 0x33, 0x1E, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C}, // U+00A5 (yen)
|
||||
{ 0x7C, 0xC6, 0x1C, 0x36, 0x36, 0x1C, 0x33, 0x1E}, // U+00A7 (paragraph)
|
||||
{ 0x70, 0xD8, 0x18, 0x3C, 0x18, 0x18, 0x1B, 0x0E}, // U+0192 (dutch florijn)
|
||||
{ 0x38, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E1 (a aigu)
|
||||
{ 0x1C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00ED (i augu)
|
||||
{ 0x00, 0x38, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F3 (o aigu)
|
||||
{ 0x00, 0x38, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FA (u aigu)
|
||||
{ 0x00, 0x1F, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x00}, // U+00F1 (n ~)
|
||||
{ 0x3F, 0x00, 0x33, 0x37, 0x3F, 0x3B, 0x33, 0x00}, // U+00D1 (N ~)
|
||||
{ 0x3C, 0x36, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00}, // U+00AA (superscript a)
|
||||
{ 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00BA (superscript 0)
|
||||
{ 0x0C, 0x00, 0x0C, 0x06, 0x03, 0x33, 0x1E, 0x00}, // U+00BF (inverted ?)
|
||||
{ 0x00, 0x00, 0x00, 0x3F, 0x03, 0x03, 0x00, 0x00}, // U+2310 (gun pointing right)
|
||||
{ 0x00, 0x00, 0x00, 0x3F, 0x30, 0x30, 0x00, 0x00}, // U+00AC (gun pointing left)
|
||||
{ 0xC3, 0x63, 0x33, 0x7B, 0xCC, 0x66, 0x33, 0xF0}, // U+00BD (1/2)
|
||||
{ 0xC3, 0x63, 0x33, 0xBD, 0xEC, 0xF6, 0xF3, 0x03}, // U+00BC (1/4)
|
||||
{ 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+00A1 (inverted !)
|
||||
{ 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, // U+00AB (<<)
|
||||
{ 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, // U+00BB (>>)
|
||||
{ 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00}, // U+2591 (25% solid)
|
||||
{ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}, // U+2592 (50% solid)
|
||||
{ 0xFF, 0xAA, 0xFF, 0x55, 0xFF, 0xAA, 0xFF, 0x55}, // U+2593 (75% solid)
|
||||
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // U+2502 (thin vertical)
|
||||
{ 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08}, // U+2524 (down L, left L, up L)
|
||||
{ 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2561 (up L, down L, left D)
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14}, // U+2562 (up D, down D, left L)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14}, // U+2556 (down D, left L)
|
||||
{ 0x00, 0x00, 0x00, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2555 (down L, left D)
|
||||
{ 0x14, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14}, // U+2563 (up D, down D, left D)
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}, // U+2551 (double vertical)
|
||||
{ 0x00, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14}, // U+2557 (down D, left D)
|
||||
{ 0x14, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00}, // U+255D (up D, left D)
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00}, // U+255C (up D, left L)
|
||||
{ 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00}, // U+255B (up L, left D)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08}, // U+2510 (down L, left L)
|
||||
{ 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00}, // U+2514 (up L, right L)
|
||||
{ 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00}, // U+2534 (up L, right L, left L)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08}, // U+252C (down L, right L, left L)
|
||||
{ 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08}, // U+251C (down L, right L, up L)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, // U+2500 (thin horizontal)
|
||||
{ 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08}, // U+253C (up L, right L, left L, down L)
|
||||
{ 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+255E (up L, down L, right D)
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0xF4, 0x14, 0x14, 0x14}, // U+255F (up D, down D, right L)
|
||||
{ 0x14, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x00, 0x00}, // U+255A (up D, right D)
|
||||
{ 0x00, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14}, // U+2554 (down D, right D)
|
||||
{ 0x14, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00}, // U+2569 (left D, right D, up D)
|
||||
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14}, // U+2566 (left D, right D, down D)
|
||||
{ 0x14, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x14, 0x14}, // U+2560 (up D, down D, right D)
|
||||
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2550 (double horizontal)
|
||||
{ 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14}, // U+256C (left D, right D, down D, up D)
|
||||
{ 0x08, 0x08, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2567 (left D, right D, up L)
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x00, 0x00}, // U+2568 (left L, right L, up D)
|
||||
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x08, 0x08}, // U+2564 (left D, right D, down L)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x14, 0x14}, // U+2565 (left L, right L, down D)
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x00, 0x00}, // U+2559 (up D, right L)
|
||||
{ 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x00, 0x00}, // U+2558 (up L, right D)
|
||||
{ 0x00, 0x00, 0x00, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+2552 (down L, right D)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x14, 0x14}, // U+2553 (down D, right L)
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x14, 0x14}, // U+256B (left L, right L, down D, up D)
|
||||
{ 0x08, 0x08, 0x08, 0xFF, 0x08, 0xFF, 0x08, 0x08}, // U+256A (left D, right D, down L, up L)
|
||||
{ 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00}, // U+2518 (up L, left L)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08}, // U+250C (down L, right L)
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2588 (solid)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2584 (bottom half)
|
||||
{ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, // U+258C (left half)
|
||||
{ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, // U+2590 (right half)
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, // U+2580 (top half)
|
||||
};
|
199
part15-tcpip/kernel/arp.c
Normal file
199
part15-tcpip/kernel/arp.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
#include "../net/enc28j60.h"
|
||||
#include "../include/fb.h"
|
||||
#include "../tcpip/ip_arp_udp_tcp.h"
|
||||
|
||||
ENC_HandleTypeDef handle;
|
||||
|
||||
// Structure for Ethernet header
|
||||
|
||||
typedef struct {
|
||||
uint8_t DestAddrs[6];
|
||||
uint8_t SrcAddrs[6];
|
||||
uint16_t type;
|
||||
} EtherNetII;
|
||||
|
||||
// Ethernet packet types
|
||||
|
||||
#define ARPPACKET 0x0608
|
||||
#define IPPACKET 0x0008
|
||||
|
||||
// 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 0x0200
|
||||
#define ARPREQUEST 0x0100
|
||||
|
||||
// ARP hardware types
|
||||
|
||||
#define ETHERNET 0x0100
|
||||
|
||||
// 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, unsigned char val, unsigned short len)
|
||||
{
|
||||
uint8_t *ptr = dest;
|
||||
while (len-- > 0)
|
||||
*ptr++ = val;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, unsigned short 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
|
||||
|
||||
debugstr("Sending ARP request.");
|
||||
debugcrlf();
|
||||
enc28j60PacketSend(sizeof(ARP), &arpPacket);
|
||||
}
|
||||
|
||||
void net_test(void)
|
||||
{
|
||||
while (1) {
|
||||
while (!ENC_GetReceivedFrame(&handle));
|
||||
|
||||
uint16_t len = handle.RxFrameInfos.length;
|
||||
uint8_t *buffer = (uint8_t *)handle.RxFrameInfos.buffer;
|
||||
packetloop_arp_icmp_tcp(buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
void enc28j60PacketSend(unsigned short buflen, void *buffer) {
|
||||
if (ENC_RestoreTXBuffer(&handle, buflen) == 0) {
|
||||
ENC_WriteBuffer((unsigned char *) buffer, buflen);
|
||||
handle.transmitLength = buflen;
|
||||
ENC_Transmit(&handle);
|
||||
}
|
||||
}
|
||||
|
||||
void init_network(void)
|
||||
{
|
||||
handle.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
|
||||
handle.Init.MACAddr = myMAC;
|
||||
handle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
|
||||
handle.Init.InterruptEnableBits = EIE_LINKIE | EIE_PKTIE;
|
||||
|
||||
debugstr("Starting network up.");
|
||||
debugcrlf();
|
||||
if (!ENC_Start(&handle)) {
|
||||
debugstr("Could not initialise network card.");
|
||||
} else {
|
||||
debugstr("Setting MAC address to C0:FF:EE:C0:FF:EE.");
|
||||
debugcrlf();
|
||||
|
||||
ENC_SetMacAddr(&handle);
|
||||
|
||||
debugstr("Network card successfully initialised.");
|
||||
}
|
||||
debugcrlf();
|
||||
|
||||
debugstr("Waiting for ifup... ");
|
||||
while (!(handle.LinkStatus & PHSTAT2_LSTAT)) ENC_IRQHandler(&handle);
|
||||
debugstr("done.");
|
||||
debugcrlf();
|
||||
|
||||
debugstr("Initialising the TCP stack... ");
|
||||
init_udp_or_www_server(myMAC, deviceIP);
|
||||
debugstr("done.");
|
||||
debugcrlf();
|
||||
|
||||
// Re-enable global interrupts
|
||||
ENC_EnableInterrupts(EIE_INTIE);
|
||||
}
|
58
part15-tcpip/kernel/irq.c
Normal file
58
part15-tcpip/kernel/irq.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
#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() {
|
||||
REGS_IRQ->irq0_enable_0 = SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3;
|
||||
}
|
||||
|
||||
void disable_interrupt_controller() {
|
||||
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() {
|
||||
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
||||
|
||||
while(irq) {
|
||||
if (irq & SYS_TIMER_IRQ_1) {
|
||||
irq &= ~SYS_TIMER_IRQ_1;
|
||||
|
||||
handle_timer_1();
|
||||
}
|
||||
|
||||
if (irq & SYS_TIMER_IRQ_3) {
|
||||
irq &= ~SYS_TIMER_IRQ_3;
|
||||
|
||||
handle_timer_3();
|
||||
}
|
||||
}
|
||||
}
|
156
part15-tcpip/kernel/irqentry.S
Normal file
156
part15-tcpip/kernel/irqentry.S
Normal file
|
@ -0,0 +1,156 @@
|
|||
#define SYNC_INVALID_EL1t 0
|
||||
#define IRQ_INVALID_EL1t 1
|
||||
#define FIQ_INVALID_EL1t 2
|
||||
#define ERROR_INVALID_EL1t 3
|
||||
|
||||
#define SYNC_INVALID_EL1h 4
|
||||
#define IRQ_INVALID_EL1h 5
|
||||
#define FIQ_INVALID_EL1h 6
|
||||
#define ERROR_INVALID_EL1h 7
|
||||
|
||||
#define SYNC_INVALID_EL0_64 8
|
||||
#define IRQ_INVALID_EL0_64 9
|
||||
#define FIQ_INVALID_EL0_64 10
|
||||
#define ERROR_INVALID_EL0_64 11
|
||||
|
||||
#define SYNC_INVALID_EL0_32 12
|
||||
#define IRQ_INVALID_EL0_32 13
|
||||
#define FIQ_INVALID_EL0_32 14
|
||||
#define ERROR_INVALID_EL0_32 15
|
||||
|
||||
//stack frame size
|
||||
#define S_FRAME_SIZE 256
|
||||
|
||||
.macro kernel_entry
|
||||
sub sp, sp, #S_FRAME_SIZE
|
||||
stp x0, x1, [sp, #16 * 0]
|
||||
stp x2, x3, [sp, #16 * 1]
|
||||
stp x4, x5, [sp, #16 * 2]
|
||||
stp x6, x7, [sp, #16 * 3]
|
||||
stp x8, x9, [sp, #16 * 4]
|
||||
stp x10, x11, [sp, #16 * 5]
|
||||
stp x12, x13, [sp, #16 * 6]
|
||||
stp x14, x15, [sp, #16 * 7]
|
||||
stp x16, x17, [sp, #16 * 8]
|
||||
stp x18, x19, [sp, #16 * 9]
|
||||
stp x20, x21, [sp, #16 * 10]
|
||||
stp x22, x23, [sp, #16 * 11]
|
||||
stp x24, x25, [sp, #16 * 12]
|
||||
stp x26, x27, [sp, #16 * 13]
|
||||
stp x28, x29, [sp, #16 * 14]
|
||||
str x30, [sp, #16 * 15]
|
||||
.endm
|
||||
|
||||
.macro kernel_exit
|
||||
ldp x0, x1, [sp, #16 * 0]
|
||||
ldp x2, x3, [sp, #16 * 1]
|
||||
ldp x4, x5, [sp, #16 * 2]
|
||||
ldp x6, x7, [sp, #16 * 3]
|
||||
ldp x8, x9, [sp, #16 * 4]
|
||||
ldp x10, x11, [sp, #16 * 5]
|
||||
ldp x12, x13, [sp, #16 * 6]
|
||||
ldp x14, x15, [sp, #16 * 7]
|
||||
ldp x16, x17, [sp, #16 * 8]
|
||||
ldp x18, x19, [sp, #16 * 9]
|
||||
ldp x20, x21, [sp, #16 * 10]
|
||||
ldp x22, x23, [sp, #16 * 11]
|
||||
ldp x24, x25, [sp, #16 * 12]
|
||||
ldp x26, x27, [sp, #16 * 13]
|
||||
ldp x28, x29, [sp, #16 * 14]
|
||||
ldr x30, [sp, #16 * 15]
|
||||
add sp, sp, #S_FRAME_SIZE
|
||||
eret
|
||||
.endm
|
||||
|
||||
.macro handle_invalid_entry type
|
||||
kernel_entry
|
||||
mov x0, #\type
|
||||
mrs x1, esr_el1
|
||||
mrs x2, elr_el1
|
||||
bl show_invalid_entry_message
|
||||
|
||||
b err_hang
|
||||
.endm
|
||||
|
||||
.macro ventry label
|
||||
.align 7
|
||||
b \label
|
||||
.endm
|
||||
|
||||
//Exception vectors table
|
||||
.align 11
|
||||
.globl vectors
|
||||
vectors:
|
||||
ventry sync_invalid_el1t // Synchronous EL1t
|
||||
ventry irq_invalid_el1t // IRQ EL1t
|
||||
ventry fiq_invalid_el1t // FIQ EL1t
|
||||
ventry error_invalid_el1t // Error EL1t
|
||||
|
||||
ventry sync_invalid_el1h // Synchronous EL1h
|
||||
ventry handle_el1_irq // IRQ EL1h
|
||||
ventry fiq_invalid_el1h // FIQ EL1h
|
||||
ventry error_invalid_el1h // Error EL1h
|
||||
|
||||
ventry sync_invalid_el0_64 // Synchronous 64-bit EL0
|
||||
ventry irq_invalid_el0_64 // IRQ 64-bit EL0
|
||||
ventry fiq_invalid_el0_64 // FIQ 64-bit EL0
|
||||
ventry error_invalid_el0_64 // Error 64-bit EL0
|
||||
|
||||
ventry sync_invalid_el0_32 // Synchronous 32-bit EL0
|
||||
ventry irq_invalid_el0_32 // IRQ 32-bit EL0
|
||||
ventry fiq_invalid_el0_32 // FIQ 32-bit EL0
|
||||
ventry error_invalid_el0_32 // Error 32-bit EL0
|
||||
|
||||
|
||||
sync_invalid_el1t:
|
||||
handle_invalid_entry SYNC_INVALID_EL1t
|
||||
|
||||
irq_invalid_el1t:
|
||||
handle_invalid_entry IRQ_INVALID_EL1t
|
||||
|
||||
fiq_invalid_el1t:
|
||||
handle_invalid_entry FIQ_INVALID_EL1t
|
||||
|
||||
error_invalid_el1t:
|
||||
handle_invalid_entry ERROR_INVALID_EL1t
|
||||
|
||||
sync_invalid_el1h:
|
||||
handle_invalid_entry SYNC_INVALID_EL1h
|
||||
|
||||
fiq_invalid_el1h:
|
||||
handle_invalid_entry FIQ_INVALID_EL1h
|
||||
|
||||
error_invalid_el1h:
|
||||
handle_invalid_entry ERROR_INVALID_EL1h
|
||||
|
||||
sync_invalid_el0_64:
|
||||
handle_invalid_entry SYNC_INVALID_EL0_64
|
||||
|
||||
irq_invalid_el0_64:
|
||||
handle_invalid_entry IRQ_INVALID_EL0_64
|
||||
|
||||
fiq_invalid_el0_64:
|
||||
handle_invalid_entry FIQ_INVALID_EL0_64
|
||||
|
||||
error_invalid_el0_64:
|
||||
handle_invalid_entry ERROR_INVALID_EL0_64
|
||||
|
||||
sync_invalid_el0_32:
|
||||
handle_invalid_entry SYNC_INVALID_EL0_32
|
||||
|
||||
irq_invalid_el0_32:
|
||||
handle_invalid_entry IRQ_INVALID_EL0_32
|
||||
|
||||
fiq_invalid_el0_32:
|
||||
handle_invalid_entry FIQ_INVALID_EL0_32
|
||||
|
||||
error_invalid_el0_32:
|
||||
handle_invalid_entry ERROR_INVALID_EL0_32
|
||||
|
||||
handle_el1_irq:
|
||||
kernel_entry
|
||||
bl handle_irq
|
||||
kernel_exit
|
||||
|
||||
.globl err_hang
|
||||
err_hang: b err_hang
|
176
part15-tcpip/kernel/kernel.c
Normal file
176
part15-tcpip/kernel/kernel.c
Normal file
|
@ -0,0 +1,176 @@
|
|||
#include "../include/fb.h"
|
||||
#include "../include/io.h"
|
||||
#include "../include/spi.h"
|
||||
#include "../include/multicore.h"
|
||||
#include "../net/enc28j60.h"
|
||||
#include "kernel.h"
|
||||
|
||||
void initProgress(void)
|
||||
{
|
||||
drawRect(0, 0, 301, 50, 0x0f, 0);
|
||||
drawString(309, 21, "Core 0", 0x0f, 1);
|
||||
|
||||
drawRect(0, 60, 301, 110, 0x0f, 0);
|
||||
drawString(309, 81, "Core 1", 0x0f, 1);
|
||||
|
||||
drawRect(0, 120, 301, 170, 0x0f, 0);
|
||||
drawString(309, 141, "Timer 1", 0x0f, 1);
|
||||
|
||||
drawRect(0, 180, 301, 230, 0x0f, 0);
|
||||
drawString(309, 201, "Timer 3", 0x0f, 1);
|
||||
}
|
||||
|
||||
void drawProgress(unsigned int core, unsigned int val) {
|
||||
unsigned char col = (core + 1) + ((core + 1) << 4);
|
||||
|
||||
// val should be 0-100
|
||||
if (val == 0) drawRect(1, (60 * core) + 1, 300, (60 * core) + 49, 0x00, 1);
|
||||
if (val > 0) drawRect(1, (60 * core) + 1, (val * 3), (60 * core) + 49, col, 1);
|
||||
}
|
||||
|
||||
void core3_main(void) {
|
||||
clear_core3(); // Only run once
|
||||
|
||||
// Test the network card
|
||||
|
||||
spi_init();
|
||||
init_network();
|
||||
net_test();
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
void core0_main(void)
|
||||
{
|
||||
unsigned int core0_val = 0;
|
||||
|
||||
while (core0_val <= 100) {
|
||||
wait_msec(0x100000);
|
||||
drawProgress(0, core0_val);
|
||||
core0_val++;
|
||||
}
|
||||
|
||||
debugstr("Core 0 done.");
|
||||
debugcrlf();
|
||||
}
|
||||
|
||||
void core1_main(void)
|
||||
{
|
||||
unsigned int core1_val = 0;
|
||||
|
||||
clear_core1(); // Only run once
|
||||
|
||||
while (core1_val <= 100) {
|
||||
wait_msec(0x3FFFF);
|
||||
drawProgress(1, core1_val);
|
||||
core1_val++;
|
||||
}
|
||||
|
||||
debugstr("Core 1 done.");
|
||||
debugcrlf();
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
// TIMER FUNCTIONS
|
||||
|
||||
const unsigned int timer1_int = CLOCKHZ;
|
||||
const unsigned int timer3_int = CLOCKHZ / 4;
|
||||
unsigned int timer1_val = 0;
|
||||
unsigned int timer3_val = 0;
|
||||
|
||||
void timer_init() {
|
||||
timer1_val = REGS_TIMER->counter_lo;
|
||||
timer1_val += timer1_int;
|
||||
REGS_TIMER->compare[1] = timer1_val;
|
||||
|
||||
timer3_val = REGS_TIMER->counter_lo;
|
||||
timer3_val += timer3_int;
|
||||
REGS_TIMER->compare[3] = timer3_val;
|
||||
}
|
||||
|
||||
void handle_timer_1() {
|
||||
timer1_val += timer1_int;
|
||||
REGS_TIMER->compare[1] = timer1_val;
|
||||
REGS_TIMER->control_status |= SYS_TIMER_IRQ_1;
|
||||
|
||||
unsigned int progval = timer1_val / timer1_int;
|
||||
if (progval <= 100) {
|
||||
drawProgress(2, progval);
|
||||
} else {
|
||||
debugstr("Timer 1 done.");
|
||||
debugcrlf();
|
||||
}
|
||||
}
|
||||
|
||||
void handle_timer_3() {
|
||||
timer3_val += timer3_int;
|
||||
REGS_TIMER->compare[3] = timer3_val;
|
||||
REGS_TIMER->control_status |= SYS_TIMER_IRQ_3;
|
||||
|
||||
unsigned int progval = timer3_val / timer3_int;
|
||||
if (progval <= 100) drawProgress(3, progval);
|
||||
}
|
||||
|
||||
unsigned long timer_get_ticks() {
|
||||
unsigned int hi = REGS_TIMER->counter_hi;
|
||||
unsigned int lo = REGS_TIMER->counter_lo;
|
||||
|
||||
//double check hi value didn't change after setting it...
|
||||
if (hi != REGS_TIMER->counter_hi) {
|
||||
hi = REGS_TIMER->counter_hi;
|
||||
lo = REGS_TIMER->counter_lo;
|
||||
}
|
||||
|
||||
return ((unsigned long)hi << 32) | lo;
|
||||
}
|
||||
|
||||
void timer_sleep(unsigned int ms) {
|
||||
unsigned long start = timer_get_ticks();
|
||||
|
||||
while(timer_get_ticks() < start + (ms * 1000));
|
||||
}
|
||||
|
||||
void HAL_Delay(volatile unsigned int Delay) {
|
||||
timer_sleep(Delay);
|
||||
}
|
||||
|
||||
unsigned int HAL_GetTick(void) {
|
||||
return timer_get_ticks();
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
fb_init();
|
||||
|
||||
unsigned int i=0;
|
||||
while (i++<30) debugcrlf();
|
||||
|
||||
initProgress();
|
||||
|
||||
// Kick it off on core 1
|
||||
|
||||
start_core1(core1_main);
|
||||
|
||||
// Kick off the timers
|
||||
|
||||
irq_init_vectors();
|
||||
enable_interrupt_controller();
|
||||
irq_enable();
|
||||
timer_init();
|
||||
|
||||
// Kick it off on core 3
|
||||
|
||||
start_core3(core3_main);
|
||||
|
||||
// Kick it off on core 0
|
||||
|
||||
core0_main();
|
||||
|
||||
// Disable IRQs and loop endlessly
|
||||
|
||||
irq_disable();
|
||||
disable_interrupt_controller();
|
||||
|
||||
while(1);
|
||||
}
|
56
part15-tcpip/kernel/kernel.h
Normal file
56
part15-tcpip/kernel/kernel.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#define PERIPHERAL_BASE 0xFE000000
|
||||
#define CLOCKHZ 1000000
|
||||
|
||||
struct timer_regs {
|
||||
volatile unsigned int control_status;
|
||||
volatile unsigned int counter_lo;
|
||||
volatile unsigned int counter_hi;
|
||||
volatile unsigned int compare[4];
|
||||
};
|
||||
|
||||
#define REGS_TIMER ((struct timer_regs *)(PERIPHERAL_BASE + 0x00003000))
|
||||
|
||||
struct arm_irq_regs_2711 {
|
||||
volatile unsigned int irq0_pending_0;
|
||||
volatile unsigned int irq0_pending_1;
|
||||
volatile unsigned int irq0_pending_2;
|
||||
volatile unsigned int res0;
|
||||
volatile unsigned int irq0_enable_0;
|
||||
volatile unsigned int irq0_enable_1;
|
||||
volatile unsigned int irq0_enable_2;
|
||||
volatile unsigned int res1;
|
||||
volatile unsigned int irq0_disable_0;
|
||||
volatile unsigned int irq0_disable_1;
|
||||
volatile unsigned int irq0_disable_2;
|
||||
};
|
||||
|
||||
typedef struct arm_irq_regs_2711 arm_irq_regs;
|
||||
|
||||
#define REGS_IRQ ((arm_irq_regs *)(PERIPHERAL_BASE + 0x0000B200))
|
||||
|
||||
enum vc_irqs {
|
||||
SYS_TIMER_IRQ_0 = 1,
|
||||
SYS_TIMER_IRQ_1 = 2,
|
||||
SYS_TIMER_IRQ_2 = 4,
|
||||
SYS_TIMER_IRQ_3 = 8,
|
||||
AUX_IRQ = (1 << 29)
|
||||
};
|
||||
|
||||
void irq_init_vectors();
|
||||
void irq_enable();
|
||||
void irq_disable();
|
||||
void enable_interrupt_controller();
|
||||
void disable_interrupt_controller();
|
||||
|
||||
void handle_timer_1();
|
||||
void handle_timer_3();
|
||||
|
||||
unsigned long timer_get_ticks();
|
||||
void timer_sleep(unsigned int ms);
|
||||
void HAL_Delay(volatile unsigned int Delay);
|
||||
unsigned int HAL_GetTick(void);
|
||||
|
||||
void init_network(void);
|
||||
void net_test(void);
|
||||
void enc28j60PacketSend(unsigned short buflen, void *buffer);
|
||||
void *memcpy(void *dest, const void *src, unsigned short len);
|
15
part15-tcpip/kernel/utils.S
Normal file
15
part15-tcpip/kernel/utils.S
Normal file
|
@ -0,0 +1,15 @@
|
|||
.globl irq_init_vectors
|
||||
irq_init_vectors:
|
||||
adr x0, vectors
|
||||
msr vbar_el1, x0
|
||||
ret
|
||||
|
||||
.globl irq_enable
|
||||
irq_enable:
|
||||
msr daifclr, #2
|
||||
ret
|
||||
|
||||
.globl irq_disable
|
||||
irq_disable:
|
||||
msr daifset, #2
|
||||
ret
|
260
part15-tcpip/lib/fb.c
Normal file
260
part15-tcpip/lib/fb.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
#include "../include/io.h"
|
||||
#include "../include/mb.h"
|
||||
#include "../include/terminal.h"
|
||||
|
||||
unsigned int width, height, pitch, isrgb;
|
||||
unsigned char *fb;
|
||||
|
||||
int curx = 0;
|
||||
int cury = 0;
|
||||
|
||||
void fb_init()
|
||||
{
|
||||
mbox[0] = 35*4; // Length of message in bytes
|
||||
mbox[1] = MBOX_REQUEST;
|
||||
|
||||
mbox[2] = MBOX_TAG_SETPHYWH; // Tag identifier
|
||||
mbox[3] = 8; // Value size in bytes
|
||||
mbox[4] = 0;
|
||||
mbox[5] = 1920; // Value(width)
|
||||
mbox[6] = 1080; // Value(height)
|
||||
|
||||
mbox[7] = MBOX_TAG_SETVIRTWH;
|
||||
mbox[8] = 8;
|
||||
mbox[9] = 8;
|
||||
mbox[10] = 1920;
|
||||
mbox[11] = 1080;
|
||||
|
||||
mbox[12] = MBOX_TAG_SETVIRTOFF;
|
||||
mbox[13] = 8;
|
||||
mbox[14] = 8;
|
||||
mbox[15] = 0; // Value(x)
|
||||
mbox[16] = 0; // Value(y)
|
||||
|
||||
mbox[17] = MBOX_TAG_SETDEPTH;
|
||||
mbox[18] = 4;
|
||||
mbox[19] = 4;
|
||||
mbox[20] = 32; // Bits per pixel
|
||||
|
||||
mbox[21] = MBOX_TAG_SETPXLORDR;
|
||||
mbox[22] = 4;
|
||||
mbox[23] = 4;
|
||||
mbox[24] = 1; // RGB
|
||||
|
||||
mbox[25] = MBOX_TAG_GETFB;
|
||||
mbox[26] = 8;
|
||||
mbox[27] = 8;
|
||||
mbox[28] = 4096; // FrameBufferInfo.pointer
|
||||
mbox[29] = 0; // FrameBufferInfo.size
|
||||
|
||||
mbox[30] = MBOX_TAG_GETPITCH;
|
||||
mbox[31] = 4;
|
||||
mbox[32] = 4;
|
||||
mbox[33] = 0; // Bytes per line
|
||||
|
||||
mbox[34] = MBOX_TAG_LAST;
|
||||
|
||||
// Check call is successful and we have a pointer with depth 32
|
||||
if (mbox_call(MBOX_CH_PROP) && mbox[20] == 32 && mbox[28] != 0) {
|
||||
mbox[28] &= 0x3FFFFFFF; // Convert GPU address to ARM address
|
||||
width = mbox[10]; // Actual physical width
|
||||
height = mbox[11]; // Actual physical height
|
||||
pitch = mbox[33]; // Number of bytes per line
|
||||
isrgb = mbox[24]; // Pixel order
|
||||
fb = (unsigned char *)((long)mbox[28]);
|
||||
}
|
||||
}
|
||||
|
||||
void drawPixel(int x, int y, unsigned char attr)
|
||||
{
|
||||
int offs = (y * pitch) + (x * 4);
|
||||
*((unsigned int*)(fb + offs)) = vgapal[attr & 0x0f];
|
||||
}
|
||||
|
||||
void drawRect(int x1, int y1, int x2, int y2, unsigned char attr, int fill)
|
||||
{
|
||||
int y=y1;
|
||||
|
||||
while (y <= y2) {
|
||||
int x=x1;
|
||||
while (x <= x2) {
|
||||
if ((x == x1 || x == x2) || (y == y1 || y == y2)) drawPixel(x, y, attr);
|
||||
else if (fill) drawPixel(x, y, (attr & 0xf0) >> 4);
|
||||
x++;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
void drawLine(int x1, int y1, int x2, int y2, unsigned char attr)
|
||||
{
|
||||
int dx, dy, p, x, y;
|
||||
|
||||
dx = x2-x1;
|
||||
dy = y2-y1;
|
||||
x = x1;
|
||||
y = y1;
|
||||
p = 2*dy-dx;
|
||||
|
||||
while (x<x2) {
|
||||
if (p >= 0) {
|
||||
drawPixel(x,y,attr);
|
||||
y++;
|
||||
p = p+2*dy-2*dx;
|
||||
} else {
|
||||
drawPixel(x,y,attr);
|
||||
p = p+2*dy;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void drawCircle(int x0, int y0, int radius, unsigned char attr, int fill)
|
||||
{
|
||||
int x = radius;
|
||||
int y = 0;
|
||||
int err = 0;
|
||||
|
||||
while (x >= y) {
|
||||
if (fill) {
|
||||
drawLine(x0 - y, y0 + x, x0 + y, y0 + x, (attr & 0xf0) >> 4);
|
||||
drawLine(x0 - x, y0 + y, x0 + x, y0 + y, (attr & 0xf0) >> 4);
|
||||
drawLine(x0 - x, y0 - y, x0 + x, y0 - y, (attr & 0xf0) >> 4);
|
||||
drawLine(x0 - y, y0 - x, x0 + y, y0 - x, (attr & 0xf0) >> 4);
|
||||
}
|
||||
drawPixel(x0 - y, y0 + x, attr);
|
||||
drawPixel(x0 + y, y0 + x, attr);
|
||||
drawPixel(x0 - x, y0 + y, attr);
|
||||
drawPixel(x0 + x, y0 + y, attr);
|
||||
drawPixel(x0 - x, y0 - y, attr);
|
||||
drawPixel(x0 + x, y0 - y, attr);
|
||||
drawPixel(x0 - y, y0 - x, attr);
|
||||
drawPixel(x0 + y, y0 - x, attr);
|
||||
|
||||
if (err <= 0) {
|
||||
y += 1;
|
||||
err += 2*y + 1;
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
x -= 1;
|
||||
err -= 2*x + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawChar(unsigned char ch, int x, int y, unsigned char attr, int zoom)
|
||||
{
|
||||
unsigned char *glyph = (unsigned char *)&font + (ch < FONT_NUMGLYPHS ? ch : 0) * FONT_BPG;
|
||||
|
||||
for (int i=1;i<=(FONT_HEIGHT*zoom);i++) {
|
||||
for (int j=0;j<(FONT_WIDTH*zoom);j++) {
|
||||
unsigned char mask = 1 << (j/zoom);
|
||||
unsigned char col = (*glyph & mask) ? attr & 0x0f : (attr & 0xf0) >> 4;
|
||||
|
||||
drawPixel(x+j, y+i, col);
|
||||
}
|
||||
glyph += (i%zoom) ? 0 : FONT_BPL;
|
||||
}
|
||||
}
|
||||
|
||||
void drawString(int x, int y, char *s, unsigned char attr, int zoom)
|
||||
{
|
||||
while (*s) {
|
||||
if (*s == '\r') {
|
||||
x = 0;
|
||||
} else if(*s == '\n') {
|
||||
x = 0; y += (FONT_HEIGHT*zoom);
|
||||
} else {
|
||||
drawChar(*s, x, y, attr, zoom);
|
||||
x += (FONT_WIDTH*zoom);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
void moveRect(int oldx, int oldy, int width, int height, int shiftx, int shifty, unsigned char attr)
|
||||
{
|
||||
unsigned int newx = oldx + shiftx, newy = oldy + shifty;
|
||||
unsigned int xcount = 0, ycount = 0;
|
||||
unsigned int bitmap[width][height]; // This is very unsafe if it's too big for the stack...
|
||||
unsigned int offs;
|
||||
|
||||
// Save the bitmap
|
||||
while (xcount < width) {
|
||||
while (ycount < height) {
|
||||
offs = ((oldy + ycount) * pitch) + ((oldx + xcount) * 4);
|
||||
|
||||
bitmap[xcount][ycount] = *((unsigned int*)(fb + offs));
|
||||
ycount++;
|
||||
}
|
||||
ycount=0;
|
||||
xcount++;
|
||||
}
|
||||
// Wipe it out with background colour
|
||||
drawRect(oldx, oldy, oldx + width, oldy + width, attr, 1);
|
||||
// Draw it again
|
||||
for (int i=newx;i<newx + width;i++) {
|
||||
for (int j=newy;j<newy + height;j++) {
|
||||
offs = (j * pitch) + (i * 4);
|
||||
*((unsigned int*)(fb + offs)) = bitmap[i-newx][j-newy];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wait_msec(unsigned int n)
|
||||
{
|
||||
register unsigned long f, t, r;
|
||||
|
||||
// Get the current counter frequency
|
||||
asm volatile ("mrs %0, cntfrq_el0" : "=r"(f));
|
||||
// Read the current counter
|
||||
asm volatile ("mrs %0, cntpct_el0" : "=r"(t));
|
||||
// Calculate expire value for counter
|
||||
t+=((f/1000)*n)/1000;
|
||||
do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r<t);
|
||||
}
|
||||
|
||||
int strlen(const char *str) {
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s; ++s);
|
||||
return (s - str);
|
||||
}
|
||||
|
||||
void debugstr(char *str) {
|
||||
if (curx + (strlen(str) * 8) >= 1920) {
|
||||
curx = 0; cury += 8;
|
||||
}
|
||||
if (cury + 8 >= 1080) {
|
||||
cury = 0;
|
||||
}
|
||||
drawString(curx, cury, str, 0x0f, 1);
|
||||
curx += (strlen(str) * 8);
|
||||
}
|
||||
|
||||
void debugcrlf(void) {
|
||||
curx = 0; cury += 8;
|
||||
}
|
||||
|
||||
void debugch(unsigned char b) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=4;c>=0;c-=4) {
|
||||
n=(b>>c)&0xF;
|
||||
n+=n>9?0x37:0x30;
|
||||
debugstr((char *)&n);
|
||||
}
|
||||
debugstr(" ");
|
||||
}
|
||||
|
||||
void debughex(unsigned int d) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=28;c>=0;c-=4) {
|
||||
n=(d>>c)&0xF;
|
||||
n+=n>9?0x37:0x30;
|
||||
debugstr((char *)&n);
|
||||
}
|
||||
debugstr(" ");
|
||||
}
|
199
part15-tcpip/lib/io.c
Normal file
199
part15-tcpip/lib/io.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
#include "../include/io.h"
|
||||
|
||||
// GPIO
|
||||
|
||||
enum {
|
||||
GPFSEL0 = PERIPHERAL_BASE + 0x200000,
|
||||
GPSET0 = PERIPHERAL_BASE + 0x20001C,
|
||||
GPCLR0 = PERIPHERAL_BASE + 0x200028,
|
||||
GPPUPPDN0 = PERIPHERAL_BASE + 0x2000E4
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIO_MAX_PIN = 53,
|
||||
GPIO_FUNCTION_OUT = 1,
|
||||
GPIO_FUNCTION_ALT5 = 2,
|
||||
GPIO_FUNCTION_ALT3 = 7,
|
||||
GPIO_FUNCTION_ALT0 = 4
|
||||
};
|
||||
|
||||
enum {
|
||||
Pull_None = 0,
|
||||
Pull_Down = 1, // Are down and up the right way around?
|
||||
Pull_Up = 2
|
||||
};
|
||||
|
||||
void mmio_write(long reg, unsigned int val) { *(volatile unsigned int *)reg = val; }
|
||||
unsigned int mmio_read(long reg) { return *(volatile unsigned int *)reg; }
|
||||
|
||||
unsigned int gpio_call(unsigned int pin_number, unsigned int value, unsigned int base, unsigned int field_size, unsigned int field_max) {
|
||||
unsigned int field_mask = (1 << field_size) - 1;
|
||||
|
||||
if (pin_number > field_max) return 0;
|
||||
if (value > field_mask) return 0;
|
||||
|
||||
unsigned int num_fields = 32 / field_size;
|
||||
unsigned int reg = base + ((pin_number / num_fields) * 4);
|
||||
unsigned int shift = (pin_number % num_fields) * field_size;
|
||||
|
||||
unsigned int curval = mmio_read(reg);
|
||||
curval &= ~(field_mask << shift);
|
||||
curval |= value << shift;
|
||||
mmio_write(reg, curval);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int gpio_set (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPSET0, 1, GPIO_MAX_PIN); }
|
||||
unsigned int gpio_clear (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPCLR0, 1, GPIO_MAX_PIN); }
|
||||
unsigned int gpio_pull (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPPUPPDN0, 2, GPIO_MAX_PIN); }
|
||||
unsigned int gpio_function(unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPFSEL0, 3, GPIO_MAX_PIN); }
|
||||
|
||||
void gpio_useAsAlt0(unsigned int pin_number) {
|
||||
gpio_pull(pin_number, Pull_None);
|
||||
gpio_function(pin_number, GPIO_FUNCTION_ALT0);
|
||||
}
|
||||
|
||||
void gpio_useAsAlt3(unsigned int pin_number) {
|
||||
gpio_pull(pin_number, Pull_None);
|
||||
gpio_function(pin_number, GPIO_FUNCTION_ALT3);
|
||||
}
|
||||
|
||||
void gpio_useAsAlt5(unsigned int pin_number) {
|
||||
gpio_pull(pin_number, Pull_None);
|
||||
gpio_function(pin_number, GPIO_FUNCTION_ALT5);
|
||||
}
|
||||
|
||||
void gpio_initOutputPinWithPullNone(unsigned int pin_number) {
|
||||
gpio_pull(pin_number, Pull_None);
|
||||
gpio_function(pin_number, GPIO_FUNCTION_OUT);
|
||||
}
|
||||
|
||||
void gpio_setPinOutputBool(unsigned int pin_number, unsigned int onOrOff) {
|
||||
if (onOrOff) {
|
||||
gpio_set(pin_number, 1);
|
||||
} else {
|
||||
gpio_clear(pin_number, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// UART
|
||||
|
||||
enum {
|
||||
AUX_BASE = PERIPHERAL_BASE + 0x215000,
|
||||
AUX_IRQ = AUX_BASE,
|
||||
AUX_ENABLES = AUX_BASE + 4,
|
||||
AUX_MU_IO_REG = AUX_BASE + 64,
|
||||
AUX_MU_IER_REG = AUX_BASE + 68,
|
||||
AUX_MU_IIR_REG = AUX_BASE + 72,
|
||||
AUX_MU_LCR_REG = AUX_BASE + 76,
|
||||
AUX_MU_MCR_REG = AUX_BASE + 80,
|
||||
AUX_MU_LSR_REG = AUX_BASE + 84,
|
||||
AUX_MU_MSR_REG = AUX_BASE + 88,
|
||||
AUX_MU_SCRATCH = AUX_BASE + 92,
|
||||
AUX_MU_CNTL_REG = AUX_BASE + 96,
|
||||
AUX_MU_STAT_REG = AUX_BASE + 100,
|
||||
AUX_MU_BAUD_REG = AUX_BASE + 104,
|
||||
AUX_UART_CLOCK = 500000000,
|
||||
UART_MAX_QUEUE = 16 * 1024
|
||||
};
|
||||
|
||||
#define AUX_MU_BAUD(baud) ((AUX_UART_CLOCK/(baud*8))-1)
|
||||
|
||||
unsigned char uart_output_queue[UART_MAX_QUEUE];
|
||||
unsigned int uart_output_queue_write = 0;
|
||||
unsigned int uart_output_queue_read = 0;
|
||||
|
||||
void uart_init() {
|
||||
mmio_write(AUX_ENABLES, 1); //enable UART1
|
||||
mmio_write(AUX_MU_IER_REG, 0);
|
||||
mmio_write(AUX_MU_CNTL_REG, 0);
|
||||
mmio_write(AUX_MU_LCR_REG, 3); //8 bits
|
||||
mmio_write(AUX_MU_MCR_REG, 0);
|
||||
mmio_write(AUX_MU_IER_REG, 0);
|
||||
mmio_write(AUX_MU_IIR_REG, 0xC6); //disable interrupts
|
||||
mmio_write(AUX_MU_BAUD_REG, AUX_MU_BAUD(115200));
|
||||
gpio_useAsAlt5(14);
|
||||
gpio_useAsAlt5(15);
|
||||
mmio_write(AUX_MU_CNTL_REG, 3); //enable RX/TX
|
||||
}
|
||||
|
||||
unsigned int uart_isOutputQueueEmpty() {
|
||||
return uart_output_queue_read == uart_output_queue_write;
|
||||
}
|
||||
|
||||
unsigned int uart_isReadByteReady() { return mmio_read(AUX_MU_LSR_REG) & 0x01; }
|
||||
unsigned int uart_isWriteByteReady() { return mmio_read(AUX_MU_LSR_REG) & 0x20; }
|
||||
|
||||
unsigned char uart_readByte() {
|
||||
while (!uart_isReadByteReady());
|
||||
return (unsigned char)mmio_read(AUX_MU_IO_REG);
|
||||
}
|
||||
|
||||
void uart_writeByteBlockingActual(unsigned char ch) {
|
||||
while (!uart_isWriteByteReady());
|
||||
mmio_write(AUX_MU_IO_REG, (unsigned int)ch);
|
||||
}
|
||||
|
||||
void uart_loadOutputFifo() {
|
||||
while (!uart_isOutputQueueEmpty() && uart_isWriteByteReady()) {
|
||||
uart_writeByteBlockingActual(uart_output_queue[uart_output_queue_read]);
|
||||
uart_output_queue_read = (uart_output_queue_read + 1) & (UART_MAX_QUEUE - 1); // Don't overrun
|
||||
}
|
||||
}
|
||||
|
||||
void uart_writeByteBlocking(unsigned char ch) {
|
||||
unsigned int next = (uart_output_queue_write + 1) & (UART_MAX_QUEUE - 1); // Don't overrun
|
||||
|
||||
while (next == uart_output_queue_read) uart_loadOutputFifo();
|
||||
|
||||
uart_output_queue[uart_output_queue_write] = ch;
|
||||
uart_output_queue_write = next;
|
||||
}
|
||||
|
||||
void uart_writeText(char *buffer) {
|
||||
while (*buffer) {
|
||||
if (*buffer == '\n') uart_writeByteBlockingActual('\r');
|
||||
uart_writeByteBlockingActual(*buffer++);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_drainOutputQueue() {
|
||||
while (!uart_isOutputQueueEmpty()) uart_loadOutputFifo();
|
||||
}
|
||||
|
||||
void uart_update() {
|
||||
uart_loadOutputFifo();
|
||||
|
||||
if (uart_isReadByteReady()) {
|
||||
unsigned char ch = uart_readByte();
|
||||
if (ch == '\r') uart_writeText("\n"); else uart_writeByteBlocking(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_hex(unsigned int d) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=28;c>=0;c-=4) {
|
||||
// get highest tetrad
|
||||
n=(d>>c)&0xF;
|
||||
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
|
||||
n+=n>9?0x37:0x30;
|
||||
|
||||
uart_writeByteBlockingActual(n);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_byte(unsigned char b) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=4;c>=0;c-=4) {
|
||||
// get highest tetrad
|
||||
n=(b>>c)&0xF;
|
||||
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
|
||||
n+=n>9?0x37:0x30;
|
||||
|
||||
uart_writeByteBlockingActual(n);
|
||||
}
|
||||
uart_writeByteBlockingActual(' ');
|
||||
}
|
39
part15-tcpip/lib/mb.c
Normal file
39
part15-tcpip/lib/mb.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "../include/io.h"
|
||||
|
||||
// The buffer must be 16-byte aligned as only the upper 28 bits of the address can be passed via the mailbox
|
||||
volatile unsigned int __attribute__((aligned(16))) mbox[36];
|
||||
|
||||
enum {
|
||||
VIDEOCORE_MBOX = (PERIPHERAL_BASE + 0x0000B880),
|
||||
MBOX_READ = (VIDEOCORE_MBOX + 0x0),
|
||||
MBOX_POLL = (VIDEOCORE_MBOX + 0x10),
|
||||
MBOX_SENDER = (VIDEOCORE_MBOX + 0x14),
|
||||
MBOX_STATUS = (VIDEOCORE_MBOX + 0x18),
|
||||
MBOX_CONFIG = (VIDEOCORE_MBOX + 0x1C),
|
||||
MBOX_WRITE = (VIDEOCORE_MBOX + 0x20),
|
||||
MBOX_RESPONSE = 0x80000000,
|
||||
MBOX_FULL = 0x80000000,
|
||||
MBOX_EMPTY = 0x40000000
|
||||
};
|
||||
|
||||
unsigned int mbox_call(unsigned char ch)
|
||||
{
|
||||
// 28-bit address (MSB) and 4-bit value (LSB)
|
||||
unsigned int r = ((unsigned int)((long) &mbox) &~ 0xF) | (ch & 0xF);
|
||||
|
||||
// Wait until we can write
|
||||
while (mmio_read(MBOX_STATUS) & MBOX_FULL);
|
||||
|
||||
// Write the address of our buffer to the mailbox with the channel appended
|
||||
mmio_write(MBOX_WRITE, r);
|
||||
|
||||
while (1) {
|
||||
// Is there a reply?
|
||||
while (mmio_read(MBOX_STATUS) & MBOX_EMPTY);
|
||||
|
||||
// Is it a reply to our message?
|
||||
if (r == mmio_read(MBOX_READ)) return mbox[1]==MBOX_RESPONSE; // Is it successful?
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
44
part15-tcpip/lib/multicore.c
Normal file
44
part15-tcpip/lib/multicore.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "../include/multicore.h"
|
||||
|
||||
void store32(unsigned long address, unsigned long value)
|
||||
{
|
||||
*(unsigned long *) address = value;
|
||||
}
|
||||
|
||||
unsigned long load32(unsigned long address)
|
||||
{
|
||||
return *(unsigned long *) address;
|
||||
}
|
||||
|
||||
void start_core1(void (*func)(void))
|
||||
{
|
||||
store32((unsigned long)&spin_cpu1, (unsigned long)func);
|
||||
asm volatile ("sev");
|
||||
}
|
||||
|
||||
void start_core2(void (*func)(void))
|
||||
{
|
||||
store32((unsigned long)&spin_cpu2, (unsigned long)func);
|
||||
asm volatile ("sev");
|
||||
}
|
||||
|
||||
void start_core3(void (*func)(void))
|
||||
{
|
||||
store32((unsigned long)&spin_cpu3, (unsigned long)func);
|
||||
asm volatile ("sev");
|
||||
}
|
||||
|
||||
void clear_core1(void)
|
||||
{
|
||||
store32((unsigned long)&spin_cpu1, 0);
|
||||
}
|
||||
|
||||
void clear_core2(void)
|
||||
{
|
||||
store32((unsigned long)&spin_cpu2, 0);
|
||||
}
|
||||
|
||||
void clear_core3(void)
|
||||
{
|
||||
store32((unsigned long)&spin_cpu3, 0);
|
||||
}
|
100
part15-tcpip/lib/spi.c
Normal file
100
part15-tcpip/lib/spi.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
#include "../include/io.h"
|
||||
#include "../include/fb.h"
|
||||
|
||||
// SPI
|
||||
|
||||
struct Spi0Regs {
|
||||
volatile unsigned int cs;
|
||||
volatile unsigned int fifo;
|
||||
volatile unsigned int clock;
|
||||
volatile unsigned int data_length;
|
||||
volatile unsigned int ltoh;
|
||||
volatile unsigned int dc;
|
||||
};
|
||||
|
||||
#define REGS_SPI0 ((struct Spi0Regs *)(PERIPHERAL_BASE + 0x00204000))
|
||||
|
||||
// CS Register
|
||||
#define CS_LEN_LONG (1 << 25)
|
||||
#define CS_DMA_LEN (1 << 24)
|
||||
#define CS_CSPOL2 (1 << 23)
|
||||
#define CS_CSPOL1 (1 << 22)
|
||||
#define CS_CSPOL0 (1 << 21)
|
||||
#define CS_RXF (1 << 20)
|
||||
#define CS_RXR (1 << 19)
|
||||
#define CS_TXD (1 << 18)
|
||||
#define CS_RXD (1 << 17)
|
||||
#define CS_DONE (1 << 16)
|
||||
#define CS_LEN (1 << 13)
|
||||
#define CS_REN (1 << 12)
|
||||
#define CS_ADCS (1 << 11)
|
||||
#define CS_INTR (1 << 10)
|
||||
#define CS_INTD (1 << 9)
|
||||
#define CS_DMAEN (1 << 8)
|
||||
#define CS_TA (1 << 7)
|
||||
#define CS_CSPOL (1 << 6)
|
||||
#define CS_CLEAR_RX (1 << 5)
|
||||
#define CS_CLEAR_TX (1 << 4)
|
||||
#define CS_CPOL__SHIFT 3
|
||||
#define CS_CPHA__SHIFT 2
|
||||
#define CS_CS (1 << 0)
|
||||
#define CS_CS__SHIFT 0
|
||||
|
||||
void spi_init() {
|
||||
gpio_useAsAlt0(7); //CS1
|
||||
gpio_initOutputPinWithPullNone(8); //CS0
|
||||
gpio_useAsAlt0(9); //MISO
|
||||
gpio_useAsAlt0(10); //MOSI
|
||||
gpio_useAsAlt0(11); //SCLK
|
||||
}
|
||||
|
||||
void spi_chip_select(unsigned char chip_select) {
|
||||
gpio_setPinOutputBool(8, chip_select);
|
||||
}
|
||||
|
||||
void spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int size) {
|
||||
REGS_SPI0->data_length = size;
|
||||
REGS_SPI0->cs = REGS_SPI0->cs | CS_CLEAR_RX | CS_CLEAR_TX | CS_TA;
|
||||
|
||||
unsigned int read_count = 0;
|
||||
unsigned int write_count = 0;
|
||||
|
||||
while(read_count < size || write_count < size) {
|
||||
while(write_count < size && REGS_SPI0->cs & CS_TXD) {
|
||||
if (sbuffer) {
|
||||
REGS_SPI0->fifo = *sbuffer++;
|
||||
} else {
|
||||
REGS_SPI0->fifo = 0;
|
||||
}
|
||||
|
||||
write_count++;
|
||||
}
|
||||
|
||||
while(read_count < size && REGS_SPI0->cs & CS_RXD) {
|
||||
unsigned int data = REGS_SPI0->fifo;
|
||||
|
||||
if (rbuffer) {
|
||||
*rbuffer++ = data;
|
||||
}
|
||||
|
||||
read_count++;
|
||||
}
|
||||
}
|
||||
|
||||
while(!(REGS_SPI0->cs & CS_DONE)) {
|
||||
while(REGS_SPI0->cs & CS_RXD) {
|
||||
unsigned int r = REGS_SPI0->fifo;
|
||||
debughex(r);
|
||||
}
|
||||
}
|
||||
|
||||
REGS_SPI0->cs = (REGS_SPI0->cs & ~CS_TA);
|
||||
}
|
||||
|
||||
void spi_send(unsigned char *data, unsigned int size) {
|
||||
spi_send_recv(data, 0, size);
|
||||
}
|
||||
|
||||
void spi_recv(unsigned char *data, unsigned int size) {
|
||||
spi_send_recv(0, data, size);
|
||||
}
|
1450
part15-tcpip/net/enc28j60.c
Normal file
1450
part15-tcpip/net/enc28j60.c
Normal file
File diff suppressed because it is too large
Load diff
816
part15-tcpip/net/enc28j60.h
Normal file
816
part15-tcpip/net/enc28j60.h
Normal file
|
@ -0,0 +1,816 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file enc28j60.h
|
||||
* @author Christian Schoffit, portions from Gregory Nutt:
|
||||
* Copyright (C) 2010-2012, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* @version V1.0.0
|
||||
* @date 02-June-2015
|
||||
* @brief This file provides a set of functions needed to manage the ENC28J60
|
||||
* Stand-Alone Ethernet Controller with SPI Interface.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2015 Christian Schoffit</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Christian Schoffit nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ENC28J60_H_INCLUDED
|
||||
#define ENC28J60_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef USE_PROTOTHREADS
|
||||
#include "pt.h"
|
||||
#else
|
||||
#define PT_BEGIN(x)
|
||||
#define PT_END(x)
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
/* Ethernet frames are between 64 and 1518 bytes long */
|
||||
|
||||
#define MIN_FRAMELEN 64
|
||||
#define MAX_FRAMELEN 1518
|
||||
|
||||
|
||||
/* External functions --------------------------------------------------------*/
|
||||
void HAL_Delay(volatile uint32_t Delay);
|
||||
uint32_t HAL_GetTick(void);
|
||||
|
||||
/* Callback functions *********************************************************/
|
||||
|
||||
/**
|
||||
* Implement SPI Slave selection and deselection. Must be provided by user code
|
||||
* param select: true if the ENC28J60 slave SPI if selected, false otherwise
|
||||
* retval none
|
||||
*/
|
||||
|
||||
void ENC_SPI_Select(bool select);
|
||||
|
||||
/**
|
||||
* Implement SPI single byte send and receive.
|
||||
* The ENC28J60 slave SPI must already be selected and wont be deselected after transmission
|
||||
* Must be provided by user code
|
||||
* param command: command or data to be sent to ENC28J60
|
||||
* retval answer from ENC28J60
|
||||
*/
|
||||
|
||||
void ENC_SPI_SendWithoutSelection(uint8_t command);
|
||||
|
||||
/**
|
||||
* Implement SPI single byte send and receive. Must be provided by user code
|
||||
* param command: command or data to be sent to ENC28J60
|
||||
* retval answer from ENC28J60
|
||||
*/
|
||||
|
||||
void ENC_SPI_Send(uint8_t command);
|
||||
|
||||
/**
|
||||
* 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 slave2master: answer from ENC28J60 to host, can be NULL if we only want to send data to slave
|
||||
* retval none
|
||||
*/
|
||||
|
||||
void ENC_SPI_SendBuf(uint8_t *master2slave, uint8_t *slave2master, uint16_t bufferSize);
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** @defgroup ETH_Exported_Types ETH Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief ETH Init Structure definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t DuplexMode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode
|
||||
This parameter can be a value of @ref ETH_Duplex_Mode */
|
||||
|
||||
uint8_t *MACAddr; /*!< MAC Address of used Hardware: must be pointer on an array of 6 bytes */
|
||||
|
||||
uint32_t ChecksumMode; /*!< Selects if the checksum is check by hardware or by software.
|
||||
This parameter can be a value of @ref ETH_Checksum_Mode */
|
||||
|
||||
uint8_t InterruptEnableBits; /*!< Selects the enabled interrupts */
|
||||
} ENC_InitTypeDef;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Received Frame Informations structure definition
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t length; /*!< Frame length */
|
||||
|
||||
uint8_t buffer[MAX_FRAMELEN+20]; /*!< Frame buffer */
|
||||
|
||||
} ENC_RxFrameInfos;
|
||||
|
||||
|
||||
/**
|
||||
* @brief ENC28J60 Handle Structure definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ENC_InitTypeDef Init; /*!< Ethernet Init Configuration */
|
||||
|
||||
uint8_t bank; /*!< Currently selected bank */
|
||||
uint8_t interruptFlags;/*!< The last value of interrupts flags */
|
||||
uint8_t pktCnt; /*!< The number of pending receive packets */
|
||||
uint16_t nextpkt; /*!< Next packet address */
|
||||
uint16_t LinkStatus; /*!< Ethernet link status */
|
||||
uint16_t transmitLength;/*!< The length of ip frame to transmit */
|
||||
uint32_t startTime; /*!< The start time of the current timer */
|
||||
uint32_t duration; /*!< The duration of the current timer in ms */
|
||||
uint16_t retries; /*!< The number of transmission retries left to do */
|
||||
|
||||
ENC_RxFrameInfos RxFrameInfos; /*!< last Rx frame infos */
|
||||
} ENC_HandleTypeDef;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup ETH_Exported_Constants ETH Exported Constants
|
||||
* @{
|
||||
*/
|
||||
/* Size of the Ethernet header */
|
||||
#define ETH_HDRLEN 14 /* Minimum size: 2*6 + 2 */
|
||||
|
||||
|
||||
#define ERR_OK 0 /* No error, everything OK. */
|
||||
#define ERR_MEM -1 /* Out of memory error. */
|
||||
#define ERR_BUF -2 /* Buffer error. */
|
||||
#define ERR_TIMEOUT -3 /* Timeout. */
|
||||
|
||||
/* ENC28J60 Commands ********************************************************/
|
||||
/* A total of seven instructions are implemented on the ENC28J60. Where:
|
||||
*
|
||||
* aaaaaa is the 5-bit address of a control register, and
|
||||
* dddddddd is one or more bytes of data that may accompany the command.
|
||||
*/
|
||||
|
||||
#define ENC_RCR (0x00) /* Read Control Register
|
||||
* 000 | aaaaa | (Register value returned)) */
|
||||
#define ENC_RBM (0x3a) /* Read Buffer Memory
|
||||
* 001 | 11010 | (Read buffer data follows) */
|
||||
#define ENC_WCR (0x40) /* Write Control Register
|
||||
* 010 | aaaaa | dddddddd */
|
||||
#define ENC_WBM (0x7a) /* Write Buffer Memory
|
||||
* 011 | 11010 | (Write buffer data follows) */
|
||||
#define ENC_BFS (0x80) /* Bit Field Set
|
||||
* 100 | aaaaa | dddddddd */
|
||||
#define ENC_BFC (0xa0) /* Bit Field Clear
|
||||
* 101 | aaaaa | dddddddd */
|
||||
#define ENC_SRC (0xff) /* System Reset
|
||||
* 111 | 11111 | (No data) */
|
||||
|
||||
/* Global Control Registers *************************************************/
|
||||
/* Control registers are accessed with the RCR, RBM, WCR, BFS, and BFC
|
||||
* commands. The following identifies all ENC28J60 control registers. The
|
||||
* control register memory is partitioned into four banks, selectable by the
|
||||
* bank select bits, BSEL1:BSEL0, in the ECON1 register.
|
||||
*
|
||||
* The last five locations (0x1b to 0x1f) of all banks point to a common set
|
||||
* of registers: EIE, EIR, ESTAT, ECON2 and ECON1. These are key registers
|
||||
* used in controlling and monitoring the operation of the device. Their
|
||||
* common mapping allows easy access without switching the bank.
|
||||
*
|
||||
* Control registers for the ENC28J60 are generically grouped as ETH, MAC and
|
||||
* MII registers. Register names starting with E belong to the ETH group.
|
||||
* Similarly, registers names starting with MA belong to the MAC group and
|
||||
* registers prefixed with MI belong to the MII group.
|
||||
*/
|
||||
|
||||
#define ENC_EIE (0x1b) /* Ethernet Interrupt Enable Register */
|
||||
#define ENC_EIR (0x1c) /* Ethernet Interupt Request Register */
|
||||
#define ENC_ESTAT (0x1d) /* Ethernet Status Register */
|
||||
#define ENC_ECON2 (0x1e) /* Ethernet Control 2 Register */
|
||||
#define ENC_ECON1 (0x1f) /* Ethernet Control 1 Register */
|
||||
|
||||
/* Ethernet Interrupt Enable Register Bit Definitions */
|
||||
|
||||
#define EIE_RXERIE (1 << 0) /* Bit 0: Receive Error Interrupt Enable */
|
||||
#define EIE_TXERIE (1 << 1) /* Bit 1: Transmit Error Interrupt Enable */
|
||||
/* Bit 2: Reserved */
|
||||
#define EIE_TXIE (1 << 3) /* Bit 3: Transmit Enable */
|
||||
#define EIE_LINKIE (1 << 4) /* Bit 4: Link Status Change Interrupt Enable */
|
||||
#define EIE_DMAIE (1 << 5) /* Bit 5: DMA Interrupt Enable */
|
||||
#define EIE_PKTIE (1 << 6) /* Bit 6: Receive Packet Pending Interrupt Enable */
|
||||
#define EIE_INTIE (1 << 7) /* Bit 7: Global INT Interrupt Enable */
|
||||
|
||||
/* Ethernet Interrupt Request Register Bit Definitions */
|
||||
|
||||
#define EIR_RXERIF (1 << 0) /* Bit 0: Receive Error Interrupt */
|
||||
#define EIR_TXERIF (1 << 1) /* Bit 1: Transmit Error Interrupt */
|
||||
/* Bit 2: Reserved */
|
||||
#define EIR_TXIF (1 << 3) /* Bit 3: Transmit Interrupt */
|
||||
#define EIR_LINKIF (1 << 4) /* Bit 4: Link Change Interrupt */
|
||||
#define EIR_DMAIF (1 << 5) /* Bit 5: DMA Interrupt */
|
||||
#define EIR_PKTIF (1 << 6) /* Bit 6: Receive Packet Pending Interrupt */
|
||||
/* Bit 7: Reserved */
|
||||
#define EIR_ALLINTS (EIR_RXERIF | EIR_TXERIF | EIR_TXIF | EIR_LINKIF | EIR_DMAIF) /* All interrupts bar EIR_PKTIF*/
|
||||
|
||||
/* Ethernet Status Register Bit Definitions */
|
||||
|
||||
#define ESTAT_CLKRDY (1 << 0) /* Bit 0: Clock Ready */
|
||||
#define ESTAT_TXABRT (1 << 1) /* Bit 1: Transmit Abort Error */
|
||||
#define ESTAT_RXBUSY (1 << 2) /* Bit 2: Receive Busy */
|
||||
/* Bit 3: Reserved */
|
||||
#define ESTAT_LATECOL (1 << 4) /* Bit 4: Late Collision Error */
|
||||
/* Bit 5: Reserved */
|
||||
#define ESTAT_BUFER (1 << 6) /* Bit 6: Ethernet Buffer Error Status */
|
||||
#define ESTAT_INT (1 << 7) /* Bit 7: INT Interrupt */
|
||||
|
||||
/* Ethernet Control 1 Register Bit Definitions */
|
||||
|
||||
#define ECON1_BSEL_SHIFT (0) /* Bits 0-1: Bank select */
|
||||
#define ECON1_BSEL_MASK (3 << ECON1_BSEL_SHIFT)
|
||||
# define ECON1_BSEL_BANK0 (0 << ECON1_BSEL_SHIFT) /* Bank 0 */
|
||||
# define ECON1_BSEL_BANK1 (1 << ECON1_BSEL_SHIFT) /* Bank 1 */
|
||||
# define ECON1_BSEL_BANK2 (2 << ECON1_BSEL_SHIFT) /* Bank 2 */
|
||||
# define ECON1_BSEL_BANK3 (3 << ECON1_BSEL_SHIFT) /* Bank 3 */
|
||||
#define ECON1_RXEN (1 << 2) /* Bit 2: Receive Enable */
|
||||
#define ECON1_TXRTS (1 << 3) /* Bit 3: Transmit Request to Send */
|
||||
#define ECON1_CSUMEN (1 << 4) /* Bit 4: DMA Checksum Enable */
|
||||
#define ECON1_DMAST (1 << 5) /* Bit 5: DMA Start and Busy Status */
|
||||
#define ECON1_RXRST (1 << 6) /* Bit 6: Receive Logic Reset */
|
||||
#define ECON1_TXRST (1 << 7) /* Bit 7: Transmit Logic Reset */
|
||||
|
||||
/* Ethernet Control 2 Register */
|
||||
/* Bits 0-2: Reserved */
|
||||
#define ECON2_VRPS (1 << 3) /* Bit 3: Voltage Regulator Power Save Enable */
|
||||
/* Bit 4: Reserved */
|
||||
#define ECON2_PWRSV (1 << 5) /* Bit 5: Power Save Enable */
|
||||
#define ECON2_PKTDEC (1 << 6) /* Bit 6: Packet Decrement */
|
||||
#define ECON2_AUTOINC (1 << 7) /* Bit 7: Automatic Buffer Pointer Increment Enable */
|
||||
|
||||
/* Banked Control Registers *************************************************/
|
||||
/* The remaining control registers are identified with a a 5 bit address and
|
||||
* a bank selection. We pack the bank number and an indication if this is
|
||||
* a MAC/PHY register access together with the control register address
|
||||
* together to keep the design simpler.
|
||||
*/
|
||||
|
||||
#define ENC_ADDR_SHIFT (0) /* Bits 0-4: Register address */
|
||||
#define ENC_ADDR_MASK (0x1f << ENC_ADDR_SHIFT)
|
||||
#define ENC_BANK_SHIFT (5) /* Bits 5-6: Bank number */
|
||||
#define ENC_BANK_MASK (3 << ENC_BSEL_SHIFT)
|
||||
# define ENC_BANK0 (0 << ENC_BSEL_SHIFT)
|
||||
# define ENC_BANK1 (1 << ENC_BSEL_SHIFT)
|
||||
# define ENC_BANK2 (2 << ENC_BSEL_SHIFT)
|
||||
# define ENC_BANK3 (3 << ENC_BSEL_SHIFT)
|
||||
#define ENC_PHYMAC_SHIFT (7) /* Bit 7: This is a PHY/MAC command */
|
||||
#define ENC_PHYMAC (1 << ENC_PHYMAC_SHIFT)
|
||||
|
||||
#define REGADDR(a,b,m) ((m) << ENC_PHYMAC_SHIFT | (b) << ENC_BANK_SHIFT | (a))
|
||||
#define GETADDR(a) ((a) & ENC_ADDR_MASK)
|
||||
#define GETBANK(a) (((a) >> ENC_BANK_SHIFT) & 3)
|
||||
#define ISPHYMAC(a) (((a) & ENC_PHYMAC) != 0)
|
||||
|
||||
/* Bank 0 Control Register Addresses */
|
||||
|
||||
#define ENC_ERDPTL REGADDR(0x00, 0, 0) /* Read Pointer Low Byte (ERDPT<7:0> */
|
||||
#define ENC_ERDPTH REGADDR(0x01, 0, 0) /* Read Pointer High Byte (ERDPT<12:8>) */
|
||||
#define ENC_EWRPTL REGADDR(0x02, 0, 0) /* Write Pointer Low Byte (EWRPT<7:0>) */
|
||||
#define ENC_EWRPTH REGADDR(0x03, 0, 0) /* Write Pointer High Byte (EWRPT<12:8>) */
|
||||
#define ENC_ETXSTL REGADDR(0x04, 0, 0) /* TX Start Low Byte (ETXST<7:0>) */
|
||||
#define ENC_ETXSTH REGADDR(0x05, 0, 0) /* TX Start High Byte (ETXST<12:8>) */
|
||||
#define ENC_ETXNDL REGADDR(0x06, 0, 0) /* TX End Low Byte (ETXND<7:0>) */
|
||||
#define ENC_ETXNDH REGADDR(0x07, 0, 0) /* TX End High Byte (ETXND<12:8>) */
|
||||
#define ENC_ERXSTL REGADDR(0x08, 0, 0) /* RX Start Low Byte (ERXST<7:0>) */
|
||||
#define ENC_ERXSTH REGADDR(0x09, 0, 0) /* RX Start High Byte (ERXST<12:8>) */
|
||||
#define ENC_ERXNDL REGADDR(0x0a, 0, 0) /* RX End Low Byte (ERXND<7:0>) */
|
||||
#define ENC_ERXNDH REGADDR(0x0b, 0, 0) /* RX End High Byte (ERXND<12:8>) */
|
||||
#define ENC_ERXRDPTL REGADDR(0x0c, 0, 0) /* RX RD Pointer Low Byte (ERXRDPT<7:0>) */
|
||||
#define ENC_ERXRDPTH REGADDR(0x0d, 0, 0) /* RX RD Pointer High Byte (ERXRDPT<12:8>) */
|
||||
#define ENC_ERXWRPTL REGADDR(0x0e, 0, 0) /* RX WR Pointer Low Byte (ERXWRPT<7:0>) */
|
||||
#define ENC_ERXWRPTH REGADDR(0x0f, 0, 0) /* RX WR Pointer High Byte (ERXWRPT<12:8>) */
|
||||
#define ENC_EDMASTL REGADDR(0x10, 0, 0) /* DMA Start Low Byte (EDMAST<7:0>) */
|
||||
#define ENC_EDMASTH REGADDR(0x11, 0, 0) /* DMA Start High Byte (EDMAST<12:8>) */
|
||||
#define ENC_EDMANDL REGADDR(0x12, 0, 0) /* DMA End Low Byte (EDMAND<7:0>) */
|
||||
#define ENC_EDMANDH REGADDR(0x13, 0, 0) /* DMA End High Byte (EDMAND<12:8>) */
|
||||
#define ENC_EDMADSTL REGADDR(0x14, 0, 0) /* DMA Destination Low Byte (EDMADST<7:0>) */
|
||||
#define ENC_EDMADSTH REGADDR(0x15, 0, 0) /* DMA Destination High Byte (EDMADST<12:8>) */
|
||||
#define ENC_EDMACSL REGADDR(0x16, 0, 0) /* DMA Checksum Low Byte (EDMACS<7:0>) */
|
||||
#define ENC_EDMACSH REGADDR(0x17, 0, 0) /* DMA Checksum High Byte (EDMACS<15:8>) */
|
||||
/* 0x18-0x1a: Reserved */
|
||||
/* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */
|
||||
/* Bank 1 Control Register Addresses */
|
||||
|
||||
#define ENC_EHT0 REGADDR(0x00, 1, 0) /* Hash Table Byte 0 (EHT<7:0>) */
|
||||
#define ENC_EHT1 REGADDR(0x01, 1, 0) /* Hash Table Byte 1 (EHT<15:8>) */
|
||||
#define ENC_EHT2 REGADDR(0x02, 1, 0) /* Hash Table Byte 2 (EHT<23:16>) */
|
||||
#define ENC_EHT3 REGADDR(0x03, 1, 0) /* Hash Table Byte 3 (EHT<31:24>) */
|
||||
#define ENC_EHT4 REGADDR(0x04, 1, 0) /* Hash Table Byte 4 (EHT<39:32>) */
|
||||
#define ENC_EHT5 REGADDR(0x05, 1, 0) /* Hash Table Byte 5 (EHT<47:40>) */
|
||||
#define ENC_EHT6 REGADDR(0x06, 1, 0) /* Hash Table Byte 6 (EHT<55:48>) */
|
||||
#define ENC_EHT7 REGADDR(0x07, 1, 0) /* Hash Table Byte 7 (EHT<63:56>) */
|
||||
#define ENC_EPMM0 REGADDR(0x08, 1, 0) /* Pattern Match Mask Byte 0 (EPMM<7:0>) */
|
||||
#define ENC_EPMM1 REGADDR(0x09, 1, 0) /* Pattern Match Mask Byte 1 (EPMM<15:8>) */
|
||||
#define ENC_EPMM2 REGADDR(0x0a, 1, 0) /* Pattern Match Mask Byte 2 (EPMM<23:16>) */
|
||||
#define ENC_EPMM3 REGADDR(0x0b, 1, 0) /* Pattern Match Mask Byte 3 (EPMM<31:24>) */
|
||||
#define ENC_EPMM4 REGADDR(0x0c, 1, 0) /* Pattern Match Mask Byte 4 (EPMM<39:32>) */
|
||||
#define ENC_EPMM5 REGADDR(0x0d, 1, 0) /* Pattern Match Mask Byte 5 (EPMM<47:40>) */
|
||||
#define ENC_EPMM6 REGADDR(0x0e, 1, 0) /* Pattern Match Mask Byte 6 (EPMM<55:48>) */
|
||||
#define ENC_EPMM7 REGADDR(0x0f, 1, 0) /* Pattern Match Mask Byte 7 (EPMM<63:56>) */
|
||||
#define ENC_EPMCSL REGADDR(0x10, 1, 0) /* Pattern Match Checksum Low Byte (EPMCS<7:0>) */
|
||||
#define ENC_EPMCSH REGADDR(0x11, 1, 0) /* Pattern Match Checksum High Byte (EPMCS<15:0>) */
|
||||
/* 0x12-0x13: Reserved */
|
||||
#define ENC_EPMOL REGADDR(0x14, 1, 0) /* Pattern Match Offset Low Byte (EPMO<7:0>) */
|
||||
#define ENC_EPMOH REGADDR(0x15, 1, 0) /* Pattern Match Offset High Byte (EPMO<12:8>) */
|
||||
/* 0x16-0x17: Reserved */
|
||||
#define ENC_ERXFCON REGADDR(0x18, 1, 0) /* Receive Filter Configuration */
|
||||
#define ENC_EPKTCNT REGADDR(0x19, 1, 0) /* Ethernet Packet Count */
|
||||
/* 0x1a: Reserved */
|
||||
/* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */
|
||||
|
||||
/* Receive Filter Configuration Bit Definitions */
|
||||
|
||||
#define ERXFCON_BCEN (1 << 0) /* Bit 0: Broadcast Filter Enable */
|
||||
#define ERXFCON_MCEN (1 << 1) /* Bit 1: Multicast Filter Enable */
|
||||
#define ERXFCON_HTEN (1 << 2) /* Bit 2: Hash Table Filter Enable */
|
||||
#define ERXFCON_MPEN (1 << 3) /* Bit 3: Magic Packet Filter Enable */
|
||||
#define ERXFCON_PMEN (1 << 4) /* Bit 4: Pattern Match Filter Enable */
|
||||
#define ERXFCON_CRCEN (1 << 5) /* Bit 5: Post-Filter CRC Check Enable */
|
||||
#define ERXFCON_ANDOR (1 << 6) /* Bit 6: AND/OR Filter Select */
|
||||
#define ERXFCON_UCEN (1 << 7) /* Bit 7: Unicast Filter Enable */
|
||||
|
||||
/* Bank 2 Control Register Addresses */
|
||||
|
||||
#define ENC_MACON1 REGADDR(0x00, 2, 1) /* MAC Control 1 */
|
||||
/* 0x01: Reserved */
|
||||
#define ENC_MACON3 REGADDR(0x02, 2, 1) /* MAC Control 3 */
|
||||
#define ENC_MACON4 REGADDR(0x03, 2, 1) /* MAC Control 4 */
|
||||
#define ENC_MABBIPG REGADDR(0x04, 2, 1) /* Back-to-Back Inter-Packet Gap (BBIPG<6:0>) */
|
||||
/* 0x05: Reserved */
|
||||
#define ENC_MAIPGL REGADDR(0x06, 2, 1) /* Non-Back-to-Back Inter-Packet Gap Low Byte (MAIPGL<6:0>) */
|
||||
#define ENC_MAIPGH REGADDR(0x07, 2, 1) /* Non-Back-to-Back Inter-Packet Gap High Byte (MAIPGH<6:0>) */
|
||||
#define ENC_MACLCON1 REGADDR(0x08, 2, 1) /* MAC Collision Control 1 */
|
||||
#define ENC_MACLCON2 REGADDR(0x09, 2, 1) /* MAC Collision Control 2 */
|
||||
#define ENC_MAMXFLL REGADDR(0x0a, 2, 1) /* Maximum Frame Length Low Byte (MAMXFL<7:0>) */
|
||||
#define ENC_MAMXFLH REGADDR(0x0b, 2, 1) /* Maximum Frame Length High Byte (MAMXFL<15:8>) */
|
||||
/* 0x0c-0x11: Reserved */
|
||||
#define ENC_MICMD REGADDR(0x12, 2, 1) /* MII Command Register */
|
||||
/* 0x13: Reserved */
|
||||
#define ENC_MIREGADR REGADDR(0x14, 2, 1) /* MII Register Address */
|
||||
/* 0x15: Reserved */
|
||||
#define ENC_MIWRL REGADDR(0x16, 2, 1) /* MII Write Data Low Byte (MIWR<7:0>) */
|
||||
#define ENC_MIWRH REGADDR(0x17, 2, 1) /* MII Write Data High Byte (MIWR<15:8>) */
|
||||
#define ENC_MIRDL REGADDR(0x18, 2, 1) /* MII Read Data Low Byte (MIRD<7:0>) */
|
||||
#define ENC_MIRDH REGADDR(0x19, 2, 1) /* MII Read Data High Byte(MIRD<15:8>) */
|
||||
/* 0x1a: Reserved */
|
||||
/* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */
|
||||
|
||||
/* MAC Control 1 Register Bit Definitions */
|
||||
|
||||
#define MACON1_MARXEN (1 << 0) /* Bit 0: MAC Receive Enable */
|
||||
#define MACON1_PASSALL (1 << 1) /* Bit 1: Pass All Received Frames Enable */
|
||||
#define MACON1_RXPAUS (1 << 2) /* Bit 2: Pause Control Frame Reception Enable */
|
||||
#define MACON1_TXPAUS (1 << 3) /* Bit 3: Pause Control Frame Transmission Enable */
|
||||
/* Bits 4-7: Unimplemented or reserved */
|
||||
|
||||
/* MAC Control 1 Register Bit Definitions */
|
||||
|
||||
#define MACON3_FULDPX (1 << 0) /* Bit 0: MAC Full-Duplex Enable */
|
||||
#define MACON3_FRMLNEN (1 << 1) /* Bit 1: Frame Length Checking Enable */
|
||||
#define MACON3_HFRMLEN (1 << 2) /* Bit 2: Huge Frame Enable */
|
||||
#define MACON3_PHDRLEN (1 << 3) /* Bit 3: Proprietary Header Enable */
|
||||
#define MACON3_TXCRCEN (1 << 4) /* Bit 4: Transmit CRC Enable */
|
||||
#define MACON3_PADCFG0 (1 << 5) /* Bit 5: Automatic Pad and CRC Configuration */
|
||||
#define MACON3_PADCFG1 (1 << 6) /* Bit 6: " " " " " " " " " " */
|
||||
#define MACON3_PADCFG2 (1 << 7) /* Bit 7: " " " " " " " " " " */
|
||||
|
||||
/* MAC Control 1 Register Bit Definitions */
|
||||
|
||||
#define MACON4_NOBKOFF (1 << 4) /* Bit 4: No Backoff Enable */
|
||||
#define MACON4_BPEN (1 << 5) /* Bit 5: No Backoff During Backpressure Enable */
|
||||
#define MACON4_DEFER (1 << 6) /* Bit 6: Defer Transmission Enable bit */
|
||||
|
||||
/* MII Command Register Bit Definitions */
|
||||
|
||||
#define MICMD_MIIRD (1 << 0) /* Bit 0: MII Read Enable */
|
||||
#define MICMD_MIISCAN (1 << 1) /* Bit 1: MII Scan Enable */
|
||||
|
||||
/* Bank 3 Control Register Addresses */
|
||||
|
||||
#define ENC_MAADR5 REGADDR(0x00, 3, 1) /* MAC Address Byte 5 (MAADR<15:8>) */
|
||||
#define ENC_MAADR6 REGADDR(0x01, 3, 1) /* MAC Address Byte 6 (MAADR<7:0>) */
|
||||
#define ENC_MAADR3 REGADDR(0x02, 3, 1) /* MAC Address Byte 3 (MAADR<31:24>), OUI Byte 3 */
|
||||
#define ENC_MAADR4 REGADDR(0x03, 3, 1) /* MAC Address Byte 4 (MAADR<23:16>) */
|
||||
#define ENC_MAADR1 REGADDR(0x04, 3, 1) /* MAC Address Byte 1 (MAADR<47:40>), OUI Byte 1 */
|
||||
#define ENC_MAADR2 REGADDR(0x05, 3, 1) /* MAC Address Byte 2 (MAADR<39:32>), OUI Byte 2 */
|
||||
#define ENC_EBSTSD REGADDR(0x06, 3, 0) /* Built-in Self-Test Fill Seed (EBSTSD<7:0>) */
|
||||
#define ENC_EBSTCON REGADDR(0x07, 3, 0) /* Built-in Self-Test Control */
|
||||
#define ENC_EBSTCSL REGADDR(0x08, 3, 0) /* Built-in Self-Test Checksum Low Byte (EBSTCS<7:0>) */
|
||||
#define ENC_EBSTCSH REGADDR(0x09, 3, 0) /* Built-in Self-Test Checksum High Byte (EBSTCS<15:8>) */
|
||||
#define ENC_MISTAT REGADDR(0x0a, 3, 1) /* MII Status Register */
|
||||
/* 0x0b-0x11: Reserved */
|
||||
#define ENC_EREVID REGADDR(0x12, 3, 0) /* Ethernet Revision ID */
|
||||
/* 0x13-0x14: Reserved */
|
||||
#define ENC_ECOCON REGADDR(0x15, 3, 0) /* Clock Output Control */
|
||||
/* 0x16: Reserved */
|
||||
#define ENC_EFLOCON REGADDR(0x17, 3, 0) /* Ethernet Flow Control */
|
||||
#define ENC_EPAUSL REGADDR(0x18, 3, 0) /* Pause Timer Value Low Byte (EPAUS<7:0>) */
|
||||
#define ENC_EPAUSH REGADDR(0x19, 3, 0) /* Pause Timer Value High Byte (EPAUS<15:8>) */
|
||||
/* 0x1a: Reserved */
|
||||
/* 0x1b-0x1f: EIE, EIR, ESTAT, ECON2, ECON1 */
|
||||
|
||||
/* Built-in Self-Test Control Register Bit Definitions */
|
||||
|
||||
#define EBSTCON_BISTST (1 << 0) /* Bit 0: Built-in Self-Test Start/Busy */
|
||||
#define EBSTCON_TME (1 << 1) /* Bit 1: Test Mode Enable */
|
||||
#define EBSTCON_TMSEL0 (1 << 2) /* Bit 2: Test Mode Select */
|
||||
#define EBSTCON_TMSEL1 (1 << 3) /* Bit 3: " " " " " " */
|
||||
#define EBSTCON_PSEL (1 << 4) /* Bit 4: Port Select */
|
||||
#define EBSTCON_PSV0 (1 << 5) /* Bit 5: Pattern Shift Value */
|
||||
#define EBSTCON_PSV1 (1 << 6) /* Bit 6: " " " " " */
|
||||
#define EBSTCON_PSV2 (1 << 7) /* Bit 7: " " " " " */
|
||||
|
||||
/* MII Status Register Register Bit Definitions */
|
||||
|
||||
#define MISTAT_BUSY (1 << 0) /* Bit 0: MII Management Busy */
|
||||
#define MISTAT_SCAN (1 << 1) /* Bit 1: MII Management Scan Operation */
|
||||
#define MISTAT_NVALID (1 << 2) /* Bit 2: MII Management Read Data Not Valid */
|
||||
/* Bits 3-7: Reserved or unimplemented */
|
||||
|
||||
/* Ethernet Flow Control Register Bit Definitions */
|
||||
|
||||
#define EFLOCON_FCEN0 (1 << 0) /* Bit 0: Flow Control Enable */
|
||||
#define EFLOCON_FCEN1 (1 << 1) /* Bit 1: " " " " " " */
|
||||
#define EFLOCON_FULDPXS (1 << 2) /* Bit 2: Read-Only MAC Full-Duplex Shadow */
|
||||
/* Bits 3-7: Reserved or unimplemented */
|
||||
|
||||
/* PHY Registers ************************************************************/
|
||||
|
||||
#define ENC_PHCON1 (0x00) /* PHY Control Register 1 */
|
||||
#define ENC_PHSTAT1 (0x01) /* PHY Status 1 */
|
||||
#define ENC_PHID1 (0x02) /* PHY ID Register 1 */
|
||||
#define ENC_PHID2 (0x03) /* PHY ID Register 2 */
|
||||
#define ENC_PHCON2 (0x10) /* PHY Control Register 2 */
|
||||
#define ENC_PHSTAT2 (0x11) /* PHY Status 2 */
|
||||
#define ENC_PHIE (0x12) /* PHY Interrupt Enable Register */
|
||||
#define ENC_PHIR (0x13) /* PHY Interrupt Request Register */
|
||||
#define ENC_PHLCON (0x14)
|
||||
|
||||
/* PHY Control Register 1 Register Bit Definitions */
|
||||
|
||||
#define PHCON1_PDPXMD (1 << 8) /* Bit 8: PHY Duplex Mode */
|
||||
#define PHCON1_PPWRSV (1 << 11) /* Bit 11: PHY Power-Down */
|
||||
#define PHCON1_PLOOPBK (1 << 14) /* Bit 14: PHY Loopback */
|
||||
#define PHCON1_PRST (1 << 15) /* Bit 15: PHY Software Reset */
|
||||
|
||||
/* PHY Status 1 Register Bit Definitions */
|
||||
|
||||
#define PHSTAT1_JBSTAT (1 << 1) /* Bit 1: PHY Latching Jabber Status */
|
||||
#define PHSTAT1_LLSTAT (1 << 2) /* Bit 2: PHY Latching Link Status */
|
||||
#define PHSTAT1_PHDPX (1 << 11) /* Bit 11: PHY Half-Duplex Capable */
|
||||
#define PHSTAT1_PFDPX (1 << 12) /* Bit 12: PHY Full-Duplex Capable */
|
||||
|
||||
/* PHY Control Register 2 Register Bit Definitions */
|
||||
|
||||
#define PHCON2_HDLDIS (1 << 8) /* Bit 8: PHY Half-Duplex Loopback Disable */
|
||||
#define PHCON2_JABBER (1 << 10) /* Bit 10: Jabber Correction Disable */
|
||||
#define PHCON2_TXDIS (1 << 13) /* Bit 13: Twisted-Pair Transmitter Disable */
|
||||
#define PHCON2_FRCLINK (1 << 14) /* Bit 14: PHY Force Linkup */
|
||||
|
||||
/* PHY Status 2 Register Bit Definitions */
|
||||
|
||||
#define PHSTAT2_PLRITY (1 << 5) /* Bit 5: Polarity Status */
|
||||
#define PHSTAT2_DPXSTAT (1 << 9) /* Bit 9: PHY Duplex Status */
|
||||
#define PHSTAT2_LSTAT (1 << 10) /* Bit 10: PHY Link Status */
|
||||
#define PHSTAT2_COLSTAT (1 << 11) /* Bit 11: PHY Collision Status */
|
||||
#define PHSTAT2_RXSTAT (1 << 12) /* Bit 12: PHY Receive Status */
|
||||
#define PHSTAT2_TXSTAT (1 << 13) /* Bit 13: PHY Transmit Status */
|
||||
|
||||
/* PHY Interrupt Enable Register Bit Definitions */
|
||||
|
||||
#define PHIE_PGEIE (1 << 1) /* Bit 1: PHY Global Interrupt Enable */
|
||||
#define PHIE_PLNKIE (1 << 4) /* Bit 4: PHY Link Change Interrupt Enable */
|
||||
|
||||
/* PHIR Regiser Bit Definitions */
|
||||
|
||||
#define PHIR_PGIF (1 << 2) /* Bit 2: PHY Global Interrupt */
|
||||
#define PHIR_PLNKIF (1 << 4) /* Bit 4: PHY Link Change Interrupt */
|
||||
|
||||
/* PHLCON Regiser Bit Definitions */
|
||||
/* Bit 0: Reserved */
|
||||
#define PHLCON_STRCH (1 << 1) /* Bit 1: LED Pulse Stretching Enable */
|
||||
#define PHLCON_LFRQ0 (1 << 2) /* Bit 2: LED Pulse Stretch Time Configuration */
|
||||
#define PHLCON_LFRQ1 (1 << 3) /* Bit 3: " " " " " " " " " */
|
||||
#define PHLCON_LBCFG0 (1 << 4) /* Bit 4: LEDB Configuration */
|
||||
#define PHLCON_LBCFG1 (1 << 5) /* Bit 5: " " " " */
|
||||
#define PHLCON_LBCFG2 (1 << 6) /* Bit 6: " " " " */
|
||||
#define PHLCON_LBCFG3 (1 << 7) /* Bit 7: " " " " */
|
||||
#define PHLCON_LACFG0 (1 << 8) /* Bit 8: LEDA Configuration */
|
||||
#define PHLCON_LACFG1 (1 << 9) /* Bit 9: " " " " */
|
||||
#define PHLCON_LACFG2 (1 << 10) /* Bit 10: " " " " */
|
||||
#define PHLCON_LACFG3 (1 << 11) /* Bit 11: " " " " */
|
||||
|
||||
/* Packet Memory ************************************************************/
|
||||
|
||||
/* 8-Kbyte Transmit/Receive Packet Dual Port SRAM */
|
||||
|
||||
#define PKTMEM_START 0x0000
|
||||
#define PKTMEM_END 0x1fff
|
||||
|
||||
/* maximum transfer unit */
|
||||
#define CONFIG_NET_ETH_MTU 1500
|
||||
|
||||
/* Packet Control Bits Definitions ******************************************/
|
||||
|
||||
#define PKTCTRL_POVERRIDE (1 << 0) /* Bit 0: Per Packet Override */
|
||||
#define PKTCTRL_PCRCEN (1 << 1) /* Bit 1: Per Packet CRC Enable */
|
||||
#define PKTCTRL_PPADEN (1 << 2) /* Bit 2: Per Packet Padding Enable */
|
||||
#define PKTCTRL_PHUGEEN (1 << 3) /* Bit 3: Per Packet Huge Frame Enable */
|
||||
|
||||
/* RX Status Bit Definitions ************************************************/
|
||||
|
||||
#define RXSTAT_LDEVENT (1 << 0) /* Bit 0: Long event or pack dropped */
|
||||
/* Bit 1: Reserved */
|
||||
#define RXSTAT_CEPS (1 << 2) /* Bit 2: Carrier event previously seen */
|
||||
/* Bit 3: Reserved */
|
||||
#define RXSTAT_CRCERROR (1 << 4) /* Bit 4: Frame CRC field bad */
|
||||
#define RXSTAT_LENERROR (1 << 5) /* Bit 5: Packet length != data length */
|
||||
#define RXSTAT_LENRANGE (1 << 6) /* Bit 6: Type/length field > 1500 bytes */
|
||||
#define RXSTAT_OK (1 << 7) /* Bit 7: Packet with valid CRC and no symbol errors */
|
||||
#define RXSTAT_MCAST (1 << 8) /* Bit 8: Packet with multicast address */
|
||||
#define RXSTAT_BCAST (1 << 9) /* Bit 9: Packet with broadcast address */
|
||||
#define RXSTAT_DRIBBLE (1 << 10) /* Bit 10: Additional bits received after packet */
|
||||
#define RXSTAT_CTRLFRAME (1 << 11) /* Bit 11: Control frame with valid type/length */
|
||||
#define RXSTAT_PAUSE (1 << 12) /* Bit 12: Control frame with pause frame opcde */
|
||||
#define RXSTAT_UNKOPCODE (1 << 13) /* Bit 13: Control frame with unknown opcode */
|
||||
#define RXSTAT_VLANTYPE (1 << 14) /* Bit 14: Current frame is a VLAN tagged frame */
|
||||
/* Bit 15: Zero */
|
||||
/* TSV bit definitions */
|
||||
#define TSV_LATECOL (1 << 5) /* Bit 5: Late Collision Error, RSV byte 3 */
|
||||
|
||||
|
||||
|
||||
/** @defgroup ETH_Duplex_Mode ETH Duplex Mode
|
||||
* @{
|
||||
*/
|
||||
#define ETH_MODE_FULLDUPLEX ((uint32_t)0x00000800)
|
||||
#define ETH_MODE_HALFDUPLEX ((uint32_t)0x00000000)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Rx_Mode ETH Rx Mode
|
||||
* @{
|
||||
*/
|
||||
#define ETH_RXPOLLING_MODE ((uint32_t)0x00000000)
|
||||
#define ETH_RXINTERRUPT_MODE ((uint32_t)0x00000001)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Checksum_Mode ETH Checksum Mode
|
||||
* @{
|
||||
*/
|
||||
#define ETH_CHECKSUM_BY_HARDWARE ((uint32_t)0x00000000)
|
||||
#define ETH_CHECKSUM_BY_SOFTWARE ((uint32_t)0x00000001)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup SPI_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_Exported_Functions_Group1
|
||||
* @{
|
||||
*/
|
||||
/* Initialization/de-initialization functions **********************************/
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the enc28j60 and configure the needed hardware resources
|
||||
* param handle: Handle on data configuration.
|
||||
* retval None
|
||||
*/
|
||||
|
||||
bool ENC_Start(ENC_HandleTypeDef *handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_SetMacAddr
|
||||
*
|
||||
* Description:
|
||||
* Set the MAC address to the configured value. This is done after ifup
|
||||
* or after a TX timeout. Note that this means that the interface must
|
||||
* be down before configuring the MAC addr.
|
||||
*
|
||||
* Parameters:
|
||||
* handle - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ENC_SetMacAddr(ENC_HandleTypeDef *handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_RestoreTXBuffer
|
||||
*
|
||||
* Description:
|
||||
* Prepare TX buffer
|
||||
*
|
||||
* Parameters:
|
||||
* handle - Reference to the driver state structure
|
||||
* len - length of buffer
|
||||
*
|
||||
* Returned Value:
|
||||
* ERR_OK 0 No error, everything OK.
|
||||
* ERR_MEM -1 Out of memory error.
|
||||
* ERR_TIMEOUT -3 Timeout.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int8_t ENC_RestoreTXBuffer(ENC_HandleTypeDef *handle, uint16_t len);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_WriteBuffer
|
||||
*
|
||||
* Description:
|
||||
* Write a buffer of data.
|
||||
*
|
||||
* Parameters:
|
||||
* buffer - A pointer to the buffer to write from
|
||||
* buflen - The number of bytes to write
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Read pointer is set to the correct address
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ENC_WriteBuffer(void *buffer, uint16_t buflen);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_Transmit
|
||||
*
|
||||
* Description:
|
||||
* Start hardware transmission. Called either from:
|
||||
*
|
||||
* - pkif interrupt when an application responds to the receipt of data
|
||||
* by trying to send something, or
|
||||
* - From watchdog based polling.
|
||||
*
|
||||
* Parameters:
|
||||
* handle - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* none
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef USE_PROTOTHREADS
|
||||
PT_THREAD(ENC_Transmit(struct pt *pt, ENC_HandleTypeDef *handle));
|
||||
#else
|
||||
void ENC_Transmit(ENC_HandleTypeDef *handle);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_GetReceivedFrame
|
||||
*
|
||||
* Description:
|
||||
* Check if we have received packet, and if so, retrive them.
|
||||
*
|
||||
* Parameters:
|
||||
* handle - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* true if new packet is available; false otherwise
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool ENC_GetReceivedFrame(ENC_HandleTypeDef *handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_IRQHandler
|
||||
*
|
||||
* Description:
|
||||
* Perform interrupt handling logic outside of the interrupt handler (on
|
||||
* the work queue thread).
|
||||
*
|
||||
* Parameters:
|
||||
* handle - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ENC_IRQHandler(ENC_HandleTypeDef *handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_EnableInterrupts
|
||||
*
|
||||
* Description:
|
||||
* Enable individual ENC28J60 interrupts
|
||||
*
|
||||
* Parameters:
|
||||
* bits - The individual bits to enable
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ENC_EnableInterrupts(uint8_t bits);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ENC_GetPkcnt
|
||||
*
|
||||
* Description:
|
||||
* Get the number of pending receive packets
|
||||
*
|
||||
* Parameters:
|
||||
* handle - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* the number of receive packet not processed yet
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ENC_GetPkcnt(ENC_HandleTypeDef *handle);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Function: up_udelay
|
||||
*
|
||||
* Description:
|
||||
* wait us µs
|
||||
*
|
||||
* Parameters:
|
||||
* us - The amount of time to wait in µs
|
||||
*
|
||||
* Returned Value:
|
||||
* none
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_udelay(uint32_t us);
|
||||
|
||||
#endif /* ENC28J60_H_INCLUDED */
|
21
part15-tcpip/net/encspi.c
Normal file
21
part15-tcpip/net/encspi.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "../include/spi.h"
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
void ENC_SPI_SendBuf(unsigned char *master2slave, unsigned char *slave2master, unsigned short bufferSize) {
|
||||
spi_chip_select(0);
|
||||
spi_send_recv(master2slave, slave2master, bufferSize);
|
||||
spi_chip_select(1); // De-select the ENC
|
||||
}
|
||||
|
||||
void ENC_SPI_Send(unsigned char command) {
|
||||
spi_chip_select(0);
|
||||
spi_send(&command, 1);
|
||||
spi_chip_select(1); // De-select the ENC
|
||||
}
|
||||
|
||||
void ENC_SPI_SendWithoutSelection(unsigned char command) {
|
||||
spi_send(&command, 1);
|
||||
}
|
1525
part15-tcpip/tcpip/ip_arp_udp_tcp.c
Normal file
1525
part15-tcpip/tcpip/ip_arp_udp_tcp.c
Normal file
File diff suppressed because it is too large
Load diff
212
part15-tcpip/tcpip/ip_arp_udp_tcp.h
Normal file
212
part15-tcpip/tcpip/ip_arp_udp_tcp.h
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*********************************************
|
||||
* vim:sw=8:ts=8:si:et
|
||||
* To use the above modeline in vim you must have "set modeline" in your .vimrc
|
||||
* Author: Guido Socher
|
||||
* Copyright:LGPL V2
|
||||
* See http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html
|
||||
*
|
||||
* IP/ARP/UDP/TCP functions
|
||||
*
|
||||
* Chip type : ATMEGA88/168/328/644 with ENC28J60
|
||||
*********************************************/
|
||||
//@{
|
||||
#ifndef IP_ARP_UDP_TCP_H
|
||||
#define IP_ARP_UDP_TCP_H 1
|
||||
|
||||
#include "net.h"
|
||||
#include "../net/enc28j60.h"
|
||||
#include "../kernel/kernel.h"
|
||||
#include "../include/fb.h"
|
||||
#include "ip_config.h"
|
||||
|
||||
// set my own mac address:
|
||||
extern void init_mac(uint8_t *mymac); // not needed if you call init_udp_or_www_server
|
||||
// -- web server functions --
|
||||
#if defined (WWW_server) || defined (UDP_server)
|
||||
// you must call this function once before you use any of the other server functions:
|
||||
// mymac may be set to NULL in this function if init_mac was used before
|
||||
// init_ip_arp_udp_tcp is now replaced by init_udp_or_www_server and the www_server_port function.
|
||||
extern void init_udp_or_www_server(uint8_t *mymac,uint8_t *myip);
|
||||
#endif
|
||||
|
||||
#if defined (WWW_server)
|
||||
extern void www_server_port(uint16_t port); // not needed if you want port 80
|
||||
// send data from the web server to the client:
|
||||
extern void www_server_reply(uint8_t *buf,uint16_t dlen);
|
||||
#endif
|
||||
|
||||
// for a UDP server:
|
||||
#if defined (UDP_server)
|
||||
extern uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len);
|
||||
extern void make_udp_reply_from_request_udpdat_ready(uint8_t *buf,uint16_t datalen,uint16_t port);
|
||||
extern void make_udp_reply_from_request(uint8_t *buf,char *data,uint8_t datalen,uint16_t port);
|
||||
#endif
|
||||
// return 0 to just continue in the packet loop and return the position
|
||||
// of the tcp data if there is tcp data part:
|
||||
extern uint16_t packetloop_arp_icmp_tcp(uint8_t *buf,uint16_t plen);
|
||||
// functions to fill the web pages with data:
|
||||
extern uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const uint8_t *progmem_s);
|
||||
extern uint16_t fill_tcp_data_string(uint8_t *buf,uint16_t pos, char *reply);
|
||||
|
||||
extern uint16_t fill_tcp_data(uint8_t *buf,uint16_t pos, const char *s);
|
||||
// fill a binary string of len data into the tcp packet:
|
||||
extern uint16_t fill_tcp_data_len(uint8_t *buf,uint16_t pos, const uint8_t *s, uint8_t len);
|
||||
|
||||
// -- client only functions --
|
||||
#if defined (WWW_client) || defined (NTP_client) || defined (UDP_client) || defined (TCP_client) || defined (PING_client)
|
||||
extern void client_ifconfig(uint8_t *ip,uint8_t *netmask);
|
||||
// route_via_gw can be used decide if a packed needs to be routed via GW or can be found on the LAN:
|
||||
extern uint8_t route_via_gw(uint8_t *destip); // returns 1 if destip must be routed via the GW. Returns 0 if destip is on the local LAN
|
||||
//
|
||||
// The get_mac_with_arp function can be used to find the MAC address of
|
||||
// a host that is directly connected to the same LAN. It translates the IP address into
|
||||
// a MAC address.
|
||||
// You need to provide a callback function. That function will be executed once the
|
||||
// MAC address is found. We do this to not block execution in the main loop.
|
||||
// NOTE: you can only do one MAC address resolution at a time. The reference_number is just
|
||||
// a number given back to you to make it easier to know what this relates to.
|
||||
//
|
||||
// You declare the callback function:
|
||||
//
|
||||
//#define TRANS_NUM_GWMAC 12
|
||||
//void arpresolver_result_callback(uint8_t *ip __attribute__((unused)),uint8_t reference_number,uint8_t *mac){ // the __attribute__((unused)) is a gcc compiler directive to avoid warnings about unsed variables.
|
||||
// uint8_t i=0;
|
||||
// if (reference_number==TRANS_NUM_GWMAC){
|
||||
// // copy mac address over:
|
||||
// while(i<6){gwmac[i]=mac[i];i++;}
|
||||
// }
|
||||
//}
|
||||
//
|
||||
// and then you can just call get_mac_with_arp like this:
|
||||
// get_mac_with_arp(gwip,TRANS_NUM_GWMAC,&arpresolver_result_callback);
|
||||
// Note: you must have initialized the stack with init_udp_or_www_server or client_ifconfig
|
||||
// before you can use get_mac_with_arp(). The arp request will automatically be repeated if
|
||||
// there is no answer.
|
||||
extern void get_mac_with_arp(uint8_t *ip, uint8_t reference_number,void (*arp_result_callback)(uint8_t *ip,uint8_t reference_number,uint8_t *mac));
|
||||
uint8_t get_mac_with_arp_wait(void); // checks current ongoing transaction, retuns 0 when the transaction is over
|
||||
#endif
|
||||
|
||||
#ifdef TCP_client
|
||||
// To use the tcp client you need to:
|
||||
//
|
||||
// Declare a callback function to get the result (tcp data from the server):
|
||||
//
|
||||
// uint8_t your_client_tcp_result_callback(uint8_t fd, uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data){
|
||||
// ...your code;
|
||||
// return(close_tcp_session);
|
||||
// }
|
||||
//
|
||||
// statuscode=0 means the buffer has valid data, otherwise len and pos_in_buf
|
||||
// are invalid. That is: do to use data_start_pos_in_buf and len_of_data
|
||||
// if statuscode!=0.
|
||||
//
|
||||
// This callback gives you access to the TCP data of the first
|
||||
// packet returned from the server. You should aim to minimize the server
|
||||
// output such that this will be the only packet.
|
||||
//
|
||||
// close_tcp_session=1 means close the session now. close_tcp_session=0
|
||||
// read all data and leave it to the other side to close it.
|
||||
// If you connect to a web server then you want close_tcp_session=0.
|
||||
// If you connect to a modbus/tcp equipment then you want close_tcp_session=1
|
||||
//
|
||||
// Declare a callback function to be called in order to fill in the
|
||||
//
|
||||
// request (tcp data sent to the server):
|
||||
// uint16_t your_client_tcp_datafill_callback(uint8_t fd){...your code;return(len_of_data_filled_in);}
|
||||
//
|
||||
// Now call:
|
||||
// fd=client_tcp_req(&your_client_tcp_result_callback,&your_client_tcp_datafill_callback,portnumber);
|
||||
//
|
||||
// fd is a file descriptor like number that you get back in the fill and result
|
||||
// function so you know to which call of client_tcp_req this callback belongs.
|
||||
//
|
||||
// You can not start different clients (e.g modbus and web) at the
|
||||
// same time but you can start them one after each other. That is
|
||||
// when the request has timed out or when the result_callback was
|
||||
// executed then you can start a new one. The fd makes it still possible to
|
||||
// distinguish in the callback code the different types you started.
|
||||
//
|
||||
// Note that you might never get called back if the other side does
|
||||
// not answer. A timer would be needed to recongnize such a condition.
|
||||
//
|
||||
// We use callback functions because that is the best implementation
|
||||
// given the fact that we have very little RAM memory.
|
||||
//
|
||||
extern uint8_t client_tcp_req(uint8_t (*result_callback)(uint8_t fd,uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data),uint16_t (*datafill_callback)(uint8_t fd),uint16_t port,uint8_t *dstip,uint8_t *dstmac);
|
||||
#endif
|
||||
|
||||
#ifdef WWW_client
|
||||
// ----- http get
|
||||
// The string buffers to which urlbuf_varpart and hoststr are pointing
|
||||
// must not be changed until the callback is executed.
|
||||
extern void client_browse_url(const prog_char *urlbuf, char *urlbuf_varpart, const char *hoststr,void (*callback)(uint16_t,uint16_t,uint16_t),uint8_t *dstip,uint8_t *dstmac);
|
||||
// The callback is a reference to a function which must look like this:
|
||||
// void browserresult_callback(uint16_t webstatuscode,uint16_t datapos,uint16_t len)
|
||||
// webstatuscode is zero if there was no proper reply from the server (garbage message total communication failure, this is rare).
|
||||
// webstatuscode is otherwise the http status code (e.g webstatuscode=200 for 200 OK);
|
||||
// For possible status codes look at http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
// Basically 2xx is success and any 5xx, 4xx is a failure.
|
||||
// ----- http post
|
||||
// client web browser using http POST operation:
|
||||
// additionalheaderline must be set to NULL if not used.
|
||||
// The string buffers to which urlbuf_varpart and hoststr are pointing
|
||||
// must not be changed until the callback is executed.
|
||||
// postval is a string buffer which can only be de-allocated by the caller
|
||||
// when the post operation was really done (e.g when callback was executed).
|
||||
// postval must be urlencoded.
|
||||
extern void client_http_post(const prog_char *urlbuf, char *urlbuf_varpart,const char *hoststr, const prog_char *additionalheaderline,char *postval,void (*callback)(uint16_t,uint16_t,uint16_t),uint8_t *dstip,uint8_t *dstmac);
|
||||
// The callback is a reference to a function which must look like this:
|
||||
// void browserresult_callback(uint16_t webstatuscode,uint16_t datapos,uint16_t len)
|
||||
// webstatuscode is zero if there was no proper reply from the server (garbage message total communication failure, this is rare).
|
||||
// webstatuscode is otherwise the http status code (e.g webstatuscode=200 for 200 OK);
|
||||
#endif
|
||||
|
||||
#ifdef NTP_client
|
||||
// be careful to not mix client_ntp_request with situations where you are filling
|
||||
// a web-page. Normally you will be using the same packet buffer and
|
||||
// client_ntp_request writes immediately to buf. You might need to
|
||||
// set a marker and call client_ntp_request when your main loop is idle.
|
||||
extern void client_ntp_request(uint8_t *buf,uint8_t *ntpip,uint8_t srcport,uint8_t *dstmac);
|
||||
extern uint8_t client_ntp_process_answer(uint8_t *buf,uint32_t *time,uint8_t dstport_l);
|
||||
#endif
|
||||
|
||||
#ifdef UDP_client
|
||||
// There are two ways of using this UDP client:
|
||||
//
|
||||
// 1) you call send_udp_prepare, you fill the data yourself into buf starting at buf[UDP_DATA_P],
|
||||
// you send the packet by calling send_udp_transmit
|
||||
//
|
||||
// 2) You just allocate a large enough buffer for you data and you call send_udp and nothing else
|
||||
// needs to be done.
|
||||
//
|
||||
extern void send_udp_prepare(uint8_t *buf,uint16_t sport, const uint8_t *dip, uint16_t dport,const uint8_t *dstmac);
|
||||
extern void send_udp_transmit(uint8_t *buf,uint16_t datalen);
|
||||
|
||||
// send_udp sends via gwip, you must call client_set_gwip at startup, datalen must be less than 220 bytes
|
||||
extern void send_udp(uint8_t *buf,char *data,uint8_t datalen,uint16_t sport, const uint8_t *dip, uint16_t dport,const uint8_t *dstmac);
|
||||
#endif
|
||||
|
||||
// you can find out who ping-ed you if you want:
|
||||
extern void register_ping_rec_callback(void (*callback)(uint8_t *srcip));
|
||||
|
||||
#ifdef PING_client
|
||||
extern void client_icmp_request(uint8_t *buf,uint8_t *destip,uint8_t *dstmac);
|
||||
// you must loop over this function to check if there was a ping reply:
|
||||
extern uint8_t packetloop_icmp_checkreply(uint8_t *buf,uint8_t *ip_monitoredhost);
|
||||
#endif // PING_client
|
||||
|
||||
#ifdef WOL_client
|
||||
extern void send_wol(uint8_t *buf,uint8_t *wolmac);
|
||||
#endif // WOL_client
|
||||
|
||||
#if defined GRATARP
|
||||
// send a Gratuitous arp, this is to refresh the arp
|
||||
// cash of routers and switches. It can improve the response
|
||||
// time in wifi networks as some wifi equipment expects the initial
|
||||
// communication to not start from the network side. That is wrong
|
||||
// but some consumer devices are made like this.
|
||||
extern uint8_t gratutious_arp(uint8_t *buf);
|
||||
#endif // GRATARP
|
||||
|
||||
#endif /* IP_ARP_UDP_TCP_H */
|
||||
//@}
|
53
part15-tcpip/tcpip/ip_config.h
Normal file
53
part15-tcpip/tcpip/ip_config.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*********************************************
|
||||
* vim:sw=8:ts=8:si:et
|
||||
* To use the above modeline in vim you must have "set modeline" in your .vimrc
|
||||
* Author: Guido Socher
|
||||
* Copyright:LGPL V2
|
||||
* See http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html
|
||||
*
|
||||
* This file can be used to decide which functionallity of the
|
||||
* TCP/IP stack shall be available. By picking the right functions
|
||||
* you can significantly reduce the size of the resulting code.
|
||||
*
|
||||
*********************************************/
|
||||
//@{
|
||||
#ifndef IP_CONFIG_H
|
||||
#define IP_CONFIG_H
|
||||
|
||||
//------------- functions in ip_arp_udp_tcp.c --------------
|
||||
// an NTP client (ntp clock):
|
||||
#undef NTP_client
|
||||
// a spontanious sending UDP client (needed as well for DNS and DHCP)
|
||||
#undef UDP_client
|
||||
// a server answering to UDP messages
|
||||
#define UDP_server
|
||||
// a web server
|
||||
#undef WWW_server
|
||||
|
||||
// to send out a ping:
|
||||
#undef PING_client
|
||||
#define PINGPATTERN 0x42
|
||||
|
||||
// a UDP wake on lan sender:
|
||||
#undef WOL_client
|
||||
|
||||
// function to send a gratuitous arp
|
||||
#undef GRATARP
|
||||
|
||||
// a "web browser". This can be use to upload data
|
||||
// to a web server on the internet by encoding the data
|
||||
// into the url (like a Form action of type GET):
|
||||
#undef WWW_client
|
||||
// if you do not need a browser and just a server:
|
||||
//#undef WWW_client
|
||||
//
|
||||
//------------- functions in websrv_help_functions.c --------------
|
||||
//
|
||||
// functions to decode cgi-form data:
|
||||
#undef FROMDECODE_websrv_help
|
||||
|
||||
// function to encode a URL (mostly needed for a web client)
|
||||
#undef URLENCODE_websrv_help
|
||||
|
||||
#endif /* IP_CONFIG_H */
|
||||
//@}
|
132
part15-tcpip/tcpip/net.h
Normal file
132
part15-tcpip/tcpip/net.h
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*********************************************
|
||||
* vim:sw=8:ts=8:si:et
|
||||
* To use the above modeline in vim you must have "set modeline" in your .vimrc
|
||||
* Author: Guido Socher
|
||||
* Copyright:LGPL V2
|
||||
* See http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html
|
||||
*
|
||||
* Based on the net.h file from the AVRlib library by Pascal Stang.
|
||||
* For AVRlib See http://www.procyonengineering.com/
|
||||
* Used with explicit permission of Pascal Stang.
|
||||
*
|
||||
*********************************************/
|
||||
|
||||
// notation: _P = position of a field
|
||||
// _V = value of a field
|
||||
|
||||
//@{
|
||||
|
||||
#ifndef NET_H
|
||||
#define NET_H
|
||||
|
||||
// ******* ETH *******
|
||||
#define ETH_HEADER_LEN 14
|
||||
// values of certain bytes:
|
||||
#define ETHTYPE_ARP_H_V 0x08
|
||||
#define ETHTYPE_ARP_L_V 0x06
|
||||
#define ETHTYPE_IP_H_V 0x08
|
||||
#define ETHTYPE_IP_L_V 0x00
|
||||
// byte positions in the ethernet frame:
|
||||
//
|
||||
// Ethernet type field (2bytes):
|
||||
#define ETH_TYPE_H_P 12
|
||||
#define ETH_TYPE_L_P 13
|
||||
//
|
||||
#define ETH_DST_MAC 0
|
||||
#define ETH_SRC_MAC 6
|
||||
|
||||
|
||||
// ******* ARP *******
|
||||
#define ETH_ARP_OPCODE_REPLY_H_V 0x0
|
||||
#define ETH_ARP_OPCODE_REPLY_L_V 0x02
|
||||
#define ETH_ARP_OPCODE_REQ_H_V 0x0
|
||||
#define ETH_ARP_OPCODE_REQ_L_V 0x01
|
||||
// start of arp header:
|
||||
#define ETH_ARP_P 0xe
|
||||
//
|
||||
#define ETHTYPE_ARP_L_V 0x06
|
||||
// arp.dst.ip
|
||||
#define ETH_ARP_DST_IP_P 0x26
|
||||
// arp.opcode
|
||||
#define ETH_ARP_OPCODE_H_P 0x14
|
||||
#define ETH_ARP_OPCODE_L_P 0x15
|
||||
// arp.src.mac
|
||||
#define ETH_ARP_SRC_MAC_P 0x16
|
||||
#define ETH_ARP_SRC_IP_P 0x1c
|
||||
#define ETH_ARP_DST_MAC_P 0x20
|
||||
#define ETH_ARP_DST_IP_P 0x26
|
||||
|
||||
// ******* IP *******
|
||||
#define IP_HEADER_LEN 20
|
||||
// ip.src
|
||||
#define IP_SRC_P 0x1a
|
||||
#define IP_DST_P 0x1e
|
||||
#define IP_HEADER_LEN_VER_P 0xe
|
||||
#define IP_CHECKSUM_P 0x18
|
||||
#define IP_TTL_P 0x16
|
||||
#define IP_FLAGS_P 0x14
|
||||
#define IP_P 0xe
|
||||
#define IP_TOTLEN_H_P 0x10
|
||||
#define IP_TOTLEN_L_P 0x11
|
||||
#define IP_ID_H_P 0x12
|
||||
#define IP_ID_L_P 0x13
|
||||
|
||||
#define IP_PROTO_P 0x17
|
||||
|
||||
#define IP_PROTO_ICMP_V 1
|
||||
#define IP_PROTO_TCP_V 6
|
||||
// 17=0x11
|
||||
#define IP_PROTO_UDP_V 17
|
||||
// ******* ICMP *******
|
||||
#define ICMP_TYPE_ECHOREPLY_V 0
|
||||
#define ICMP_TYPE_ECHOREQUEST_V 8
|
||||
//
|
||||
#define ICMP_TYPE_P 0x22
|
||||
#define ICMP_CHECKSUM_P 0x24
|
||||
#define ICMP_CHECKSUM_H_P 0x24
|
||||
#define ICMP_CHECKSUM_L_P 0x25
|
||||
#define ICMP_IDENT_H_P 0x26
|
||||
#define ICMP_IDENT_L_P 0x27
|
||||
#define ICMP_DATA_P 0x2a
|
||||
|
||||
// ******* UDP *******
|
||||
#define UDP_HEADER_LEN 8
|
||||
//
|
||||
#define UDP_SRC_PORT_H_P 0x22
|
||||
#define UDP_SRC_PORT_L_P 0x23
|
||||
#define UDP_DST_PORT_H_P 0x24
|
||||
#define UDP_DST_PORT_L_P 0x25
|
||||
//
|
||||
#define UDP_LEN_H_P 0x26
|
||||
#define UDP_LEN_L_P 0x27
|
||||
#define UDP_CHECKSUM_H_P 0x28
|
||||
#define UDP_CHECKSUM_L_P 0x29
|
||||
#define UDP_DATA_P 0x2a
|
||||
|
||||
// ******* TCP *******
|
||||
#define TCP_SRC_PORT_H_P 0x22
|
||||
#define TCP_SRC_PORT_L_P 0x23
|
||||
#define TCP_DST_PORT_H_P 0x24
|
||||
#define TCP_DST_PORT_L_P 0x25
|
||||
// the tcp seq number is 4 bytes 0x26-0x29
|
||||
#define TCP_SEQ_H_P 0x26
|
||||
#define TCP_SEQACK_H_P 0x2a
|
||||
// flags: SYN=2
|
||||
#define TCP_FLAGS_P 0x2f
|
||||
#define TCP_FLAGS_SYN_V 2
|
||||
#define TCP_FLAGS_FIN_V 1
|
||||
#define TCP_FLAGS_RST_V 4
|
||||
#define TCP_FLAGS_PUSH_V 8
|
||||
#define TCP_FLAGS_SYNACK_V 0x12
|
||||
#define TCP_FLAGS_ACK_V 0x10
|
||||
#define TCP_FLAGS_PSHACK_V 0x18
|
||||
// plain len without the options:
|
||||
#define TCP_HEADER_LEN_PLAIN 20
|
||||
#define TCP_HEADER_LEN_P 0x2e
|
||||
#define TCP_WIN_SIZE 0x30
|
||||
#define TCP_CHECKSUM_H_P 0x32
|
||||
#define TCP_CHECKSUM_L_P 0x33
|
||||
#define TCP_OPTIONS_P 0x36
|
||||
//
|
||||
#endif
|
||||
//@}
|
Loading…
Reference in a new issue