working version

This commit is contained in:
Olaf Rempel 2007-10-05 23:21:02 +02:00
parent 5eca151828
commit 2a89d39f19

281
main.c
View File

@ -78,140 +78,49 @@ static int uart_putchar(char c, FILE *stream)
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
static uint8_t i2c_cmd; static uint8_t i2c_master_tx(uint8_t val)
static uint8_t i2c_dev;
static uint16_t i2c_address;
static uint8_t i2c_buf[64];
static volatile uint8_t i2c_complete;
void i2c_transfer(uint8_t cmd)
{ {
i2c_complete = 0; TWDR = val;
i2c_cmd = cmd; TWCR = (1<<TWINT) | (1<<TWEN);
TWCR |= (1<<TWINT) | (1<<TWSTA); loop_until_bit_is_set(TWCR, TWINT);
PORTB |= LED_RT;
while (i2c_complete != 1) {
if (i2c_complete == 2) {
_delay_ms(5);
TWCR |= (1<<TWINT) | (1<<TWSTA);
}
}
PORTB &= ~LED_RT;
}
ISR(TWI_vect)
{
static uint8_t bcnt;
uint8_t status = TWSR & 0xF8; uint8_t status = TWSR & 0xF8;
// printf("status: 0x%02x 0x%02x 0x%02x\n", i2c_cmd, status, bcnt); return status;
}
switch (status) { static uint8_t i2c_master_rx(uint8_t *val, uint8_t ack)
/* START transmitted -> send SLA+W */ {
case 0x08: if (ack)
bcnt = 0; TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
TWDR = (i2c_dev << 1); else
TWCR &= ~(1<<TWSTA); TWCR = (1<<TWINT) | (1<<TWEN);
TWCR |= (1<<TWINT);
break;
/* repeated START transmitted -> send SLA+R */ loop_until_bit_is_set(TWCR, TWINT);
case 0x10: *val = TWDR;
bcnt = 0;
TWDR = (i2c_dev << 1) | 0x01;
TWCR &= ~(1<<TWSTA);
TWCR |= (1<<TWINT);
break;
/* SLA+W transmitted, ACK received -> send command */ uint8_t status = TWSR & 0xF8;
case 0x18: return status;
bcnt++; }
TWDR = i2c_cmd;
TWCR |= (1<<TWINT);
break;
/* data transmitted, ACK received -> ? */ static void i2c_stop(void)
case 0x28: {
switch (i2c_cmd) { PORTB &= ~LED_RT;
case CMD_GET_INFO: TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
case CMD_GET_SIGNATURE: }
case CMD_READ_FLASH:
case CMD_READ_EEPROM: static void i2c_start_address(uint8_t addr)
TWCR |= (1<<TWINT) | (1<<TWSTA); {
while (1) {
PORTB |= LED_RT;
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
uint8_t status = i2c_master_tx(addr);
if (status == 0x18 || status == 0x40)
break; break;
case CMD_WRITE_FLASH: i2c_stop();
case CMD_WRITE_EEPROM: _delay_ms(1);
if (bcnt == 1) {
TWDR = (i2c_address >> 8);
} else if (bcnt == 2) {
TWDR = (i2c_address & 0xFF);
} else if (bcnt == 3) {
TWDR = (WRITE_COOKIE >> 8);
} else if (bcnt == 4) {
TWDR = (WRITE_COOKIE & 0xFF);
} else if (bcnt >= 5 && bcnt < (64 +5)) {
TWDR = i2c_buf[bcnt -5];
} else {
i2c_complete = 1;
TWCR |= (1<<TWSTO);
}
TWCR |= (1<<TWINT);
break;
default:
case CMD_BOOT_APPLICATION:
case CMD_BOOT_LOADER:
i2c_complete = 1;
TWCR |= (1<<TWINT) | (1<<TWSTO);
break;
}
bcnt++;
break;
/* SLA+R transmitted, ACK received -> send ACK (send more data) */
case 0x40:
TWCR |= (1<<TWINT) | (1<<TWEA);
break;
/* data received, ACK sent */
case 0x50:
i2c_buf[bcnt++] = TWDR;
if ((i2c_cmd == CMD_GET_INFO && bcnt < 16) ||
(i2c_cmd == CMD_GET_SIGNATURE && bcnt < 4) ||
((i2c_cmd == CMD_READ_FLASH || i2c_cmd == CMD_READ_EEPROM) && bcnt < 64)) {
TWCR |= (1<<TWEA);
} else {
TWCR &= ~(1<<TWEA);
}
TWCR |= (1<<TWINT);
break;
/* data received, NACK sent */
case 0x58:
i2c_buf[bcnt++] = TWDR;
i2c_complete = 1;
TWCR |= (1<<TWINT) | (1<<TWSTO);
break;
/* SLA+W transmitted, NACK received */
case 0x20:
/* data transmitted, NACK received */
case 0x30:
/* arbitation lost during SLA+W, SLA+R or data */
case 0x38:
/* SLA+R transmitted, NACK received */
default:
i2c_complete = 2;
TWCR |= (1<<TWINT) | (1<<TWSTO);
break;
} }
} }
@ -331,8 +240,15 @@ static uint16_t readEEpromPage(uint16_t address, uint16_t size)
void cmd_loop(void) void cmd_loop(void)
{ {
uint8_t dev = 0; uint8_t dev = 0;
uint8_t i2c_dev = (0x21 << 1);
i2c_dev = 0x21; sendchar('F');
sendchar('C');
sendchar('_');
sendchar('B');
sendchar('O');
sendchar('O');
sendchar('T');
while (1) { while (1) {
uint8_t val = recvchar(); uint8_t val = recvchar();
@ -366,22 +282,24 @@ void cmd_loop(void)
*tmp++ = (cnt < size) ? recvchar() : 0xFF; *tmp++ = (cnt < size) ? recvchar() : 0xFF;
if (dev == DEVCODE_M8) { if (dev == DEVCODE_M8) {
if (val == 'F') { i2c_start_address(i2c_dev);
tmp = page_buf; if (val == 'F')
while (size) { i2c_master_tx(CMD_WRITE_FLASH);
i2c_address = address; else
for (cnt = 0; cnt < sizeof(i2c_buf); cnt++) i2c_master_tx(CMD_WRITE_EEPROM);
i2c_buf[cnt] = *tmp++;
i2c_transfer(CMD_WRITE_FLASH); i2c_master_tx(address >> 8);
address += sizeof(i2c_buf); i2c_master_tx(address & 0xFF);
address += sizeof(page_buf);
size -= sizeof(i2c_buf); i2c_master_tx(WRITE_COOKIE >> 8);
} i2c_master_tx(WRITE_COOKIE & 0xFF);
} else if (val == 'E') { tmp = page_buf;
for (cnt = 0; cnt < sizeof(page_buf); cnt++)
i2c_master_tx(*tmp++);
} i2c_stop();
} else if (dev == DEVCODE_M644) { } else if (dev == DEVCODE_M644) {
if (val == 'F') { if (val == 'F') {
@ -399,22 +317,24 @@ void cmd_loop(void)
val = recvchar(); val = recvchar();
if (dev == DEVCODE_M8) { if (dev == DEVCODE_M8) {
if (val == 'F') { i2c_start_address(i2c_dev);
while (size > 0) { if (val == 'F')
uint8_t i = 0; i2c_master_tx(CMD_READ_FLASH);
i2c_address = address; else
i2c_transfer(CMD_READ_FLASH); i2c_master_tx(CMD_READ_EEPROM);
address += sizeof(i2c_buf); i2c_master_tx(address >> 8);
while (size-- && i < sizeof(i2c_buf)) i2c_master_tx(address & 0xFF);
sendchar(i2c_buf[i++]);
}
} else if (val == 'E') {
sendchar(0xff);
i2c_start_address(i2c_dev | 0x01);
while (size--) {
i2c_master_rx(&val, size > 0);
sendchar(val);
address++;
} }
i2c_stop();
} else if (dev == DEVCODE_M644) { } else if (dev == DEVCODE_M644) {
if (val == 'F') { if (val == 'F') {
address = readFlashPage(address, size); address = readFlashPage(address, size);
@ -437,14 +357,27 @@ void cmd_loop(void)
// Enter programming mode // Enter programming mode
} else if (val == 'P') { } else if (val == 'P') {
/* boot loader */ i2c_start_address(i2c_dev);
i2c_transfer(CMD_BOOT_LOADER); i2c_master_tx(CMD_BOOT_LOADER);
i2c_stop();
_delay_ms(10);
i2c_start_address(i2c_dev);
i2c_master_tx(CMD_GET_SIGNATURE);
i2c_start_address(i2c_dev | 0x01);
i2c_master_rx(&val, 1);
i2c_master_rx(&val, 1);
i2c_master_rx(&val, 0);
i2c_stop();
sendchar('\r'); sendchar('\r');
// Leave programming mode // Leave programming mode
} else if (val == 'L') { } else if (val == 'L') {
/* boot application */ i2c_start_address(i2c_dev);
i2c_transfer(CMD_BOOT_APPLICATION); i2c_master_tx(CMD_BOOT_APPLICATION);
i2c_stop();
sendchar('\r'); sendchar('\r');
// return programmer type // return programmer type
@ -478,7 +411,7 @@ void cmd_loop(void)
sendchar('T'); sendchar('T');
// Return Software Version // Return Software Version
} else if (val == 'V') { } else if (val == 'V' || val == 'v') {
sendchar('0'); sendchar('0');
sendchar('8'); sendchar('8');
@ -502,9 +435,23 @@ void cmd_loop(void)
// set i2c target // set i2c target
} else if (val >= '1' && val <= '4') { } else if (val >= '1' && val <= '4') {
i2c_dev = val - '1' + 0x21; i2c_dev = (val - '1' + 0x21) << 1;
sendchar(val); sendchar(val);
// test props
} else if (val == 'l') {
i2c_start_address(i2c_dev);
i2c_master_tx(CMD_SET_PWM);
i2c_master_tx(0x00);
i2c_stop();
// test props
} else if (val == 'k') {
i2c_start_address(i2c_dev);
i2c_master_tx(CMD_SET_PWM);
i2c_master_tx(0x0f);
i2c_stop();
/* ESC */ /* ESC */
} else if (val != 0x1b) { } else if (val != 0x1b) {
sendchar('?'); sendchar('?');
@ -541,38 +488,22 @@ int main(void)
/* enable TWI interface */ /* enable TWI interface */
TWBR = ((F_CPU/TWI_CLK)-16)/2; TWBR = ((F_CPU/TWI_CLK)-16)/2;
TWCR = (1<<TWSTO) | (1<<TWEN) | (1<<TWIE); TWCR = (1<<TWSTO) | (1<<TWEN);
sei(); sei();
while (boot_timeout > 0) { while (boot_timeout > 0) {
if (UCSR0A & (1<<RXC0)) if (UCSR0A & (1<<RXC0))
cmd_loop(); if (recvchar() == 'S')
cmd_loop();
} }
cli(); cli();
/* disable TWI */
TWCR = 0x00;
/* disable Timer0 */
TIMSK0 = 0x00;
TCCR0B = 0x00;
/* disable USART */
UCSR0C = 0x00;
UCSR0B = 0x00;
/* move interrupt-vectors to applicaion */ /* move interrupt-vectors to applicaion */
MCUCR = (1<<IVCE); MCUCR = (1<<IVCE);
MCUCR = (0<<IVSEL); MCUCR = (0<<IVSEL);
PORTB = 0x00;
uint8_t i;
for (i = 0; i < 10; i++)
_delay_ms(10);
jump_to_app(); jump_to_app();
return 0; return 0;