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