Commit from zer0 (2009-01-03 17:19 CET) ================ add micrb_cmd and bootloader
+ aversive_projects microb2009/microb_cmd/microbcmd.py 1.1 aversive_projects microb2009/tests/arm_test/.config 1.4 aversive_projects microb2009/tests/arm_test/Makefile 1.3 aversive_projects microb2009/tests/arm_test/commands.c 1.3 aversive_projects microb2009/tests/arm_test/main.c 1.3 aversive_projects microb2009/tests/arm_test/uart_config.h 1.2 + aversive_projects microb2009/tests/bootloader/Makefile 1.1 + aversive_projects microb2009/tests/bootloader/error_config.h 1.1 + aversive_projects microb2009/tests/bootloader/main.c 1.1 + aversive_projects microb2009/tests/bootloader/uart_config.h 1.1 ==================================================== aversive_projects/microb2009/microb_cmd/microbcmd.py (1.1) ==================================================== @@ -0,0 +1,317 @@ +#! /usr/bin/env python + +import os,sys,termios,atexit +import serial +from select import select +import cmd +#from pylab import * +import shlex +import time + +import warnings +warnings.filterwarnings("ignore","tempnam",RuntimeWarning, __name__) + +import logging +log = logging.getLogger("MicrobShell") +_handler = logging.StreamHandler() +_handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) +log.addHandler(_handler) +log.setLevel(1) + +SPM_PAGE_SIZE = 256 + +def crc_ccitt_update (crc, data): + """crc argument is the previous value of 16 bits crc (the initial + value is 0xffff). 'data' is the 8 bits value added to crc. The + function returns the new crc value.""" + + data ^= (crc & 0xff) + data ^= (data << 4) + data &= 0xff + + ret = (data << 8) & 0xffff + ret |= ((crc >> 8) & 0xff) + ret ^= ((data >> 4) & 0xff) + ret ^= ((data << 3) & 0xffff) + return ret + +def prog_page(ser, addr, buf): + """program a page from buf at addr""" + i = 0 + crc = 0xffff + + ser.flushInput() + ser.write('p') + s = ser.readline() + if not s.endswith("addr?\r\n"): + print "failed (don't match addr)" + return -1 + ser.write("%x\n"%addr) + s = ser.readline() + if not s.startswith("addr ok"): + print "failed" + return -1 + while i < SPM_PAGE_SIZE: + if i >= len(buf): + c = '\xff' + else: + c = buf[i] + ser.write(c) + i += 1 + crc = crc_ccitt_update(crc, ord(c)) + sys.stdout.write(".") + sys.stdout.flush() + avr_crc = int(ser.readline()[0:4], 16) + if crc != avr_crc: + print "failed: bad crc" + ser.write('n') + return -1 + ser.write('y') + s = ser.readline() + if not s.startswith("OK"): + print "failed" + return -1 + return 0 + +def check_crc(ser, addr, buf): + """Process the crc of buf, ask for a crc of the flash, and check + that value is correct""" + crc = 0xffff + size = len(buf) - addr + if size <= 0: + return + ser.flushInput() + ser.write('c') + s = ser.readline() + if not s.startswith("addr?"): + print "failed" + return -1 + ser.write("%x\n"%addr) + s = ser.readline() + if not s.startswith("size?"): + print "failed" + return -1 + ser.write("%x\n"%size) + i = addr + while addr < addr + size: + crc = crc_ccitt_update(crc, buf[i]) + avr_crc = int(ser.readline()[0:4], 16) + if crc != avr_crc: + print "failed: bad crc" + return -1 + return 0 + +class SerialLogger: + def __init__(self, ser, filein, fileout=None): + self.ser = ser + self.filein = filein + self.fin = open(filein, "a", 0) + if fileout: + self.fileout = fileout + self.fout = open(fileout, "a", 0) + else: + self.fileout = filein + self.fout = self.fin + def fileno(self): + return self.ser.fileno() + def read(self, *args): + res = self.ser.read(*args) + self.fin.write(res) + return res + def write(self, s): + self.fout.write(s) + self.ser.write(s) + + + +class Interp(cmd.Cmd): + prompt = "Microb> " + def __init__(self, tty, baudrate=57600): + cmd.Cmd.__init__(self) + self.ser = serial.Serial(tty,baudrate=baudrate) + self.escape = "\x01" # C-a + self.quitraw = "\x02" # C-b + self.serial_logging = False + self.default_in_log_file = "/tmp/microb.in.log" + self.default_out_log_file = "/tmp/microb.out.log" + + def do_quit(self, args): + return True + + def do_log(self, args): + """Activate serial logs. + log <filename> logs input and output to <filename> + log <filein> <fileout> logs input to <filein> and output to <fileout> + log logs to /tmp/microb.log or the last used file""" + + if self.serial_logging: + log.error("Already logging to %s and %s" % (self.ser.filein, + self.ser.fileout)) + else: + self.serial_logging = True + files = [os.path.expanduser(x) for x in args.split()] + if len(files) == 0: + files = [self.default_in_log_file, self.default_out_log_file] + elif len(files) == 1: + self.default_in_log_file = files[0] + self.default_out_log_file = None + elif len(files) == 2: + self.default_in_log_file = files[0] + self.default_out_log_file = files[1] + else: + print "Can't parse arguments" + + self.ser = SerialLogger(self.ser, *files) + log.info("Starting serial logging to %s and %s" % (self.ser.filein, + self.ser.fileout)) + + + def do_unlog(self, args): + if self.serial_logging: + log.info("Stopping serial logging to %s and %s" % (self.ser.filein, + self.ser.fileout)) + self.ser = self.ser.ser + self.serial_logging = False + else: + log.error("No log to stop") + + + def do_raw(self, args): + "Switch to RAW mode" + stdin = os.open("/dev/stdin",os.O_RDONLY) + stdout = os.open("/dev/stdout",os.O_WRONLY) + + stdin_termios = termios.tcgetattr(stdin) + raw_termios = stdin_termios[:] + + try: + log.info("Switching to RAW mode") + + # iflag + raw_termios[0] &= ~(termios.IGNBRK | termios.BRKINT | + termios.PARMRK | termios.ISTRIP | + termios.INLCR | termios.IGNCR | + termios.ICRNL | termios.IXON) + # oflag + raw_termios[1] &= ~termios.OPOST; + # cflag + raw_termios[2] &= ~(termios.CSIZE | termios.PARENB); + raw_termios[2] |= termios.CS8; + # lflag + raw_termios[3] &= ~(termios.ECHO | termios.ECHONL | + termios.ICANON | termios.ISIG | + termios.IEXTEN); + + termios.tcsetattr(stdin, termios.TCSADRAIN, raw_termios) + + mode = "normal" + while True: + ins,outs,errs=select([stdin,self.ser],[],[]) + for x in ins: + if x == stdin: + c = os.read(stdin,1) + if mode == "escape": + mode =="normal" + if c == self.escape: + self.ser.write(self.escape) + elif c == self.quitraw: + return + else: + self.ser.write(self.escape) + self.ser.write(c) + else: + if c == self.escape: + mode = "escape" + else: + self.ser.write(c) + elif x == self.ser: + os.write(stdout,self.ser.read()) + finally: + termios.tcsetattr(stdin, termios.TCSADRAIN, stdin_termios) + log.info("Back to normal mode") + + + def update_graph(self, val): + freq = self.sfreq.val + self.theta_max = freq*pi*2.0 + self.theta = arange(0.0, self.theta_max, self.theta_max/len(self.r)) + self.theta = self.theta[:len(self.r)] + + self.myplot.set_xdata(self.theta) + draw() + + def do_graph(self, args): + self.ser.write("sample start\n") + time.sleep(2) + self.ser.write("sample dump\n") + vals = [] + while True: + l = self.ser.readline() + if l[0] in ['s', 'c', 'a']: + continue + if l[0] in ['e']: + break + tokens = [x for x in shlex.shlex(l)] + v = int(tokens[0]) + #v = min(v, 150) + vals.append(v) + vals.reverse() + + subplot(111, polar = True) + self.r = vals + #theta_max = 4.8*2.3*pi + self.theta_max = 5*pi + self.theta = arange(0.0, self.theta_max, self.theta_max/len(self.r)) + + self.myplot, = plot(self.theta, self.r) + + #slide bar + axfreq = axes([0.25, 0.1, 0.65, 0.03]) + self.sfreq = Slider(axfreq, "Freq", 1, 10, valinit = 4.8) + self.sfreq.on_changed(self.update_graph) + + show() + + def do_bootloader(self, args): + f = open(args) + buf = f.read() + addr = 0 + while addr < len(buf): + if prog_page(self.ser, addr, buf[addr:]) != 0: + return + addr += SPM_PAGE_SIZE + if check_crc(self.ser, addr, buf): + return + print "Done." + + def do_toto(self, args): + print repr(args) + +if __name__ == "__main__": + try: + import readline,atexit + except ImportError: + pass + else: + histfile = os.path.join(os.environ["HOME"], ".microb_history") + atexit.register(readline.write_history_file, histfile) + try: + readline.read_history_file(histfile) + except IOError: + pass + + device = "/dev/ttyS0" + if len(sys.argv) > 1: + device = sys.argv[1] + interp = Interp(device) + while 1: + try: + interp.cmdloop() + except KeyboardInterrupt: + print + except Exception,e: + l = str(e).strip() + if l: + log.exception("%s" % l.splitlines()[-1]) + continue + break =================================================== aversive_projects/microb2009/tests/arm_test/.config (1.3 -> 1.4) =================================================== @@ -48,6 +48,8 @@ # CONFIG_MCU_AT90CAN128 is not set # CONFIG_MCU_AT94K is not set # CONFIG_MCU_AT90S1200 is not set +# CONFIG_MCU_ATMEGA2560 is not set +# CONFIG_MCU_ATMEGA256 is not set CONFIG_QUARTZ=16000000 # @@ -63,9 +65,9 @@ # CONFIG_MINIMAL_PRINTF is not set CONFIG_STANDARD_PRINTF=y # CONFIG_ADVANCED_PRINTF is not set -CONFIG_FORMAT_IHEX=y +# CONFIG_FORMAT_IHEX is not set # CONFIG_FORMAT_SREC is not set -# CONFIG_FORMAT_BINARY is not set +CONFIG_FORMAT_BINARY=y # # Base modules @@ -240,7 +242,7 @@ # CONFIG_AVRDUDE_PROG_BSD is not set # CONFIG_AVRDUDE_PROG_DAPA is not set # CONFIG_AVRDUDE_PROG_JTAG1 is not set -CONFIG_AVRDUDE_PORT="/dev/.static/dev/parport0" +CONFIG_AVRDUDE_PORT="/dev/parport0" # # Avarice ==================================================== aversive_projects/microb2009/tests/arm_test/Makefile (1.2 -> 1.3) ==================================================== @@ -4,7 +4,7 @@ AVERSIVE_DIR = ../../../.. # VALUE, absolute or relative path : example ../.. # -#CFLAGS += -Werror +CFLAGS += -Werror # List C source files here. (C dependencies are automatically generated.) SRC = commands.c $(TARGET).c @@ -22,3 +22,8 @@ -include .aversive_conf include $(AVERSIVE_DIR)/mk/aversive_project.mk + +program_noerase: $(TARGET).$(FORMAT_EXTENSION) $(TARGET).eep + echo $(AVRDUDE) -D -V $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) ;\ + $(AVRDUDE) -D -V $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) ;\ + ====================================================== aversive_projects/microb2009/tests/arm_test/commands.c (1.2 -> 1.3) ====================================================== @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: commands.c,v 1.2 2008-12-27 16:29:08 zer0 Exp $ + * Revision : $Id: commands.c,v 1.3 2009-01-03 16:19:30 zer0 Exp $ * * Olivier MATZ <z...@droids-corp.org> */ @@ -151,6 +151,53 @@ }; /**********************************************************/ +/* Bootloader */ + +/* this structure is filled when cmd_bootloader is parsed successfully */ +struct cmd_bootloader_result { + fixed_string_t arg0; +}; + +/* function called when cmd_bootloader is parsed successfully */ +static void cmd_bootloader_parsed(void * parsed_result, void * data) +{ +#define BOOTLOADER_ADDR 0x1e000 + if (pgm_read_byte_far(BOOTLOADER_ADDR) == 0xff) { + printf_P(PSTR("Bootloader is not present\r\n")); + return; + } + cli(); + /* ... very specific :( */ + TIMSK = 0; + ETIMSK = 0; + EIMSK = 0; + UCSR0B = 0; + UCSR1B = 0; + SPCR = 0; + TWCR = 0; + ACSR = 0; + ADCSRA = 0; + + __asm__ __volatile__ ("ldi r30,0x00\n"); + __asm__ __volatile__ ("ldi r31,0xf0\n"); + __asm__ __volatile__ ("ijmp\n"); +} + +prog_char str_bootloader_arg0[] = "bootloader"; +parse_pgm_token_string_t cmd_bootloader_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_bootloader_result, arg0, str_bootloader_arg0); + +prog_char help_bootloader[] = "Bootloader the board"; +parse_pgm_inst_t cmd_bootloader = { + .f = cmd_bootloader_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_bootloader, + .tokens = { /* token list, NULL terminated */ + (prog_void *)&cmd_bootloader_arg0, + NULL, + }, +}; + +/**********************************************************/ /* Ax12_Stress */ /* this structure is filled when cmd_ax12_stress is parsed successfully */ @@ -197,50 +244,48 @@ fixed_string_t arg0; }; -#define SHOULDER_AX12 4 #define ELBOW_AX12 1 #define WRIST_AX12 2 -void arm_goto(uint16_t shoulder, uint16_t elbow, uint16_t wrist) +void arm_goto(int32_t shoulder, uint16_t elbow, uint16_t wrist) { uint8_t err; - err = AX12_write_int(&ax12, SHOULDER_AX12, AA_GOAL_POSITION_L, shoulder); - if (!err) - AX12_write_int(&ax12, ELBOW_AX12, AA_GOAL_POSITION_L, elbow); + cs_set_consign(&arm.cs_mot, shoulder); + err = AX12_write_int(&ax12, ELBOW_AX12, AA_GOAL_POSITION_L, elbow); if (!err) AX12_write_int(&ax12, WRIST_AX12, AA_GOAL_POSITION_L, wrist); if (err) printf_P(PSTR("AX12 error %x !\r\n"), err); } -#define arm_take_low_v1() arm_goto(530, 295, 432) -#define arm_take_high_v1() arm_goto(570, 267, 455) -#define arm_take_low_v2() arm_goto(510, 320, 69) -#define arm_take_high_v2() arm_goto(570, 267, 90) -#define arm_intermediate() arm_goto(850, 190, 122) -#define arm_intermediate2() arm_goto(800, 400, 300) -#define arm_up() arm_goto(710, 585, 464) +#define arm_take_high_v1() arm_goto(-18700, 204, 455) +#define arm_take_low_v1() arm_goto(-11000, 273, 480) +#define arm_take_high_v2() arm_goto(-18700, 204, 154) +#define arm_take_low_v2() arm_goto(-11000, 273, 139) +#define arm_intermediate() arm_goto(-35700, 297, 385) +#define arm_drop_v2() arm_goto(-16810, 667, 564) +#define arm_drop_v1() arm_goto(-16810, 667, 904) /* function called when cmd_test is parsed successfully */ static void cmd_test_parsed(void * parsed_result, void * data) { uint8_t i=0; - int8_t err; +/* int8_t err; */ /* Set some AX12 parameters */ - err = AX12_write_int(&ax12,0xFE,AA_TORQUE_ENABLE,0x1); - if (!err) - AX12_write_int(&ax12,0xFE,AA_PUNCH_L,0x20); - if (!err) - AX12_write_int(&ax12,0xFE,AA_TORQUE_LIMIT_L,0x3FF); - if (!err) - AX12_write_int(&ax12,0xFE,AA_MOVING_SPEED_L,0x3FF); - if (!err) - AX12_write_byte(&ax12,0xFE,AA_ALARM_LED,0xEF); - if (err) { - printf_P(PSTR("AX12 error %x !\r\n"), err); - return; - } +/* err = AX12_write_int(&ax12,0xFE,AA_TORQUE_ENABLE,0x1); */ +/* if (!err) */ +/* AX12_write_int(&ax12,0xFE,AA_PUNCH_L,0x20); */ +/* if (!err) */ +/* AX12_write_int(&ax12,0xFE,AA_TORQUE_LIMIT_L,0x3FF); */ +/* if (!err) */ +/* AX12_write_int(&ax12,0xFE,AA_MOVING_SPEED_L,0x3FF); */ +/* if (!err) */ +/* AX12_write_byte(&ax12,0xFE,AA_ALARM_LED,0xEF); */ +/* if (err) { */ +/* printf_P(PSTR("AX12 error %x !\r\n"), err); */ +/* return; */ +/* } */ for (i=0; i<1; i++) { arm_take_high_v1(); @@ -257,10 +302,13 @@ arm_take_high_v2(); wait_ms(500); arm_intermediate(); - wait_ms(250); - arm_intermediate2(); - wait_ms(250); - arm_up(); + wait_ms(500); +/* arm_intermediate2(); */ +/* wait_ms(250); */ + arm_drop_v2(); + wait_ms(500); + pwm_set((void *)PWM1B_NUM, -4095); + arm_drop_v1(); wait_ms(500); pwm_set((void *)PWM1B_NUM, 0); wait_ms(500); @@ -297,6 +345,7 @@ struct cmd_baudrate_result *res = parsed_result; struct uart_config c; + printf_P(PSTR("%d %d\r\n"), UBRR1H, UBRR1L); uart_getconf(1, &c); c.baudrate = res->arg1; uart_setconf(1, &c); @@ -324,7 +373,7 @@ /* this structure is filled when cmd_test is parsed successfully */ struct cmd_arm_goto_result { fixed_string_t arg0; - uint16_t arg1; + int32_t arg1; uint16_t arg2; uint16_t arg3; }; @@ -338,7 +387,7 @@ prog_char str_arm_goto_arg0[] = "arm_goto"; parse_pgm_token_string_t cmd_arm_goto_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_arm_goto_result, arg0, str_arm_goto_arg0); -parse_pgm_token_num_t cmd_arm_goto_arg1 = TOKEN_NUM_INITIALIZER(struct cmd_arm_goto_result, arg1, UINT16); +parse_pgm_token_num_t cmd_arm_goto_arg1 = TOKEN_NUM_INITIALIZER(struct cmd_arm_goto_result, arg1, INT32); parse_pgm_token_num_t cmd_arm_goto_arg2 = TOKEN_NUM_INITIALIZER(struct cmd_arm_goto_result, arg2, UINT16); parse_pgm_token_num_t cmd_arm_goto_arg3 = TOKEN_NUM_INITIALIZER(struct cmd_arm_goto_result, arg3, UINT16); @@ -357,6 +406,41 @@ }; /**********************************************************/ + +/* this structure is filled when cmd_test is parsed successfully */ +struct cmd_arm_capture_result { + fixed_string_t arg0; +}; + +/* function called when cmd_arm_capture is parsed successfully */ +static void cmd_arm_capture_parsed(void * parsed_result, void * data) +{ + uint16_t elbow, wrist; + int32_t shoulder; + uint8_t ret = 0; + + ret |= AX12_read_int(&ax12, ELBOW_AX12, AA_PRESENT_POSITION_L, &elbow); + ret |= AX12_read_int(&ax12, WRIST_AX12, AA_PRESENT_POSITION_L, &wrist); + shoulder = encoders_microb_get_value((void *)ARM_ENC); + if (ret) + printf_P(PSTR("AX12 error %.2x!\r\n"), ret); + printf_P(PSTR("%ld %d %d\r\n"), shoulder, elbow, wrist); +} + +prog_char str_arm_capture_arg0[] = "arm_capture"; +parse_pgm_token_string_t cmd_arm_capture_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_arm_capture_result, arg0, str_arm_capture_arg0); + +prog_char help_arm_capture[] = "Change arm position (shoulder, elbow, wrist)"; +parse_pgm_inst_t cmd_arm_capture = { + .f = cmd_arm_capture_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_arm_capture, + .tokens = { /* token list, NULL terminated */ + (prog_void *)&cmd_arm_capture_arg0, + NULL, + }, +}; +/**********************************************************/ /* Uint16 */ @@ -448,38 +532,18 @@ uint8_t val; }; -extern char testxx[32]; -extern volatile uint8_t testyy; - /* function called when cmd_uint8_read is parsed successfully */ static void cmd_uint8_read_parsed(void * parsed_result, void * data) { struct cmd_uint8_result *res = parsed_result; uint8_t ret; uint8_t val; -#if 0 - int c; - int i; -#endif uint8_t addr = addr_from_string(res->arg1); ret = AX12_read_byte(&ax12, res->num, addr, &val); if (ret) printf_P(PSTR("AX12 error %.2x!\r\n"), ret); printf_P(PSTR("%s: %d [0x%.2x]\r\n"), res->arg1, val, val); -#if 0 - while (1) { - c = uart_recv_nowait(1); - if (c == -1) - break; - printf_P(PSTR("%.2x "), c&0xff); - } - printf_P(PSTR("\r\n")); - for (i=0; i<testyy; i++) { - printf_P(PSTR("%.2x "), testxx[i] & 0xff); - } - printf_P(PSTR("\r\n")); -#endif } prog_char str_uint8_arg0[] = "read"; @@ -833,6 +897,11 @@ if (!strcmp_P(res->arg1, PSTR("cs"))) { if (!strcmp_P(res->arg2, PSTR("on"))) { pwm_set(ARM_MOT_PWM, 0); + printf_P(PSTR("ax12 will start\r\n")); + while(uart_recv_nowait(0) == -1); + AX12_write_int(&ax12,0xFE,AA_TORQUE_ENABLE,0x1); + AX12_write_int(&ax12, ELBOW_AX12, AA_GOAL_POSITION_L, 660); + AX12_write_int(&ax12, WRIST_AX12, AA_GOAL_POSITION_L, 613); printf_P(PSTR("Set the arm to 0\r\n")); while(uart_recv_nowait(0) == -1); encoders_microb_set_value(ARM_ENC, 0); @@ -1072,10 +1141,12 @@ /* in progmem */ parse_pgm_ctx_t main_ctx[] = { (parse_pgm_inst_t *)&cmd_reset, + (parse_pgm_inst_t *)&cmd_bootloader, (parse_pgm_inst_t *)&cmd_ax12_stress, (parse_pgm_inst_t *)&cmd_test, (parse_pgm_inst_t *)&cmd_baudrate, (parse_pgm_inst_t *)&cmd_arm_goto, + (parse_pgm_inst_t *)&cmd_arm_capture, (parse_pgm_inst_t *)&cmd_sample, (parse_pgm_inst_t *)&cmd_uint16_read, (parse_pgm_inst_t *)&cmd_uint16_write, ================================================== aversive_projects/microb2009/tests/arm_test/main.c (1.2 -> 1.3) ================================================== @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: main.c,v 1.2 2008-12-27 16:29:08 zer0 Exp $ + * Revision : $Id: main.c,v 1.3 2009-01-03 16:19:30 zer0 Exp $ * */ @@ -175,6 +175,7 @@ if (state == AX12_STATE_WRITE) { IRQ_LOCK(flags); ax12_nsent=0; + while (uart_recv_nowait(1) != -1); UCSR1B |= (1<<TXEN); ax12_state = AX12_STATE_WRITE; IRQ_UNLOCK(flags); @@ -352,6 +353,8 @@ sei(); + printf_P(PSTR("Coucou\r\n")); + /* set status return level to 2 and torque to 0 */ AX12_write_int(&ax12,0xFE, AA_TORQUE_ENABLE, 0x00); AX12_write_byte(&ax12, 0xFE, AA_STATUS_RETURN_LEVEL, 2); ========================================================= aversive_projects/microb2009/tests/arm_test/uart_config.h (1.1 -> 1.2) ========================================================= @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: uart_config.h,v 1.1 2008-12-26 13:08:29 zer0 Exp $ + * Revision : $Id: uart_config.h,v 1.2 2009-01-03 16:19:30 zer0 Exp $ * */ @@ -73,7 +73,7 @@ /* enable uart1 interrupts if == 1, disable if == 0 */ #define UART1_INTERRUPT_ENABLED 1 -#define UART1_BAUDRATE 250000 +#define UART1_BAUDRATE 115200 //#define UART1_BAUDRATE 1000000 @@ -96,8 +96,8 @@ //#define UART1_PARITY UART_PARTITY_ODD //#define UART1_PARITY UART_PARTITY_EVEN -#define UART1_STOP_BIT UART_STOP_BITS_1 -//#define UART1_STOP_BIT UART_STOP_BITS_2 +//#define UART1_STOP_BIT UART_STOP_BITS_1 +#define UART1_STOP_BIT UART_STOP_BITS_2 #endif ====================================================== aversive_projects/microb2009/tests/bootloader/Makefile (1.1) ====================================================== @@ -0,0 +1,31 @@ +TARGET = main + +# repertoire des modules +AVERSIVE_DIR = ../../../.. +# VALUE, absolute or relative path : example ../.. # + +CFLAGS += -Werror +# address is 0xf000 (in words) +LDFLAGS += -Wl,--section-start=.text=1e000 + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +ASRC = + +######################################## + +-include .aversive_conf +include $(AVERSIVE_DIR)/mk/aversive_project.mk + +program_noerase: $(TARGET).$(FORMAT_EXTENSION) $(TARGET).eep + echo $(AVRDUDE) -D -V $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) ;\ + $(AVRDUDE) -D -V $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) ;\ + ============================================================ aversive_projects/microb2009/tests/bootloader/error_config.h (1.1) ============================================================ @@ -0,0 +1,31 @@ +/* + * Copyright Droids Corporation, Microb Technology, Eirbot (2005) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Revision : $Id: error_config.h,v 1.1 2009-01-03 16:19:30 zer0 Exp $ + * + */ + +#ifndef _ERROR_CONFIG_ +#define _ERROR_CONFIG_ + +/** enable the dump of the comment */ +#define ERROR_DUMP_TEXTLOG + +/** enable the dump of filename and line number */ +#define ERROR_DUMP_FILE_LINE + +#endif ==================================================== aversive_projects/microb2009/tests/bootloader/main.c (1.1) ==================================================== @@ -0,0 +1,210 @@ +/* + * Copyright Droids Corporation + * Olivier Matz <z...@droids-corp.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Revision : $Id: main.c,v 1.1 2009-01-03 16:19:30 zer0 Exp $ + * + */ + +/* + * A simple bootloader example. + */ + +#include <aversive.h> +#include <aversive/wait.h> +#include <aversive/pgmspace.h> +#include <uart.h> + +#include <stdlib.h> +#include <string.h> +#include <util/crc16.h> +#include <avr/boot.h> + +#define NOECHO + +#ifdef NOECHO +#define echo(c) do {} while(0) +#else +#define echo(c) uart_send(0, c) +#endif + +static void bootloader_puts(const char *buf) +{ + while (*buf) + uart_send(0, *(buf++)); +} + +static uint32_t bootloader_query_hex(void) +{ + char buf[8]; + uint8_t i=0; + int c; + + memset(buf, 0, sizeof(buf)); + while (1) { + while ((c=uart_recv_nowait(0)) == -1); + if (i >= sizeof(buf) - 1) + continue; + if (c == '\n' || c == '\r') { + echo('\r'); + echo('\n'); + break; + } + echo(c); + buf[i++] = c; + } + return strtol(buf, NULL, 16); +} + +static void launch_app(void) +{ + bootloader_puts("BOOT\r\n"); + wait_ms(500); + MCUCR = (1 << IVCE); + MCUCR = (0 << IVSEL); + reset(); +} + +static void disp_digit(uint8_t x) +{ + if (x < 10) + uart_send(0, '0' + x); + else + uart_send(0, 'a' - 10 + x); +} + +static void disp_hex8(uint8_t x) +{ + disp_digit(x>>4); + disp_digit(x&0xf); +} + +static void disp_hex16(uint16_t x) +{ + disp_hex8(x>>8); + disp_hex8(x); +} + +static void crc_app(void) +{ + uint32_t start_addr, addr, size; + uint8_t c; + uint16_t crc = 0xffff; + + bootloader_puts("start addr?\r\n"); + start_addr = bootloader_query_hex(); + if (start_addr > FLASHEND) + goto fail; + bootloader_puts("size?\r\n"); + size = bootloader_query_hex(); + if (start_addr + size > FLASHEND) + goto fail; + for (addr=start_addr; addr<start_addr+size; addr++) { + c = pgm_read_byte_far(addr); + crc = _crc_ccitt_update(crc, c); + } + disp_hex16(crc); + return; + fail: + bootloader_puts("KO"); +} + +static void prog_page(void) +{ + int c; + uint32_t addr; + uint16_t i; + uint16_t crc = 0xffff; + uint8_t buf[SPM_PAGESIZE]; + +#define SPM_PAGEMASK ((uint32_t)SPM_PAGESIZE-1) + bootloader_puts("addr?\r\n"); + addr = bootloader_query_hex(); + if (addr > FLASHEND) + goto fail; + /* start_addr must be page aligned */ + if (addr & SPM_PAGEMASK) + goto fail; + + bootloader_puts("addr ok\r\n"); + + /* data is received like the .bin format (which is already in + * little endian) */ + for (i=0; i<SPM_PAGESIZE; i++) { + while ((c=uart_recv_nowait(0)) == -1); + crc = _crc_ccitt_update(crc, c); + buf[i] = c; + } + disp_hex16(crc); + bootloader_puts(" (y to valid)\r\n"); + while ((c=uart_recv_nowait(0)) == -1); + if (c != 'y') + goto fail; + + /* erase page */ + eeprom_busy_wait(); + boot_page_erase(addr); + boot_spm_busy_wait(); + + /* Set up little-endian word and fill tmp buf. */ + for (i=0; i<SPM_PAGESIZE; i+=2) { + uint16_t w = buf[i] + ((uint16_t)(buf[i+1]) << 8); + boot_page_fill(addr + i, w); + } + + boot_page_write(addr); + boot_spm_busy_wait(); + + /* Reenable RWW-section again. We need this if we want to jump + * back to the application after bootloading. */ + boot_rww_enable(); + + bootloader_puts("OK"); + return; + fail: + bootloader_puts("KO"); +} + +int main(void) +{ + int c; + + uart_init(); + + /* move interrupt vector in bootloader section */ + MCUCR = (1 << IVCE); + MCUCR = (1 << IVSEL); + + sei(); + + bootloader_puts("\r\n"); + while (1) { + bootloader_puts("cmd>"); + while ((c=uart_recv_nowait(0)) == -1); + if (c == 'x') + launch_app(); + else if (c == 'c') + crc_app(); + else if (c == 'p') + prog_page(); + else + bootloader_puts("bad cmd (p:prog_page c:crc x:exec)"); + bootloader_puts("\r\n"); + } + + return 0; +} =========================================================== aversive_projects/microb2009/tests/bootloader/uart_config.h (1.1) =========================================================== @@ -0,0 +1,63 @@ +/* + * Copyright Droids Corporation, Microb Technology, Eirbot (2005) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Revision : $Id: uart_config.h,v 1.1 2009-01-03 16:19:30 zer0 Exp $ + * + */ + +/* Droids-corp 2004 - Zer0 + * config for uart module + */ + +#ifndef UART_CONFIG_H +#define UART_CONFIG_H + +/* compile uart0 fonctions, undefine it to pass compilation */ +#define UART0_COMPILE + +/* enable uart0 if == 1, disable if == 0 */ +#define UART0_ENABLED 1 + +/* enable uart0 interrupts if == 1, disable if == 0 */ +#define UART0_INTERRUPT_ENABLED 1 + +#define UART0_BAUDRATE 57600 + +/* + * if you enable this, the maximum baudrate you can reach is + * higher, but the precision is lower. + */ +#define UART0_USE_DOUBLE_SPEED 0 +//#define UART0_USE_DOUBLE_SPEED 1 + +#define UART0_RX_FIFO_SIZE 64 +#define UART0_TX_FIFO_SIZE 16 +//#define UART0_NBITS 5 +//#define UART0_NBITS 6 +//#define UART0_NBITS 7 +#define UART0_NBITS 8 +//#define UART0_NBITS 9 + +#define UART0_PARITY UART_PARTITY_NONE +//#define UART0_PARITY UART_PARTITY_ODD +//#define UART0_PARITY UART_PARTITY_EVEN + +#define UART0_STOP_BIT UART_STOP_BITS_1 +//#define UART0_STOP_BIT UART_STOP_BITS_2 + +#endif + Commit from zer0 on branch b_zer0 (2009-01-03 17:22 CET) ================================= add atmega2560 in config aversive config/config.in 1.42.4.22 ========================= aversive/config/config.in (1.42.4.21 -> 1.42.4.22) ========================= @@ -50,6 +50,8 @@ AT90can128 CONFIG_MCU_AT90CAN128 \ AT94k CONFIG_MCU_AT94K \ AT90s1200 CONFIG_MCU_AT90S1200 \ + ATmega2560 CONFIG_MCU_ATMEGA2560 \ + ATmega256 CONFIG_MCU_ATMEGA256 \ " ATmega128 int 'Quartz Frequency (Hz)' CONFIG_QUARTZ '12000000' Commit from zer0 on branch b_zer0 (2009-01-03 17:24 CET) ================================= move 'volatile' attribute in the structure to avoid a warning aversive modules/base/cirbuf/cirbuf.h 1.1.2.5 aversive modules/base/scheduler/scheduler_interrupt.c 1.1.2.8 aversive modules/comm/uart/uart.c 1.33.4.6 aversive modules/comm/uart/uart_private.h 1.1.2.5 aversive modules/comm/uart/uart_setconf.c 1.1.2.3 ===================================== aversive/modules/base/cirbuf/cirbuf.h (1.1.2.4 -> 1.1.2.5) ===================================== @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: cirbuf.h,v 1.1.2.4 2008-12-27 16:29:07 zer0 Exp $ + * Revision : $Id: cirbuf.h,v 1.1.2.5 2009-01-03 16:24:50 zer0 Exp $ * * */ @@ -48,11 +48,11 @@ * This structure is the header of a cirbuf type. */ struct cirbuf { - cirbuf_uint maxlen; /**< total len of the fifo (number of elements) */ - cirbuf_uint start; /**< indice of the first elt */ - cirbuf_uint end; /**< indice of the last elt */ - cirbuf_uint len; /**< current len of fifo */ - char * buf; + cirbuf_uint maxlen; /**< total len of the fifo (number of elements) */ + volatile cirbuf_uint start; /**< indice of the first elt */ + volatile cirbuf_uint end; /**< indice of the last elt */ + volatile cirbuf_uint len; /**< current len of fifo */ + char *buf; }; /* #define CIRBUF_DEBUG */ ===================================================== aversive/modules/base/scheduler/scheduler_interrupt.c (1.1.2.7 -> 1.1.2.8) ===================================================== @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: scheduler_interrupt.c,v 1.1.2.7 2008-12-27 16:29:07 zer0 Exp $ + * Revision : $Id: scheduler_interrupt.c,v 1.1.2.8 2009-01-03 16:24:50 zer0 Exp $ * */ @@ -66,6 +66,7 @@ /* maximize the number of imbrications */ if (nb_stacking >= SCHEDULER_NB_STACKING_MAX) return; + nb_stacking ++; sei(); ================================= aversive/modules/comm/uart/uart.c (1.33.4.5 -> 1.33.4.6) ================================= @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: uart.c,v 1.33.4.5 2008-12-27 16:50:01 zer0 Exp $ + * Revision : $Id: uart.c,v 1.33.4.6 2009-01-03 16:24:50 zer0 Exp $ * */ @@ -28,8 +28,8 @@ #include <uart_defs.h> #include <uart_private.h> -volatile struct cirbuf g_tx_fifo[UART_HW_NUM]; -volatile struct cirbuf g_rx_fifo[UART_HW_NUM]; +struct cirbuf g_tx_fifo[UART_HW_NUM]; +struct cirbuf g_rx_fifo[UART_HW_NUM]; /* global vars are initialized to 0 (NULL) */ event *rx_event[UART_HW_NUM]; ========================================= aversive/modules/comm/uart/uart_private.h (1.1.2.4 -> 1.1.2.5) ========================================= @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: uart_private.h,v 1.1.2.4 2008-12-27 16:50:49 zer0 Exp $ + * Revision : $Id: uart_private.h,v 1.1.2.5 2009-01-03 16:24:50 zer0 Exp $ * */ @@ -48,10 +48,10 @@ typedef void (event_9bits)(int); /** The emission fifo of uart */ -extern volatile struct cirbuf g_tx_fifo[UART_HW_NUM]; +extern struct cirbuf g_tx_fifo[UART_HW_NUM]; /** The reception fifo of uart */ -extern volatile struct cirbuf g_rx_fifo[UART_HW_NUM]; +extern struct cirbuf g_rx_fifo[UART_HW_NUM]; extern event *rx_event[UART_HW_NUM]; extern event *tx_event[UART_HW_NUM]; ========================================= aversive/modules/comm/uart/uart_setconf.c (1.1.2.2 -> 1.1.2.3) ========================================= @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: uart_setconf.c,v 1.1.2.2 2008-12-27 16:50:01 zer0 Exp $ + * Revision : $Id: uart_setconf.c,v 1.1.2.3 2009-01-03 16:24:50 zer0 Exp $ * */ @@ -27,20 +27,20 @@ /** The emission fifo of uart */ #ifdef UART0_COMPILE -volatile char g_tx0_buf[UART0_TX_FIFO_SIZE]; -volatile char g_rx0_buf[UART0_RX_FIFO_SIZE]; +char g_tx0_buf[UART0_TX_FIFO_SIZE]; +char g_rx0_buf[UART0_RX_FIFO_SIZE]; #endif #ifdef UART1_COMPILE -volatile char g_tx1_buf[UART1_TX_FIFO_SIZE]; -volatile char g_rx1_buf[UART1_RX_FIFO_SIZE]; +char g_tx1_buf[UART1_TX_FIFO_SIZE]; +char g_rx1_buf[UART1_RX_FIFO_SIZE]; #endif #ifdef UART2_COMPILE -volatile char g_tx2_buf[UART2_TX_FIFO_SIZE]; -volatile char g_rx2_buf[UART2_RX_FIFO_SIZE]; +char g_tx2_buf[UART2_TX_FIFO_SIZE]; +char g_rx2_buf[UART2_RX_FIFO_SIZE]; #endif #ifdef UART3_COMPILE -volatile char g_tx3_buf[UART3_TX_FIFO_SIZE]; -volatile char g_rx3_buf[UART3_RX_FIFO_SIZE]; +char g_tx3_buf[UART3_TX_FIFO_SIZE]; +char g_rx3_buf[UART3_RX_FIFO_SIZE]; #endif #if UART_IS_USART @@ -121,7 +121,7 @@ static int8_t uart_set_baudreg(uint8_t num, uint16_t baudreg) { - uint8_t lo,hi; + uint8_t lo, hi; /* set msb bit of hi to 0 (useful fot uC with URSEL, and not * important for the others because the baudreg will never be Commit from zer0 on branch b_zer0 (2009-01-03 17:25 CET) ================================= move PROGMEM attribute to avoid warning aversive modules/ihm/parse/parse.c 1.1.2.9 aversive modules/ihm/parse/parse.h 1.1.2.9 aversive modules/ihm/parse/parse_num.h 1.1.2.6 aversive modules/ihm/parse/parse_string.h 1.1.2.8 ================================== aversive/modules/ihm/parse/parse.c (1.1.2.8 -> 1.1.2.9) ================================== @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: parse.c,v 1.1.2.8 2007-11-24 19:27:22 zer0 Exp $ + * Revision : $Id: parse.c,v 1.1.2.9 2009-01-03 16:25:13 zer0 Exp $ * * */ @@ -202,7 +202,7 @@ #endif /* parse it !! */ - inst = (struct inst *)pgm_read_word(ctx+inst_num); + inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); while (inst) { debug_printf("INST\n"); @@ -236,7 +236,7 @@ } inst_num ++; - inst = (struct inst *)pgm_read_word(ctx+inst_num); + inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); } /* call func */ @@ -259,8 +259,8 @@ { const char * incomplete_token = buf; uint8_t inst_num = 0; - struct inst * inst; - parse_pgm_token_hdr_t * token_p; + parse_pgm_inst_t *inst; + parse_pgm_token_hdr_t *token_p; struct token_hdr token_hdr; char tmpbuf[64], completion_buf[64]; uint8_t incomplete_token_len; @@ -271,7 +271,7 @@ uint8_t nb_completable; uint8_t nb_non_completable; uint16_t local_state=0; - prog_char * help_str; + prog_char *help_str; debug_printf("%s called\n", __FUNCTION__); /* count the number of complete token to parse */ @@ -291,7 +291,7 @@ nb_completable = 0; nb_non_completable = 0; - inst = (struct inst *)pgm_read_word(ctx+inst_num); + inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); while (inst) { /* parse the first tokens of the inst */ if (nb_token && match_inst(inst, buf, nb_token, NULL)) @@ -333,7 +333,7 @@ } next: inst_num ++; - inst = (struct inst *)pgm_read_word(ctx+inst_num); + inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); } debug_printf("total choices %d for this completion\n", nb_completable); @@ -363,10 +363,10 @@ debug_printf("Multiple choice STATE=%d\n", *state); inst_num = 0; - inst = (struct inst *)pgm_read_word(ctx+inst_num); + inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); while (inst) { /* we need to redo it */ - inst = (struct inst *)pgm_read_word(ctx+inst_num); + inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); if (nb_token && match_inst(inst, buf, nb_token, NULL)) goto next2; @@ -426,7 +426,7 @@ } next2: inst_num ++; - inst = (struct inst *)pgm_read_word(ctx+inst_num); + inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); } return 0; ================================== aversive/modules/ihm/parse/parse.h (1.1.2.8 -> 1.1.2.9) ================================== @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Revision : $Id: parse.h,v 1.1.2.8 2007-11-24 19:27:22 zer0 Exp $ + * Revision : $Id: parse.h,v 1.1.2.9 2009-01-03 16:25:13 zer0 Exp $ * * */ @@ -45,7 +45,12 @@ uint8_t offset; }; typedef struct token_hdr parse_token_hdr_t; -typedef PROGMEM parse_token_hdr_t parse_pgm_token_hdr_t; + +struct token_hdr_pgm { + struct token_ops *ops; + uint8_t offset; +} PROGMEM; +typedef struct token_hdr_pgm parse_pgm_token_hdr_t; /** * A token is defined by this structure. @@ -90,7 +95,14 @@ prog_void * tokens[]; }; typedef struct inst parse_inst_t; -typedef PROGMEM parse_inst_t parse_pgm_inst_t; +struct inst_pgm { + /* f(parsed_struct, data) */ + void (*f)(void *, void *); + void * data; + char * help_str; + prog_void * tokens[]; +} PROGMEM; +typedef struct inst_pgm parse_pgm_inst_t; /** * A context is identified by its name, and contains a list of ====================================== aversive/modules/ihm/parse/parse_num.h (1.1.2.5 -> 1.1.2.6) ====================================== @@ -22,7 +22,11 @@ struct token_num_data num_data; }; typedef struct token_num parse_token_num_t; -typedef PROGMEM parse_token_num_t parse_pgm_token_num_t; +struct token_num_pgm { + struct token_hdr hdr; + struct token_num_data num_data; +} PROGMEM; +typedef struct token_num_pgm parse_pgm_token_num_t; extern struct token_ops token_num_ops; ========================================= aversive/modules/ihm/parse/parse_string.h (1.1.2.7 -> 1.1.2.8) ========================================= @@ -17,7 +17,11 @@ struct token_string_data string_data; }; typedef struct token_string parse_token_string_t; -typedef PROGMEM parse_token_string_t parse_pgm_token_string_t; +struct token_string_pgm { + struct token_hdr hdr; + struct token_string_data string_data; +} PROGMEM; +typedef struct token_string_pgm parse_pgm_token_string_t; extern struct token_ops token_string_ops; _______________________________________________ Avr-list mailing list Avr-list@droids-corp.org CVSWEB : http://cvsweb.droids-corp.org/cgi-bin/viewcvs.cgi/aversive WIKI : http://wiki.droids-corp.org/index.php/Aversive DOXYGEN : http://zer0.droids-corp.org/doxygen_aversive/html/ BUGZILLA : http://bugzilla.droids-corp.org COMMIT LOGS : http://zer0.droids-corp.org/aversive_commitlog