+ noekeon
This commit is contained in:
parent
2c2d732098
commit
9e7453525f
25
Makefile
25
Makefile
|
@ -7,7 +7,8 @@ HASHES :=
|
|||
MACS :=
|
||||
PRNGS :=
|
||||
|
||||
|
||||
# we use the gnu make standard library
|
||||
include gmsl
|
||||
include avr-makefile.inc
|
||||
include *.mk
|
||||
|
||||
|
@ -23,6 +24,9 @@ ALGORITHMS_TEST_BIN_IMM = $(foreach a, $(ALGORITHMS_TEST_BIN), $($(a)))
|
|||
ALGORITHMS_NESSIE_TEST = $(patsubst %,%_NESSIE_TEST, $(ALGORITHMS))
|
||||
ALGORITHMS_PERFORMANCE_TEST = $(patsubst %,%_PERORMANCE_TEST, $(ALGORITHMS))
|
||||
|
||||
#ALGORITHMS_LC = #algorithm names in lowercase
|
||||
#ALGORITHMS_LC = $(foreach a, $(ALGORITHMS), $$(lc Text))
|
||||
ALGORITHMS_LC = $(call lc,$(ALGORITHMS))
|
||||
PRG = remove_me
|
||||
|
||||
DEFS =
|
||||
|
@ -53,6 +57,9 @@ info:
|
|||
@echo " $(MACS)"
|
||||
@echo " PRNG functions:"
|
||||
@echo " $(PRNGS)"
|
||||
@echo " LC functions:"
|
||||
@echo " $(ALGORITHMS_LC)"
|
||||
|
||||
# echo $(ALGORITHMS_TEST_BIN_MAIN)
|
||||
# echo $(ALGORITHMS)
|
||||
# echo $(firstword $(XTEA_TEST_BIN))
|
||||
|
@ -111,6 +118,18 @@ $(MACS_OBJ): $(patsubst %,%_OBJ, $(MACS))
|
|||
|
||||
$(ALGORITHMS_TEST_BIN): $(ALGORITHMS_TEST_BIN_IMM)
|
||||
|
||||
|
||||
define SIZE_TEMPLATE
|
||||
$(1)_size.txt: $(2)
|
||||
@echo " ALGO: $(1)"
|
||||
@echo " REQ: $(2)"
|
||||
$(SIZE) $(2) > $(1)_size.txt
|
||||
endef
|
||||
|
||||
$(foreach algo, $(ALGORITHMS), $(eval $(call SIZE_TEMPLATE, $(call lc,$(algo)), $($(algo)_OBJ))))
|
||||
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all: $(PRG).elf lst text eeprom
|
||||
|
||||
|
@ -163,8 +182,8 @@ esrec: $(PRG)_eeprom.srec
|
|||
%_eeprom.bin: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@
|
||||
|
||||
%_size.txt: %.o
|
||||
$(SIZE) $< > $@
|
||||
#%_size.txt: %.o
|
||||
# $(SIZE) $< > $@
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
OBJ = $(SERPENT_OBJ)
|
||||
MCU_TARGET = atmega32
|
||||
MCU_TARGET = atmega644
|
||||
OPTIMIZE = -Os
|
||||
|
||||
DEFS = -DATMEGA644
|
||||
FLASHCMD = avrdude -p $(MCU_TARGET) -P /dev/ttyUSB0 -c avr911 -U flash:w:$(PRG).hex
|
||||
# -U eeprom:w:$(PRG)_eeprom.hex
|
||||
#uisp -dprog=bsd -dlpt=/dev/parport1 --upload if=$(PRG).hex
|
||||
|
@ -10,8 +10,8 @@ ERASECMD =
|
|||
|
||||
CC = avr-gcc
|
||||
|
||||
override CFLAGS = -pedantic -std=c99 -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET)
|
||||
$(DEFS)
|
||||
override CFLAGS = -pedantic -std=c99 -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
|
||||
|
||||
override LDFLAGS = -Wl,-Map,
|
||||
override ASFLAGS = -mmcu=$(MCU_TARGET)
|
||||
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* serpent test-suit
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "serial-tools.h"
|
||||
#include "uart.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "noekeon.h"
|
||||
#include "nessie_bc_test.h"
|
||||
#include "cli.h"
|
||||
#include "performance_test.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char* cipher_name = "Noekeon";
|
||||
|
||||
/*****************************************************************************
|
||||
* additional validation-functions *
|
||||
*****************************************************************************/
|
||||
void noekeon_genctx_dummy(uint8_t* key, uint16_t keysize, void* ctx){
|
||||
noekeon_init(key, ctx);
|
||||
}
|
||||
|
||||
void testrun_nessie_noekeon_indirect(void){
|
||||
char str[strlen(cipher_name)+10];
|
||||
strcpy(str, cipher_name);
|
||||
strcat(str, "-indirect");
|
||||
|
||||
nessie_bc_ctx.blocksize_B = 16;
|
||||
nessie_bc_ctx.keysize_b = 128;
|
||||
nessie_bc_ctx.name = str;
|
||||
nessie_bc_ctx.ctx_size_B = sizeof(noekeon_ctx_t);
|
||||
nessie_bc_ctx.cipher_enc = (nessie_bc_enc_fpt)noekeon_enc;
|
||||
nessie_bc_ctx.cipher_dec = (nessie_bc_dec_fpt)noekeon_dec;
|
||||
nessie_bc_ctx.cipher_genctx = (nessie_bc_gen_fpt)noekeon_genctx_dummy;
|
||||
|
||||
nessie_bc_run();
|
||||
}
|
||||
|
||||
void noekeon_genctx_dummy_direct(uint8_t* key, uint16_t keysize, void* ctx){
|
||||
memcpy(ctx, key, 16);
|
||||
}
|
||||
|
||||
void testrun_nessie_noekeon_direct(void){
|
||||
char str[strlen(cipher_name)+10];
|
||||
strcpy(str, cipher_name);
|
||||
strcat(str, "-Direct");
|
||||
|
||||
nessie_bc_ctx.blocksize_B = 16;
|
||||
nessie_bc_ctx.keysize_b = 128;
|
||||
nessie_bc_ctx.name = str;
|
||||
nessie_bc_ctx.ctx_size_B = sizeof(noekeon_ctx_t);
|
||||
nessie_bc_ctx.cipher_enc = (nessie_bc_enc_fpt)noekeon_enc;
|
||||
nessie_bc_ctx.cipher_dec = (nessie_bc_dec_fpt)noekeon_dec;
|
||||
nessie_bc_ctx.cipher_genctx = (nessie_bc_gen_fpt)noekeon_genctx_dummy_direct;
|
||||
|
||||
nessie_bc_run();
|
||||
}
|
||||
|
||||
void testrun_stdtest_rundirect(void* data, void* key){
|
||||
uart_putstr_P(PSTR("\r\n "));
|
||||
uart_putstr_P(PSTR("k = "));
|
||||
uart_hexdump(key,16);
|
||||
|
||||
uart_putstr_P(PSTR("\r\n "));
|
||||
uart_putstr_P(PSTR("a = "));
|
||||
uart_hexdump(data,16);
|
||||
|
||||
noekeon_enc(data, key);
|
||||
uart_putstr_P(PSTR("\r\nafter NESSIEencrypt, b = "));
|
||||
uart_hexdump(data,16);
|
||||
|
||||
noekeon_dec(data, key);
|
||||
uart_putstr_P(PSTR("\r\nafter NESSIEdecrypt, a?= "));
|
||||
uart_hexdump(data,16);
|
||||
uart_putstr_P(PSTR("\r\n"));
|
||||
}
|
||||
|
||||
void testrun_stdtest_runindirect(void* data, void* key){
|
||||
noekeon_ctx_t ctx;
|
||||
uart_putstr_P(PSTR("\r\n "));
|
||||
uart_putstr_P(PSTR("k = "));
|
||||
uart_hexdump(key,16);
|
||||
|
||||
uart_putstr_P(PSTR("\r\n "));
|
||||
uart_putstr_P(PSTR("a = "));
|
||||
uart_hexdump(data,16);
|
||||
noekeon_init(key, &ctx);
|
||||
noekeon_enc(data, &ctx);
|
||||
uart_putstr_P(PSTR("\r\nafter NESSIEencrypt, b = "));
|
||||
uart_hexdump(data,16);
|
||||
|
||||
noekeon_dec(data, &ctx);
|
||||
uart_putstr_P(PSTR("\r\nafter NESSIEdecrypt, a?= "));
|
||||
uart_hexdump(data,16);
|
||||
uart_putstr_P(PSTR("\r\n"));
|
||||
}
|
||||
|
||||
void testrun_stdtest_noekeon(void){
|
||||
uint8_t key[16], data[16];
|
||||
uint8_t key3[16];
|
||||
noekeon_ctx_t ctx;
|
||||
|
||||
uart_putstr_P(PSTR("\r\nTest vectors for block cipher Noekeon in Indirect-Key Mode:\r\n"));
|
||||
|
||||
memset(key, 0, 16);
|
||||
memset(data, 0, 16);
|
||||
testrun_stdtest_runindirect(data, key);
|
||||
|
||||
memset(key, 0xFF, 16);
|
||||
memset(data, 0xFF, 16);
|
||||
testrun_stdtest_runindirect(data, key);
|
||||
|
||||
memset(key, 0, 16);
|
||||
memset(data, 0, 16);
|
||||
noekeon_init(key, &ctx);
|
||||
noekeon_enc(data, &ctx);
|
||||
memcpy(key3, data, 16);
|
||||
memset(key, 0xFF, 16);
|
||||
memset(data, 0xFF, 16);
|
||||
noekeon_init(key, &ctx);
|
||||
noekeon_enc(data, &ctx);
|
||||
testrun_stdtest_runindirect(data, key3);
|
||||
|
||||
|
||||
uart_putstr_P(PSTR("\r\nTest vectors for block cipher Noekeon in Direct-Key Mode:\r\n"));
|
||||
|
||||
memset(key, 0, 16);
|
||||
memset(data, 0, 16);
|
||||
testrun_stdtest_rundirect(data, key);
|
||||
|
||||
memset(key, 0xFF, 16);
|
||||
memset(data, 0xFF, 16);
|
||||
testrun_stdtest_rundirect(data, key);
|
||||
|
||||
memset(key, 0, 16);
|
||||
memset(data, 0, 16);
|
||||
noekeon_enc(data, key);
|
||||
memcpy(key3, data, 16);
|
||||
memset(key, 0xFF, 16);
|
||||
memset(data, 0xFF, 16);
|
||||
noekeon_enc(data, key);
|
||||
testrun_stdtest_rundirect(data, key3);
|
||||
|
||||
}
|
||||
|
||||
void testrun_performance_noekeon(void){
|
||||
uint16_t i,c;
|
||||
uint64_t t;
|
||||
char str[6];
|
||||
uint8_t key[16], data[16];
|
||||
noekeon_ctx_t ctx;
|
||||
|
||||
calibrateTimer();
|
||||
getOverhead(&c, &i);
|
||||
uart_putstr_P(PSTR("\r\n\r\n=== benchmark ==="));
|
||||
utoa(c, str, 10);
|
||||
uart_putstr_P(PSTR("\r\n\tconst overhead: "));
|
||||
uart_putstr(str);
|
||||
utoa(i, str, 10);
|
||||
uart_putstr_P(PSTR("\r\n\tinterrupt overhead: "));
|
||||
uart_putstr(str);
|
||||
|
||||
memset(key, 0, 16);
|
||||
memset(data, 0, 16);
|
||||
|
||||
startTimer(1);
|
||||
noekeon_init(key, &ctx);
|
||||
t = stopTimer();
|
||||
uart_putstr_P(PSTR("\r\n\tctx-gen time: "));
|
||||
uart_hexdump(&t, 8);
|
||||
|
||||
|
||||
startTimer(1);
|
||||
noekeon_enc(data, ctx);
|
||||
t = stopTimer();
|
||||
uart_putstr_P(PSTR("\r\n\tencrypt time: "));
|
||||
uart_hexdump(&t, 8);
|
||||
|
||||
|
||||
startTimer(1);
|
||||
noekeon_dec(data, ctx);
|
||||
t = stopTimer();
|
||||
uart_putstr_P(PSTR("\r\n\tdecrypt time: "));
|
||||
uart_hexdump(&t, 8);
|
||||
uart_putstr_P(PSTR("\r\n"));
|
||||
}
|
||||
/*****************************************************************************
|
||||
* main *
|
||||
*****************************************************************************/
|
||||
|
||||
typedef void(*void_fpt)(void);
|
||||
|
||||
int main (void){
|
||||
char str[20];
|
||||
DEBUG_INIT();
|
||||
uart_putstr("\r\n");
|
||||
|
||||
uart_putstr_P(PSTR("\r\n\r\nCrypto-VS ("));
|
||||
uart_putstr(cipher_name);
|
||||
uart_putstr_P(PSTR(")\r\nloaded and running\r\n"));
|
||||
|
||||
PGM_P u = PSTR("nessie\0test\0direct\0indirect\0performance\0");
|
||||
void_fpt v[] = {testrun_nessie_noekeon_direct,
|
||||
testrun_stdtest_noekeon,
|
||||
testrun_nessie_noekeon_direct,
|
||||
testrun_nessie_noekeon_indirect,
|
||||
testrun_performance_noekeon};
|
||||
|
||||
while(1){
|
||||
if (!getnextwordn(str,20)){DEBUG_S("DBG: W1\r\n"); goto error;}
|
||||
if(execcommand_d0_P(str, u, v)<0){
|
||||
uart_putstr_P(PSTR("\r\nunknown command\r\n"));
|
||||
}
|
||||
continue;
|
||||
error:
|
||||
uart_putstr("ERROR\r\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* author: Daniel Otte
|
||||
* email: daniel.otte@rub.de
|
||||
* license: GPLv3
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "noekeon.h"
|
||||
|
||||
#define ROUND_NR 16
|
||||
|
||||
#define RC_POS 0
|
||||
|
||||
static
|
||||
void gamma(uint32_t* a){
|
||||
uint32_t tmp;
|
||||
|
||||
a[1] ^= ~((a[3]) | (a[2]));
|
||||
a[0] ^= a[2] & a[1];
|
||||
|
||||
tmp=a[3]; a[3]=a[0]; a[0]=tmp;
|
||||
a[2] ^= a[0] ^ a[1] ^ a[3];
|
||||
|
||||
a[1] ^= ~((a[3]) | (a[2]));
|
||||
a[0] ^= a[2] & a[1];
|
||||
}
|
||||
|
||||
#define ROTL32(a,n) (((a)<<n)|((a)>>(32-n)))
|
||||
#define ROTR32(a,n) (((a)>>n)|((a)<<(32-n)))
|
||||
|
||||
static
|
||||
void pi1(uint32_t* a){
|
||||
a[1] = ROTL32(a[1], 1);
|
||||
a[2] = ROTL32(a[2], 5);
|
||||
a[3] = ROTL32(a[3], 2);
|
||||
}
|
||||
|
||||
static
|
||||
void pi2(uint32_t* a){
|
||||
a[1] = ROTR32(a[1], 1);
|
||||
a[2] = ROTR32(a[2], 5);
|
||||
a[3] = ROTR32(a[3], 2);
|
||||
}
|
||||
|
||||
static
|
||||
void theta(uint32_t* k, uint32_t* a){
|
||||
uint32_t temp;
|
||||
temp = a[0] ^ a[2]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
|
||||
a[1] ^= temp;
|
||||
a[3] ^= temp;
|
||||
|
||||
a[0] ^= k[0];
|
||||
a[1] ^= k[1];
|
||||
a[2] ^= k[2];
|
||||
a[3] ^= k[3];
|
||||
|
||||
temp = a[1] ^ a[3]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
|
||||
a[0] ^= temp;
|
||||
a[2] ^= temp;
|
||||
}
|
||||
|
||||
static
|
||||
void noekeon_round(uint32_t* key, uint32_t* state, uint8_t const1, uint8_t const2){
|
||||
((uint8_t*)state)[RC_POS] ^= const1;
|
||||
theta(key, state);
|
||||
((uint8_t*)state)[RC_POS] ^= const2;
|
||||
pi1(state);
|
||||
gamma(state);
|
||||
pi2(state);
|
||||
}
|
||||
|
||||
uint8_t rc_tab[] PROGMEM = {
|
||||
/* 0x80, */
|
||||
0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
|
||||
0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
|
||||
0xD4
|
||||
};
|
||||
/* for more rounds
|
||||
0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
|
||||
0x72, 0xE4, 0xD3, 0xBD, 0x61, 0xC2, 0x9F, 0x25,
|
||||
*/
|
||||
|
||||
static
|
||||
void changendian32(void* a){
|
||||
((uint8_t*)a)[0] ^= ((uint8_t*)a)[3];
|
||||
((uint8_t*)a)[3] ^= ((uint8_t*)a)[0];
|
||||
((uint8_t*)a)[0] ^= ((uint8_t*)a)[3];
|
||||
|
||||
((uint8_t*)a)[1] ^= ((uint8_t*)a)[2];
|
||||
((uint8_t*)a)[2] ^= ((uint8_t*)a)[1];
|
||||
((uint8_t*)a)[1] ^= ((uint8_t*)a)[2];
|
||||
}
|
||||
|
||||
static
|
||||
void changendian(void* a){
|
||||
changendian32((uint32_t*)(&(((uint32_t*)a)[0])));
|
||||
changendian32((uint32_t*)(&(((uint32_t*)a)[1])));
|
||||
changendian32((uint32_t*)(&(((uint32_t*)a)[2])));
|
||||
changendian32((uint32_t*)(&(((uint32_t*)a)[3])));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void noekeon_enc(void* buffer, void* key){
|
||||
uint8_t rc=0x80;
|
||||
int8_t i;
|
||||
|
||||
changendian(buffer);
|
||||
changendian(key);
|
||||
|
||||
for(i=0; i<ROUND_NR; ++i){
|
||||
noekeon_round((uint32_t*)key, (uint32_t*)buffer, rc, 0);
|
||||
rc = pgm_read_byte(rc_tab+i);
|
||||
}
|
||||
((uint8_t*)buffer)[RC_POS] ^= rc;
|
||||
theta((uint32_t*)key, (uint32_t*)buffer);
|
||||
|
||||
changendian(buffer);
|
||||
changendian(key);
|
||||
}
|
||||
|
||||
|
||||
void noekeon_dec(void* buffer, void* key){
|
||||
uint8_t rc;
|
||||
int8_t i;
|
||||
uint8_t nullv[16];
|
||||
uint8_t dkey[16];
|
||||
|
||||
|
||||
changendian(buffer);
|
||||
changendian(key);
|
||||
|
||||
memset(nullv, 0, 16);
|
||||
memcpy(dkey, key, 16);
|
||||
|
||||
theta((uint32_t*)nullv, (uint32_t*)dkey);
|
||||
for(i=ROUND_NR-1; i>=0; --i){
|
||||
rc = pgm_read_byte(rc_tab+i);
|
||||
noekeon_round((uint32_t*)dkey, (uint32_t*)buffer, 0, rc);
|
||||
}
|
||||
theta((uint32_t*)dkey, (uint32_t*)buffer);
|
||||
((uint8_t*)buffer)[RC_POS] ^= 0x80;
|
||||
|
||||
changendian(buffer);
|
||||
changendian(key);
|
||||
}
|
||||
|
||||
void noekeon_init(void* key, noekeon_ctx_t* ctx){
|
||||
uint8_t nullv[16];
|
||||
|
||||
memset(nullv, 0, 16);
|
||||
memcpy(ctx, key, 16);
|
||||
noekeon_enc(ctx, nullv);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef NOEKEON_H_
|
||||
#define NOEKEON_H_
|
||||
|
||||
/*
|
||||
* author: Daniel Otte
|
||||
* email: daniel.otte@rub.de
|
||||
* license: GPLv3
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint8_t noekeon_ctx_t[16];
|
||||
|
||||
void noekeon_enc(void* buffer, void* key);
|
||||
void noekeon_dec(void* buffer, void* key);
|
||||
void noekeon_init(void* key, noekeon_ctx_t* ctx);
|
||||
|
||||
#endif /*NOEKEON_H_*/
|
|
@ -1,15 +1,25 @@
|
|||
/*
|
||||
* author: Daniel Otte
|
||||
* email: daniel.otte@rub.de
|
||||
* license: GPLv3
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
**/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "performance_test.h"
|
||||
|
||||
|
||||
#ifdef ATMEGA644
|
||||
#define TIMSK TIMSK1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
uint32_t ovfcounter;
|
||||
|
||||
uint16_t const_overhead=0;
|
||||
|
@ -37,7 +47,7 @@ void startTimer(uint8_t granularity){
|
|||
ovfcounter = 0;
|
||||
TCCR1A = 0x00;
|
||||
TIMSK &= 0xC3;
|
||||
TIMSK |= _BV(2); /* enable TOIE1 */
|
||||
TIMSK |= _BV(TOIE1); /* enable TOIE1 */
|
||||
TCCR1B = granularity & 0x7; /* start timer */
|
||||
}
|
||||
|
||||
|
|
167
uart.c
167
uart.c
|
@ -3,7 +3,6 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <avr/io.h>
|
||||
//#include <avr/signal.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -18,9 +17,42 @@
|
|||
#define URSEL UMSEL
|
||||
#endif
|
||||
|
||||
#ifdef ATMEGA644
|
||||
#define UCSRB UCSR0B
|
||||
#define UCSRC UCSR0C
|
||||
#define UDR UDR0
|
||||
#define UBRRH UBRR0H
|
||||
#define UBRRL UBRR0L
|
||||
#define URSEL UMSEL00
|
||||
#define USART_UDRE_vect USART0_UDRE_vect
|
||||
#define USART_RXC_vect USART0_RX_vect
|
||||
#define UDRIE UDRIE0
|
||||
#define TXEN TXEN0
|
||||
#define UMSEL UMSEL0
|
||||
#define RXEN RXEN0
|
||||
#define RXCIE RXCIE0
|
||||
#define UCSZ0 UCSZ00
|
||||
#define UCSRA UCSR0A
|
||||
#define UDRE UDRE0
|
||||
#define RXC RXC0
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef UART_XON_XOFF
|
||||
#ifdef UART_INTERRUPT
|
||||
void uart_insertc(char c);
|
||||
#else
|
||||
#define uart_insertc uart_putc
|
||||
#endif /* UART_INTERRUPT */
|
||||
#endif
|
||||
|
||||
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16L)-1)
|
||||
|
||||
#ifdef UART_XON_XOFF
|
||||
typedef enum{go=1,nogo=0} gonogo;
|
||||
static gonogo txon=go;
|
||||
static gonogo rxon=go;
|
||||
#endif
|
||||
|
||||
#ifdef UART_INTERRUPT
|
||||
volatile static char rxbuf[UART_RXBUFSIZE];
|
||||
|
@ -28,8 +60,11 @@ volatile static char txbuf[UART_TXBUFSIZE];
|
|||
volatile static char *volatile rxhead, *volatile rxtail;
|
||||
volatile static char *volatile txhead, *volatile txtail;
|
||||
|
||||
#ifdef UART_HOOK
|
||||
void (*uart_hook) (uint8_t) = (void*)0; /* this is a pointer to a function ;-) */
|
||||
#endif
|
||||
|
||||
SIGNAL(SIG_UART_DATA) {
|
||||
ISR(USART_UDRE_vect) {
|
||||
#ifdef UART_LEDS
|
||||
PORTC ^= 0x01;
|
||||
#endif
|
||||
|
@ -37,39 +72,89 @@ SIGNAL(SIG_UART_DATA) {
|
|||
if ( txhead == txtail ) {
|
||||
UCSRB &= ~(1 << UDRIE); /* disable data register empty IRQ */
|
||||
} else {
|
||||
#ifdef UART_XON_XOFF
|
||||
while(txon==nogo)
|
||||
;
|
||||
#endif
|
||||
UDR = *txtail; /* schreibt das Zeichen x auf die Schnittstelle */
|
||||
if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf;
|
||||
}
|
||||
}
|
||||
|
||||
SIGNAL(SIG_UART_RECV) {
|
||||
ISR(USART_RXC_vect) {
|
||||
int diff;
|
||||
|
||||
char c;
|
||||
#ifdef UART_HOOK
|
||||
static volatile uint8_t hook_running=0;
|
||||
#endif
|
||||
#ifdef UART_LEDS
|
||||
PORTC ^= 0x02;
|
||||
#endif
|
||||
|
||||
c=UDR;
|
||||
#ifdef UART_XON_XOFF
|
||||
if (c==XON){
|
||||
txon=go;
|
||||
return;
|
||||
}
|
||||
if (c==XOFF){
|
||||
txon=nogo;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* buffer full? */
|
||||
diff = rxhead - rxtail;
|
||||
if ( diff < 0 ) diff += UART_RXBUFSIZE;
|
||||
if (diff < 0) diff += UART_RXBUFSIZE; /* diff is the amount of bytes in buffer */
|
||||
if (diff < UART_RXBUFSIZE -1) {
|
||||
// buffer NOT full
|
||||
*rxhead = UDR;
|
||||
if (++rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
|
||||
#ifdef UART_HOOK
|
||||
if(!hook_running && uart_hook){
|
||||
uint8_t t=c;
|
||||
hook_running = 1;
|
||||
sei(); /* reenable interrupts, avoid recursion!!! */
|
||||
do {
|
||||
uart_hook(t);
|
||||
} while(uart_getc_nb((char*)&t));
|
||||
hook_running = 0;
|
||||
} else {
|
||||
*rxhead = c;
|
||||
++rxhead;
|
||||
if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
|
||||
}
|
||||
#else
|
||||
*rxhead = c;
|
||||
++rxhead;
|
||||
if (rxhead == (rxbuf + UART_RXBUFSIZE))
|
||||
rxhead = rxbuf;
|
||||
#endif
|
||||
} else {
|
||||
UDR; //reads the buffer to clear the interrupt condition
|
||||
//reads the buffer to clear the interrupt condition
|
||||
}
|
||||
#ifdef UART_XON_XOFF
|
||||
if((diff > UART_XON_XOFF_THRESHOLD_1) && (rxon==go)){
|
||||
rxon=nogo;
|
||||
uart_insertc(XOFF);
|
||||
}
|
||||
if((diff < UART_XON_XOFF_THRESHOLD_2) && (rxon==nogo)){
|
||||
rxon=go;
|
||||
uart_insertc(XON);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // UART_INTERRUPT
|
||||
|
||||
|
||||
void uart_init(void) {
|
||||
void uart_init() {
|
||||
PORTD |= 0x01; //Pullup an RXD an
|
||||
|
||||
UCSRB |= (1<<TXEN); //UART TX einschalten
|
||||
#ifdef ATMEGA644
|
||||
UCSRA = 0;
|
||||
UCSRC = (3<<UCSZ0); //Asynchron 8N1
|
||||
#else
|
||||
UCSRA = 0;
|
||||
UCSRC |= (1<<URSEL)|(3<<UCSZ0); //Asynchron 8N1
|
||||
|
||||
#endif
|
||||
UCSRB |= ( 1 << RXEN ); //Uart RX einschalten
|
||||
|
||||
UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
|
||||
|
@ -81,11 +166,32 @@ void uart_init(void) {
|
|||
txhead = txtail = txbuf;
|
||||
|
||||
// activate rx IRQ
|
||||
UCSRB |= (1 << RXCIE);
|
||||
UCSRB |= _BV(RXCIE) | _BV(UDRIE);
|
||||
sei();
|
||||
// #ifdef ATMEGA644
|
||||
// UCSRB |= _BV(UDRIE);
|
||||
// #endif
|
||||
#endif // UART_INTERRUPT
|
||||
}
|
||||
|
||||
#ifdef UART_INTERRUPT
|
||||
#ifdef UART_XON_XOFF
|
||||
|
||||
void uart_insertc(char c){
|
||||
volatile int diff;
|
||||
do {
|
||||
diff = txhead - txtail;
|
||||
if ( diff < 0 ) diff += UART_TXBUFSIZE;
|
||||
} while ( diff >= UART_TXBUFSIZE -1 );
|
||||
|
||||
cli();
|
||||
if (--txtail == (txbuf-1)) txtail += UART_TXBUFSIZE;
|
||||
*txtail = c;
|
||||
|
||||
UCSRB |= (1 << UDRIE); /* enable data register empty IRQ */
|
||||
sei();
|
||||
}
|
||||
#endif /* UART_XON_XOFF */
|
||||
void uart_putc(char c) {
|
||||
volatile int diff;
|
||||
|
||||
|
@ -104,8 +210,13 @@ void uart_putc(char c) {
|
|||
}
|
||||
#else // WITHOUT INTERRUPT
|
||||
void uart_putc(char c) {
|
||||
while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
|
||||
UDR = c; /* schreibt das Zeichen x auf die Schnittstelle */
|
||||
while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
|
||||
;
|
||||
#ifdef UART_XON_XOFF
|
||||
while (txon==nogo) /* warte bis XON empfangen */
|
||||
;
|
||||
#endif
|
||||
UDR = c; /* schreibt das Zeichen x auf die Schnittstelle */
|
||||
}
|
||||
#endif // UART_INTERRUPT
|
||||
|
||||
|
@ -126,13 +237,13 @@ void uart_putstr_P(PGM_P str) {
|
|||
|
||||
void uart_hexdump(void* buf, int len)
|
||||
{
|
||||
unsigned char table[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
|
||||
unsigned char table[]={'0','1','2','3','4','5','6','7',
|
||||
'8','9','a','b','c','d','e','f'};
|
||||
while(len--){
|
||||
uart_putc(table[((*((char*)buf))>>4)&0xf]);
|
||||
uart_putc(table[(*((char*)buf))&0xf]);
|
||||
uart_putc(' ');
|
||||
buf=(char*)buf+1;
|
||||
buf=(uint8_t*)buf+1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,18 +253,28 @@ char uart_getc(void)
|
|||
{
|
||||
char val;
|
||||
|
||||
while(rxhead==rxtail) ;
|
||||
while(rxhead==rxtail)
|
||||
;
|
||||
|
||||
val = *rxtail;
|
||||
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
|
||||
++rxtail;
|
||||
if (rxtail == (rxbuf + UART_RXBUFSIZE))
|
||||
rxtail = rxbuf;
|
||||
|
||||
return val;
|
||||
}
|
||||
#else // WITHOUT INTERRUPT
|
||||
char uart_getc(void)
|
||||
{
|
||||
while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
|
||||
return UDR; // Zeichen aus UDR zurueckgeben
|
||||
char t;
|
||||
while (!(UCSRA & (1<<RXC)))
|
||||
; // warten bis Zeichen verfuegbar
|
||||
t=UDR;
|
||||
#ifdef UART_XON_XOFF
|
||||
if (t==XON) txon=go;
|
||||
if (t==XOFF) txon=nogo;
|
||||
#endif
|
||||
return t; // Zeichen aus UDR zurueckgeben
|
||||
}
|
||||
#endif // UART_INTERRUPT
|
||||
|
||||
|
@ -173,6 +294,10 @@ char uart_getc_nb(char *c)
|
|||
{
|
||||
if (UCSRA & (1<<RXC)) { // Zeichen verfuegbar
|
||||
*c = UDR;
|
||||
#ifdef UART_XON_XOFF
|
||||
if (*c==XON) txon=go;
|
||||
if (*c==XOFF) txon=nogo;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue