00001
00042 #include <drv/ser.h>
00043 #include <drv/ser_p.h>
00044 #include <drv/irq.h>
00045 #include <cfg/debug.h>
00046 #include <hw.h>
00047 #include <DSP56F807.h>
00048
00049
00050
00051 #define REG_GPIO_SERIAL_0 REG_GPIO_E
00052 #define REG_GPIO_SERIAL_MASK_0 0x03
00053
00054 #define REG_GPIO_SERIAL_1 REG_GPIO_D
00055 #define REG_GPIO_SERIAL_MASK_1 0xC0
00056
00057
00058
00059 #if (SERRF_PARITYERROR != REG_SCI_SR_PF) || \
00060 (SERRF_RXSROVERRUN != REG_SCI_SR_OR) || \
00061 (SERRF_FRAMEERROR != REG_SCI_SR_FE) || \
00062 (SERRF_NOISEERROR != REG_SCI_SR_NF)
00063 #error error flags do not match with register bits
00064 #endif
00065
00066 static unsigned char ser0_fifo_rx[CONFIG_SER0_FIFOSIZE_RX];
00067 static unsigned char ser0_fifo_tx[CONFIG_SER0_FIFOSIZE_TX];
00068 static unsigned char ser1_fifo_rx[CONFIG_SER1_FIFOSIZE_RX];
00069 static unsigned char ser1_fifo_tx[CONFIG_SER1_FIFOSIZE_TX];
00070
00071 #if CONFIG_SER_MULTI
00072 #include <kern/sem.h>
00073
00074 #define MAX_MULTI_GROUPS 1
00075
00076 struct Semaphore multi_sems[MAX_MULTI_GROUPS];
00077 #endif
00078
00079
00080 struct SCI
00081 {
00082 struct SerialHardware hw;
00083 struct Serial* serial;
00084 volatile struct REG_SCI_STRUCT* regs;
00085 IRQ_VECTOR irq_tx;
00086 IRQ_VECTOR irq_rx;
00087 int num_group;
00088 int id;
00089 };
00090
00091 static inline void enable_tx_irq_bare(volatile struct REG_SCI_STRUCT* regs)
00092 {
00093 regs->CR |= REG_SCI_CR_TEIE | REG_SCI_CR_TIIE;
00094 }
00095
00096 static inline void enable_rx_irq_bare(volatile struct REG_SCI_STRUCT* regs)
00097 {
00098 regs->CR |= REG_SCI_CR_RIE;
00099 }
00100
00101 static inline void disable_tx_irq_bare(volatile struct REG_SCI_STRUCT* regs)
00102 {
00103 regs->CR &= ~(REG_SCI_CR_TEIE | REG_SCI_CR_TIIE);
00104 }
00105
00106 static inline void disable_rx_irq_bare(volatile struct REG_SCI_STRUCT* regs)
00107 {
00108 regs->CR &= ~(REG_SCI_CR_RIE | REG_SCI_CR_REIE);
00109 }
00110
00111 static inline void disable_tx_irq(struct SerialHardware* _hw)
00112 {
00113 struct SCI* hw = (struct SCI*)_hw;
00114
00115 disable_tx_irq_bare(hw->regs);
00116 }
00117
00118 static inline void disable_rx_irq(struct SerialHardware* _hw)
00119 {
00120 struct SCI* hw = (struct SCI*)_hw;
00121
00122 disable_rx_irq_bare(hw->regs);
00123 }
00124
00125 static inline void enable_tx_irq(struct SerialHardware* _hw)
00126 {
00127 struct SCI* hw = (struct SCI*)_hw;
00128
00129 enable_tx_irq_bare(hw->regs);
00130 }
00131
00132 static inline void enable_rx_irq(struct SerialHardware* _hw)
00133 {
00134 struct SCI* hw = (struct SCI*)_hw;
00135
00136 enable_rx_irq_bare(hw->regs);
00137 }
00138
00139 static inline bool tx_irq_enabled(struct SerialHardware* _hw)
00140 {
00141 struct SCI* hw = (struct SCI*)_hw;
00142
00143 return (hw->regs->CR & REG_SCI_CR_TEIE);
00144 }
00145
00146 static void tx_isr(const struct SCI *hw)
00147 {
00148 #pragma interrupt warn
00149 volatile struct REG_SCI_STRUCT* regs = hw->regs;
00150
00151 if (fifo_isempty(&hw->serial->txfifo))
00152 disable_tx_irq_bare(regs);
00153 else
00154 {
00155
00156 (void)regs->SR;
00157 regs->DR = fifo_pop(&hw->serial->txfifo);
00158 }
00159 }
00160
00161 static void rx_isr(const struct SCI *hw)
00162 {
00163 #pragma interrupt warn
00164 volatile struct REG_SCI_STRUCT* regs = hw->regs;
00165
00166
00167 hw->serial->status |= regs->SR & (SERRF_PARITYERROR |
00168 SERRF_RXSROVERRUN |
00169 SERRF_FRAMEERROR |
00170 SERRF_NOISEERROR);
00171
00172
00173
00174
00175
00176
00177
00178 if (regs->SR & REG_SCI_SR_RDRF)
00179 {
00180 unsigned char data = regs->DR;
00181
00182 if (fifo_isfull(&hw->serial->rxfifo))
00183 hw->serial->status |= SERRF_RXFIFOOVERRUN;
00184 else
00185 fifo_push(&hw->serial->rxfifo, data);
00186 }
00187
00188
00189 regs->SR = 0;
00190 }
00191
00192 static void init(struct SerialHardware* _hw, struct Serial* ser)
00193 {
00194 struct SCI* hw = (struct SCI*)_hw;
00195 volatile struct REG_SCI_STRUCT* regs = hw->regs;
00196
00197
00198 (void)regs->SR;
00199 regs->SR = 0;
00200
00201
00202 (void)regs->DR;
00203
00204
00205 irq_install(hw->irq_tx, (isr_t)tx_isr, hw);
00206 irq_install(hw->irq_rx, (isr_t)rx_isr, hw);
00207 irq_setpriority(hw->irq_tx, IRQ_PRIORITY_SCI_TX);
00208 irq_setpriority(hw->irq_rx, IRQ_PRIORITY_SCI_RX);
00209
00210
00211 regs->CR = REG_SCI_CR_TE | REG_SCI_CR_RE;
00212 enable_rx_irq_bare(regs);
00213
00214
00215
00216 REG_GPIO_SERIAL_0->PER |= REG_GPIO_SERIAL_MASK_0;
00217 REG_GPIO_SERIAL_1->PER |= REG_GPIO_SERIAL_MASK_1;
00218
00219 hw->serial = ser;
00220 }
00221
00222 static void cleanup(struct SerialHardware* _hw)
00223 {
00224 struct SCI* hw = (struct SCI*)_hw;
00225
00226
00227 disable_rx_irq(_hw);
00228 disable_tx_irq(_hw);
00229 irq_uninstall(hw->irq_tx);
00230 irq_uninstall(hw->irq_rx);
00231 }
00232
00233 static void setbaudrate(struct SerialHardware* _hw, unsigned long rate)
00234 {
00235 struct SCI* hw = (struct SCI*)_hw;
00236
00237
00238
00239
00240 hw->regs->BR = (IPBUS_FREQ + rate * 8ul) / (rate * 16ul);
00241 }
00242
00243 static void setparity(struct SerialHardware* _hw, int parity)
00244 {
00245
00246 ASSERT(0);
00247 }
00248
00249
00250 #if CONFIG_SER_MULTI
00251
00252 static void multi_init(void)
00253 {
00254 static bool flag = false;
00255 int i;
00256
00257 if (flag)
00258 return;
00259
00260 for (i = 0; i < MAX_MULTI_GROUPS; ++i)
00261 sem_init(&multi_sems[i]);
00262 flag = true;
00263 }
00264
00265 static void init_lock(struct SerialHardware* _hw, struct Serial *ser)
00266 {
00267 struct SCI* hw = (struct SCI*)_hw;
00268
00269
00270 multi_init();
00271
00272
00273 ASSERT(hw->num_group >= 0);
00274 ASSERT(hw->num_group < MAX_MULTI_GROUPS);
00275 sem_obtain(&multi_sems[hw->num_group]);
00276
00277
00278 ser_hw_switch(hw->num_group, hw->id);
00279
00280 init(_hw, ser);
00281 }
00282
00283 static void cleanup_unlock(struct SerialHardware* _hw)
00284 {
00285 struct SCI* hw = (struct SCI*)_hw;
00286
00287 cleanup(_hw);
00288
00289 sem_release(&multi_sems[hw->num_group]);
00290 }
00291
00292 #endif
00293
00294
00295 static const struct SerialHardwareVT SCI_VT =
00296 {
00297 .init = init,
00298 .cleanup = cleanup,
00299 .setBaudrate = setbaudrate,
00300 .setParity = setparity,
00301 .txStart = enable_tx_irq,
00302 .txSending = tx_irq_enabled,
00303 };
00304
00305 #if CONFIG_SER_MULTI
00306 static const struct SerialHardwareVT SCI_MULTI_VT =
00307 {
00308 .init = init_lock,
00309 .cleanup = cleanup_unlock,
00310 .setBaudrate = setbaudrate,
00311 .setParity = setparity,
00312 .txStart = enable_tx_irq,
00313 .txSending = tx_irq_enabled,
00314 };
00315 #endif
00316
00317 #define SCI_DESC_NORMAL(hwch) \
00318 { \
00319 .hw = \
00320 { \
00321 .table = &SCI_VT, \
00322 .rxbuffer = ser ## hwch ## _fifo_rx, \
00323 .txbuffer = ser ## hwch ## _fifo_tx, \
00324 .rxbuffer_size = countof(ser ## hwch ## _fifo_rx), \
00325 .txbuffer_size = countof(ser ## hwch ## _fifo_tx), \
00326 }, \
00327 .regs = ®_SCI[hwch], \
00328 .irq_rx = IRQ_SCI ## hwch ## _RECEIVER_FULL, \
00329 .irq_tx = IRQ_SCI ## hwch ## _TRANSMITTER_READY, \
00330 .num_group = -1, \
00331 .id = -1, \
00332 } \
00333
00334
00335 #if CONFIG_SER_MULTI
00336 #define SCI_DESC_MULTI(hwch, group_, id_) \
00337 { \
00338 .hw = \
00339 { \
00340 .table = &SCI_MULTI_VT, \
00341 .rxbuffer = ser ## hwch ## _fifo_rx, \
00342 .txbuffer = ser ## hwch ## _fifo_tx, \
00343 .rxbuffer_size = countof(ser ## hwch ## _fifo_rx), \
00344 .txbuffer_size = countof(ser ## hwch ## _fifo_tx), \
00345 }, \
00346 .regs = ®_SCI[hwch], \
00347 .irq_rx = IRQ_SCI ## hwch ## _RECEIVER_FULL, \
00348 .irq_tx = IRQ_SCI ## hwch ## _TRANSMITTER_READY, \
00349 .num_group = group_, \
00350 .id = id_, \
00351 } \
00352
00353 #endif
00354
00355
00356 static struct SCI SCIDescs[] =
00357 {
00358 SCI_DESC_NORMAL(0),
00359 SCI_DESC_MULTI(1, 0, 0),
00360 SCI_DESC_MULTI(1, 0, 1),
00361 };
00362
00363 struct SerialHardware* ser_hw_getdesc(int unit)
00364 {
00365 ASSERT(unit < countof(SCIDescs));
00366 return &SCIDescs[unit].hw;
00367 }