Changeset 630:6ccb3e5f852d for nxos
- Timestamp:
- 08/15/08 22:59:44 (5 months ago)
- Branch:
- default
- Files:
-
- 1 modified
-
nxos/base/drivers/rs485.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
nxos/base/drivers/rs485.c
r629 r630 22 22 23 23 static volatile struct { 24 U8 *buffer; /* Pointer to the buffer */25 U32 buflen; /* Buffer total length */26 24 enum { 27 25 RS485_UNINITIALIZED = 0, … … 83 81 AT91C_PIO_PA7; 84 82 85 static inline void isr_finish(void) { 86 rs485_state.buffer++; 87 rs485_state.buflen--; 88 if (rs485_state.buflen <= 0) { 89 *AT91C_US0_IDR = AT91C_US_RXRDY | AT91C_US_TXRDY; 83 static void nx_rs485_isr(void) { 84 const U32 csr = *AT91C_US0_CSR; 85 86 /* Successful transfer completion first, then error cases. */ 87 if ((rs485_state.status == RS485_RECEIVING && (csr & AT91C_US_ENDRX)) || 88 (rs485_state.status == RS485_TRANSMITTING && (csr & AT91C_US_ENDTX))) { 89 *AT91C_US0_IDR = AT91C_US_ENDRX | AT91C_US_ENDTX; 90 90 *AT91C_US0_CR = AT91C_US_RXDIS | AT91C_US_TXDIS; 91 91 rs485_state.status = RS485_IDLE; 92 if (rs485_state.callback) { 92 93 if (rs485_state.callback) 93 94 rs485_state.callback(); 94 } 95 } else if (csr & AT91C_US_TIMEOUT) { 96 /* TODO: handle timeouts */ 97 } else if (csr & AT91C_US_OVRE) { 98 /* TODO: handle overruns */ 99 } else if (csr & AT91C_US_FRAME) { 100 /* TODO: handle framing errors */ 95 101 } 96 102 } 97 103 98 static void nx_rs485_isr(void) {99 const U32 csr = *AT91C_US0_CSR;100 101 /* Discern between interrupt types, without cleaning the CSR */102 if (csr & AT91C_US_TIMEOUT) {103 /* TODO manage timeouts */104 } else if (csr & AT91C_US_OVRE) {105 /* Overrun error, TODO signal it */106 *AT91C_US0_CR = AT91C_US_RSTSTA;107 } else if (csr & AT91C_US_RXRDY && rs485_state.status == RS485_RECEIVING) {108 if (csr & AT91C_US_FRAME) {109 /* Framing error, TODO signal it */110 return;111 }112 *rs485_state.buffer = *AT91C_US0_RHR;113 isr_finish();114 } else if (csr & AT91C_US_TXRDY && rs485_state.status == RS485_TRANSMITTING) {115 *AT91C_US0_THR = *rs485_state.buffer;116 isr_finish();117 }118 }119 120 static inline void datainit(U8 *buffer, U32 buflen, nx_closure_t callback) {121 rs485_state.buffer = buffer;122 rs485_state.buflen = buflen;123 rs485_state.callback = callback;124 }125 126 104 void nx_rs485_init(void) { 127 /* Avoid double initialization */128 105 NX_ASSERT(rs485_state.status == RS485_UNINITIALIZED); 129 130 /* Install isr */131 /* FIXME: move isr installation at the end of init function */132 nx_interrupts_disable();133 nx_aic_install_isr(AT91C_ID_US0, AIC_PRIO_DRIVER, AIC_TRIG_LEVEL,134 nx_rs485_isr);135 106 136 107 /* Enable the peripheral clock */ … … 143 114 144 115 /* Reset and disable to avoid funny jokes: */ 145 /* FIXME: try to remove RXDIS and TXDIS */146 116 *AT91C_US0_CR = AT91C_US_RSTRX | /* Transmitter reset */ 147 117 AT91C_US_RSTTX | /* Receiver reset */ 148 AT91C_US_RSTSTA | /* Status bits */ 149 AT91C_US_TXDIS | /* Transmitter disable */ 150 AT91C_US_RXDIS; /* Receiver disable */ 118 AT91C_US_RSTSTA; /* Status bits */ 151 119 152 120 /* Placing the Usart settings in the appropriate register, time guard, … … 157 125 *AT91C_US0_BRGR = build_baud_rate(nx_rs485_settings.baud_rate); 158 126 159 /* Enable USART interrupts (keeping transmitter and receiver disabled,160 * since they will be enabled on the specific operation127 /* Enable USART interrupts for error conditions. Normal transmission 128 * conditions are enabled only when transfers are initiated. 161 129 */ 162 *AT91C_US0_IER = AT91C_US_OVRE | /* Overrun error (overwritten data) */ 163 AT91C_US_FRAME | /* Framing error (temporization) */ 164 AT91C_US_TXEMPTY; /* All data transmitted. */ 165 /* TODO: check interrupt triggering here */ 166 167 *AT91C_US0_IDR = AT91C_US_RXRDY | /* Receiver ready */ 168 AT91C_US_TXRDY; /* Transmitter ready */ 130 *AT91C_US0_IDR = ~0; 131 *AT91C_US0_IER = AT91C_US_OVRE | /* Overrun error (overwritten data) */ 132 AT91C_US_FRAME; /* Framing error */ 169 133 170 134 if (nx_rs485_settings.timeout > 0) { 171 135 *AT91C_US0_IER = AT91C_US_TIMEOUT; /* Timeout */ 172 /* TODO: signal it */173 136 } 174 137 175 /* Install interrupt service routine and reenable interrupt handling */ 176 nx_interrupts_enable(); 138 /* Install the rs485 ISR. */ 139 nx_aic_install_isr(AT91C_ID_US0, AIC_PRIO_DRIVER, AIC_TRIG_LEVEL, 140 nx_rs485_isr); 177 141 178 142 rs485_state.status = RS485_IDLE; … … 197 161 if (rs485_state.status != RS485_IDLE) 198 162 return FALSE; 163 199 164 rs485_state.status = RS485_TRANSMITTING; 200 datainit(buffer, buflen, callback); 201 202 /* Enable the transmitter */ 203 *AT91C_US0_IER = AT91C_US_TXRDY; 165 rs485_state.callback = callback; 166 167 /* Set up a DMA write and start transferring asynchronously. */ 168 *AT91C_US0_TPR = (U32)buffer; 169 *AT91C_US0_TCR = buflen; 170 *AT91C_US0_IER = AT91C_US_ENDTX; 171 *AT91C_US0_PTCR = AT91C_PDC_TXTEN; 204 172 *AT91C_US0_CR = AT91C_US_TXEN; 205 173 … … 212 180 if (rs485_state.status != RS485_IDLE) 213 181 return FALSE; 182 214 183 rs485_state.status = RS485_RECEIVING; 215 datainit(buffer, buflen, callback); 216 217 /* Enable the receiver */ 218 *AT91C_US0_IER = AT91C_US_RXRDY; 184 rs485_state.callback = callback; 185 186 /* Set up a DMA read and start transferring asynchronously. */ 187 *AT91C_US0_RPR = (U32)buffer; 188 *AT91C_US0_RCR = buflen; 189 *AT91C_US0_IER = AT91C_US_ENDRX; 190 *AT91C_US0_PTCR = AT91C_PDC_RXTEN; 191 192 /* Due to (apparently) the wiring of the RS485 bus, both the 193 * transmitter and the receiver have to be enabled, otherwise the 194 * receiver does not receive any data. 195 * 196 * TODO: Figure out the exact reason and document it. 197 */ 219 198 *AT91C_US0_CR = AT91C_US_RXEN | AT91C_US_TXEN; 220 199 221 200 return TRUE; 222 201 } 223
