tweak twi init

This commit is contained in:
Olaf Rempel 2008-02-19 20:05:01 +01:00
parent 4e0f66eb01
commit 0302d9bdb0
1 changed files with 30 additions and 26 deletions

View File

@ -34,7 +34,7 @@
/* /*
* while ((cldiv = ((MCK / (2 * TWI)) -3) / (1 << ckdiv)) > 255) * while ((cldiv = ((MCK / (2 * TWI)) -3) / (1 << ckdiv)) > 255)
* ckdiv++ ; * ckdiv++ ;
* *
* works for TWI >= 100kHz * works for TWI >= 100kHz
*/ */
#define TWI_CLK(x) (((MCK / (2 * (x))) -3)<<8 | ((MCK / (2 * (x))) -3)) #define TWI_CLK(x) (((MCK / (2 * (x))) -3)<<8 | ((MCK / (2 * (x))) -3))
@ -56,34 +56,34 @@ static void twi_isr(void)
/* get status */ /* get status */
uint32_t status = *AT91C_TWI_SR; uint32_t status = *AT91C_TWI_SR;
status &= *AT91C_TWI_IMR; status &= *AT91C_TWI_IMR;
/* NACK - disable all interrupts and go to state TWI_ERROR */ /* NACK - disable all interrupts and go to state TWI_ERROR */
if (status & AT91C_TWI_NACK) { if (status & AT91C_TWI_NACK) {
*AT91C_TWI_IDR = AT91C_TWI_TXCOMP | AT91C_TWI_RXRDY | AT91C_TWI_TXRDY | AT91C_TWI_NACK; *AT91C_TWI_IDR = AT91C_TWI_TXCOMP | AT91C_TWI_RXRDY | AT91C_TWI_TXRDY | AT91C_TWI_NACK;
twi_state = TWI_ERROR; twi_state = TWI_ERROR;
// TODO: TWI_BLMC_UPDATE? // TODO: TWI_BLMC_UPDATE?
return; return;
} }
/* tx register ready for new data */ /* tx register ready for new data */
if (status & AT91C_TWI_TXRDY) { if (status & AT91C_TWI_TXRDY) {
if (twi_count != twi_size) { if (twi_count != twi_size) {
/* feed next byte */ /* feed next byte */
*AT91C_TWI_THR = twi_data[twi_count++]; *AT91C_TWI_THR = twi_data[twi_count++];
} else { } else {
/* wait for TXCOMP */ /* wait for TXCOMP */
*AT91C_TWI_IDR = AT91C_TWI_RXRDY | AT91C_TWI_TXRDY; *AT91C_TWI_IDR = AT91C_TWI_RXRDY | AT91C_TWI_TXRDY;
*AT91C_TWI_IER = AT91C_TWI_TXCOMP | AT91C_TWI_NACK; *AT91C_TWI_IER = AT91C_TWI_TXCOMP | AT91C_TWI_NACK;
} }
} }
/* rx register has data */ /* rx register has data */
if (status & AT91C_TWI_RXRDY) { if (status & AT91C_TWI_RXRDY) {
/* get data */ /* get data */
twi_data[twi_count++] = *AT91C_TWI_RHR; twi_data[twi_count++] = *AT91C_TWI_RHR;
/* transfer complete? */ /* transfer complete? */
if (twi_count == twi_size) { if (twi_count == twi_size) {
/* send STOP and wait for TXCOMP */ /* send STOP and wait for TXCOMP */
@ -92,29 +92,29 @@ static void twi_isr(void)
*AT91C_TWI_IER = AT91C_TWI_TXCOMP | AT91C_TWI_NACK; *AT91C_TWI_IER = AT91C_TWI_TXCOMP | AT91C_TWI_NACK;
} }
} }
/* transfer really complete? */ /* transfer really complete? */
if (status & AT91C_TWI_TXCOMP) { if (status & AT91C_TWI_TXCOMP) {
/* are we doing a blmc update? */ /* are we doing a blmc update? */
if (twi_state == TWI_BLMC_UPDATE) { if (twi_state == TWI_BLMC_UPDATE) {
uint32_t addr = (*AT91C_TWI_MMR >> 16) & 0x7F; uint32_t addr = (*AT91C_TWI_MMR >> 16) & 0x7F;
if (addr != TWI_ADDR_BL4) { if (addr != TWI_ADDR_BL4) {
/* increase address */ /* increase address */
*AT91C_TWI_MMR += (1<<16); *AT91C_TWI_MMR += (1<<16);
/* send next value to next blmc */ /* send next value to next blmc */
*AT91C_TWI_THR = *twi_data++; *AT91C_TWI_THR = *twi_data++;
} else { } else {
// TODO: // TODO:
} }
} else { } else {
*AT91C_TWI_IDR = AT91C_TWI_TXCOMP | AT91C_TWI_RXRDY | AT91C_TWI_TXRDY | AT91C_TWI_NACK; *AT91C_TWI_IDR = AT91C_TWI_TXCOMP | AT91C_TWI_RXRDY | AT91C_TWI_TXRDY | AT91C_TWI_NACK;
twi_state = TWI_IDLE; twi_state = TWI_IDLE;
} }
} }
} }
uint32_t twi_setpwm(uint8_t *values) uint32_t twi_setpwm(uint8_t *values)
{ {
@ -128,21 +128,21 @@ uint32_t twi_setpwm(uint8_t *values)
*AT91C_TWI_MMR = (TWI_ADDR_BL1 << 16) | AT91C_TWI_IADRSZ_1_BYTE; *AT91C_TWI_MMR = (TWI_ADDR_BL1 << 16) | AT91C_TWI_IADRSZ_1_BYTE;
*AT91C_TWI_IADR = CMD_SET_PWM; *AT91C_TWI_IADR = CMD_SET_PWM;
*AT91C_TWI_THR = *twi_data++; *AT91C_TWI_THR = *twi_data++;
*AT91C_TWI_IER = AT91C_TWI_TXRDY | AT91C_TWI_NACK; *AT91C_TWI_IER = AT91C_TWI_TXRDY | AT91C_TWI_NACK;
return 0; return 0;
} }
uint32_t twi_cmd(uint8_t addr, struct blmc_cmd *cmd) uint32_t twi_cmd(uint8_t addr, struct blmc_cmd *cmd)
{ {
if (twi_state != TWI_IDLE) if (twi_state != TWI_IDLE)
return 1; return 1;
/* TODO: locking needed? */ /* TODO: locking needed? */
twi_state = TWI_GENERIC_CMD; twi_state = TWI_GENERIC_CMD;
/* read transfer, or write transfer with payload */ /* read transfer, or write transfer with payload */
if (cmd->mode & BLMC_CMD_READ || cmd->size != 0) { if (cmd->mode & BLMC_CMD_READ || cmd->size != 0) {
/* set address, direction, argument count and command bytes */ /* set address, direction, argument count and command bytes */
@ -156,7 +156,7 @@ uint32_t twi_cmd(uint8_t addr, struct blmc_cmd *cmd)
*AT91C_TWI_MMR = (addr << 16) | (cmd->mode & 0xFF) << 8; *AT91C_TWI_MMR = (addr << 16) | (cmd->mode & 0xFF) << 8;
*AT91C_TWI_IADR = (cmd->cmd) >> 8; *AT91C_TWI_IADR = (cmd->cmd) >> 8;
} }
/* isr needs data & size parameters */ /* isr needs data & size parameters */
twi_data = cmd->data; twi_data = cmd->data;
twi_size = cmd->size; twi_size = cmd->size;
@ -165,14 +165,14 @@ uint32_t twi_cmd(uint8_t addr, struct blmc_cmd *cmd)
if (cmd->mode & BLMC_CMD_READ) { if (cmd->mode & BLMC_CMD_READ) {
*AT91C_TWI_CR = AT91C_TWI_START; *AT91C_TWI_CR = AT91C_TWI_START;
*AT91C_TWI_IER = AT91C_TWI_RXRDY | AT91C_TWI_NACK; *AT91C_TWI_IER = AT91C_TWI_RXRDY | AT91C_TWI_NACK;
} else { } else {
*AT91C_TWI_THR = (twi_size != 0) ? cmd->data[twi_count++] : (cmd->cmd & 0xFF); *AT91C_TWI_THR = (twi_size != 0) ? cmd->data[twi_count++] : (cmd->cmd & 0xFF);
*AT91C_TWI_IER = AT91C_TWI_TXRDY | AT91C_TWI_NACK; *AT91C_TWI_IER = AT91C_TWI_TXRDY | AT91C_TWI_NACK;
} }
/* /*
* wait for end * wait for end
* TODO: locking needed? * TODO: locking needed?
* TODO: timeout? * TODO: timeout?
*/ */
@ -181,7 +181,7 @@ uint32_t twi_cmd(uint8_t addr, struct blmc_cmd *cmd)
twi_state = TWI_IDLE; twi_state = TWI_IDLE;
return 1; return 1;
} }
return 0; return 0;
} }
@ -235,13 +235,17 @@ void at91_twi_init(void)
/* SDA & SCL from Peripheral A, Open Drain, no Pullup */ /* SDA & SCL from Peripheral A, Open Drain, no Pullup */
AT91S_PIO *pio = AT91C_BASE_PIOA; AT91S_PIO *pio = AT91C_BASE_PIOA;
pio->PIO_ASR = AT91C_PA3_TWD | AT91C_PA4_TWCK;
pio->PIO_PDR = AT91C_PA3_TWD | AT91C_PA4_TWCK; /* do a software reset (bus not connected) */
*AT91C_TWI_CR = AT91C_TWI_SWRST;
pio->PIO_MDER = AT91C_PA3_TWD | AT91C_PA4_TWCK; pio->PIO_MDER = AT91C_PA3_TWD | AT91C_PA4_TWCK;
pio->PIO_PPUDR = AT91C_PA3_TWD | AT91C_PA4_TWCK; pio->PIO_PPUDR = AT91C_PA3_TWD | AT91C_PA4_TWCK;
pio->PIO_ASR = AT91C_PA3_TWD | AT91C_PA4_TWCK;
pio->PIO_PDR = AT91C_PA3_TWD | AT91C_PA4_TWCK;
/* set TWI Clock */ /* set TWI Clock */
*AT91C_TWI_CWGR = TWI_CLK(200000) | (5<<16); *AT91C_TWI_CWGR = TWI_CLK(400000); //| (5<<16);
/* disable all (known) interrupts */ /* disable all (known) interrupts */
*AT91C_TWI_IDR = AT91C_TWI_TXCOMP | AT91C_TWI_RXRDY | AT91C_TWI_TXRDY | AT91C_TWI_NACK; *AT91C_TWI_IDR = AT91C_TWI_TXCOMP | AT91C_TWI_RXRDY | AT91C_TWI_TXRDY | AT91C_TWI_NACK;