twi.c
来自「专业汽车级嵌入式操作系统OSEK的源代码」· C语言 代码 · 共 234 行
C
234 行
#include "mytypes.h"#include "twi.h"#include "interrupts.h"#include "AT91SAM7.h"#include "systick.h"#include "byte_fifo.h"#include "aic.h"extern void twi_isr_entry(void);static enum { TWI_UNINITIALISED = 0, TWI_IDLE, TWI_TX_BUSY, TWI_TX_DONE, TWI_RX_BUSY, TWI_RX_DONE, TWI_FAILED} twi_state;static U32 twi_pending;static U8 *twi_ptr;static struct { U32 rx_done; U32 tx_done; U32 bytes_tx; U32 bytes_rx; U32 unre; U32 ovre; U32 nack;} twi_stats;inttwi_busy(void){ return (twi_state == TWI_TX_BUSY || twi_state == TWI_RX_BUSY);}inttwi_ok(void){ return (twi_state >= TWI_IDLE && twi_state <= TWI_RX_DONE);}voidtwi_isr_C(void){ U32 status = *AT91C_TWI_SR; if ((status & AT91C_TWI_RXRDY) && twi_state == TWI_RX_BUSY) { if (twi_pending) { twi_stats.bytes_rx++; *twi_ptr = *AT91C_TWI_RHR; twi_ptr++; twi_pending--; if (twi_pending == 1) { /* second last byte -- issue a stop on the next byte */ *AT91C_TWI_CR = AT91C_TWI_STOP; } if (!twi_pending) { twi_stats.rx_done++; twi_state = TWI_RX_DONE; } } } if ((status & AT91C_TWI_TXRDY) && twi_state == TWI_TX_BUSY) { if (twi_pending) { /* Still Stuff to send */ *AT91C_TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_START; if (twi_pending == 1) { *AT91C_TWI_CR = AT91C_TWI_STOP; } *AT91C_TWI_THR = *twi_ptr; twi_stats.bytes_tx++; twi_ptr++; twi_pending--; } else { /* everything has been sent */ twi_state = TWI_TX_DONE; *AT91C_TWI_IDR = ~0; twi_stats.tx_done++; } } if (status & AT91C_TWI_OVRE) { /* */ twi_stats.ovre++; *AT91C_TWI_CR = AT91C_TWI_STOP; *AT91C_TWI_IDR = ~0; twi_state = TWI_FAILED; } if (status & AT91C_TWI_UNRE) { /* */ twi_stats.unre++; *AT91C_TWI_IDR = ~0; twi_state = TWI_FAILED; } if (status & AT91C_TWI_NACK) { /* */ twi_stats.nack++; *AT91C_TWI_IDR = ~0; twi_state = TWI_UNINITIALISED; }}voidtwi_reset(void){ U32 clocks = 9; *AT91C_TWI_IDR = ~0; *AT91C_PMC_PCER = (1 << AT91C_PERIPHERAL_ID_PIOA) | /* Need PIO too */ (1 << AT91C_PERIPHERAL_ID_TWI); /* TWI clock domain */ /* Set up pin as an IO pin for clocking till clean */ *AT91C_PIOA_MDER = (1 << 3) | (1 << 4); *AT91C_PIOA_PER = (1 << 3) | (1 << 4); *AT91C_PIOA_ODR = (1 << 3); *AT91C_PIOA_OER = (1 << 4); while (clocks > 0 && !(*AT91C_PIOA_PDSR & (1 << 3))) { *AT91C_PIOA_CODR = (1 << 4); systick_wait_ns(1500); *AT91C_PIOA_SODR = (1 << 4); systick_wait_ns(1500); clocks--; } *AT91C_PIOA_PDR = (1 << 3) | (1 << 4); *AT91C_PIOA_ASR = (1 << 3) | (1 << 4); *AT91C_TWI_CR = 0x88; /* Disable & reset */ *AT91C_TWI_CWGR = 0x020f0f; /* Set for 380kHz */ *AT91C_TWI_CR = 0x04; /* Enable as master */}inttwi_init(void){ int i_state; i_state = interrupts_get_and_disable(); /* Todo: set up interrupt */ *AT91C_TWI_IDR = ~0; /* Disable all interrupt sources */ aic_mask_off(AT91C_PERIPHERAL_ID_TWI); aic_set_vector(AT91C_PERIPHERAL_ID_TWI, AIC_INT_LEVEL_ABOVE_NORMAL, twi_isr_entry); aic_mask_on(AT91C_PERIPHERAL_ID_TWI); twi_reset(); /* Init peripheral */ twi_state = TWI_IDLE; if (i_state) interrupts_enable(); return 1;}voidtwi_start_read(U32 dev_addr, U32 int_addr_bytes, U32 int_addr, U8 *data, U32 nBytes){ U32 mode = ((dev_addr & 0x7f) << 16) | ((int_addr_bytes & 3) << 8) | (1 << 12); U32 dummy; if (!twi_busy()) { twi_state = TWI_RX_BUSY; *AT91C_TWI_IDR = ~0; /* Disable all interrupts */ twi_ptr = data; twi_pending = nBytes; dummy = *AT91C_TWI_SR; dummy = *AT91C_TWI_RHR;// *AT91C_AIC_ICCR = ( 1<< AT91C_PERIPHERAL_ID_TWI); *AT91C_TWI_MMR = mode; *AT91C_TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;// dummy = *AT91C_TWI_SR; *AT91C_TWI_IER = 0x01C2; }}voidtwi_start_write(U32 dev_addr, U32 int_addr_bytes, U32 int_addr, const U8 *data, U32 nBytes){ U32 mode = ((dev_addr & 0x7f) << 16) | ((int_addr_bytes & 3) << 8); if (!twi_busy()) { twi_state = TWI_TX_BUSY; *AT91C_TWI_IDR = ~0; /* Disable all interrupts */ twi_ptr = data; twi_pending = nBytes; *AT91C_TWI_MMR = mode; *AT91C_TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN; *AT91C_TWI_IER = 0x1C4; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?