static BT_ERROR canRead(BT_HANDLE hCan, BT_CAN_MESSAGE *pCanMessage) { volatile LPC17xx_CAN_REGS *pRegs = hCan->pRegs; BT_ERROR Error = BT_ERR_NONE; switch(hCan->eMode) { case BT_CAN_MODE_POLLED: { while(!(pRegs->CANGSR & LPC17xx_CAN_GSR_RBS)) { BT_ThreadYield(); } CanReceive(hCan, pCanMessage); break; } case BT_CAN_MODE_BUFFERED: { // Get bytes from RX buffer very quickly. BT_FifoRead(hCan->hRxFifo, 1, pCanMessage, &Error); break; } default: // ERR, invalid handle configuration. break; } return Error; }
static BT_u32 i2c_master_transfer(BT_HANDLE hI2C, BT_I2C_MESSAGE *msgs, BT_u32 num, BT_ERROR *pError) { while(hI2C->pRegs->STATUS & STATUS_BA) { BT_ThreadYield(); } if(num > 1) { hI2C->bHold = 1; hI2C->pRegs->CONTROL |= CONTROL_HOLD; } else { hI2C->bHold = BT_FALSE; } BT_u32 count; for(count = 0; count < num; count++, msgs++) { if(count == (num - 1)) { hI2C->bHold = BT_FALSE; } retry: hI2C->err_status = 0; hI2C->p_msg = msgs; if(msgs->flags & BT_I2C_M_TEN) { hI2C->pRegs->CONTROL &= ~CONTROL_NEA; } else { hI2C->pRegs->CONTROL |= CONTROL_NEA; } if(msgs->flags & BT_I2C_M_RD) { mrecv(hI2C); } else { msend(hI2C); } // Wait on transfer complete signal. BT_kMutexPend(hI2C->pMutex, 0); hI2C->pRegs->INT_DISABLE = 0x000002FF; if(hI2C->err_status & INT_MASK_ARB_LOST) { BT_kPrint("ZYNQ I2C: Lost ownership on bus, trying again..."); BT_ThreadSleep(2); goto retry; } } hI2C->p_msg = NULL; hI2C->err_status = 0; return num; }
/** * Make the UART inactive (Clear the Enable bit). **/ static BT_ERROR uartDisable(BT_HANDLE hUart) { volatile LM3Sxx_UART_REGS *pRegs = hUart->pRegs; // Wait for end of TX. while(pRegs->FR & LM3Sxx_UART_FR_BUSY) { BT_ThreadYield(); } // Disable the FIFO. pRegs->LCRH &= ~(LM3Sxx_UART_LCRH_FEN); // Disable the UART. pRegs->CTL &= ~(LM3Sxx_UART_CTL_UARTEN | LM3Sxx_UART_CTL_TXE | LM3Sxx_UART_CTL_RXE); return BT_ERR_NONE; }
static BT_ERROR devcfg_cleanup(BT_HANDLE h) { g_bInUse = BT_FALSE; while(!(h->pRegs->INT_STS & INT_STS_PCFG_DONE)) { BT_ThreadYield(); } zynq_slcr_unlock(h->pSLCR); zynq_slcr_postload_fpga(h->pSLCR); zynq_slcr_lock(h->pSLCR); bt_iounmap(h->pRegs); bt_iounmap(h->pSLCR); return BT_ERR_NONE; }
/** * Implementing the CHAR dev write API. * * Note, this doesn't implement ulFlags specific options yet! **/ static BT_s32 uartWrite(BT_HANDLE hUart, BT_u32 ulFlags, BT_u32 ulSize, const BT_u8 *pucSource) { volatile LM3Sxx_UART_REGS *pRegs = hUart->pRegs; BT_ERROR Error = BT_ERR_NONE; BT_u8 ucData; BT_u8 *pSrc = (BT_u8*)pucSource; BT_u32 slWritten = 0; switch(hUart->eMode) { case BT_UART_MODE_POLLED: { while(ulSize) { while((pRegs->FR & LM3Sxx_UART_FR_TXFF)) { BT_ThreadYield(); } pRegs->DR = *pucSource++; ulSize--; slWritten++; } break; } case BT_UART_MODE_BUFFERED: { slWritten = BT_FifoWrite(hUart->hTxFifo, ulSize, pSrc, 0); pRegs->IM &= ~LM3Sxx_UART_INT_TX; // Disable the interrupt while (!BT_FifoIsEmpty(hUart->hTxFifo, &Error) && (!(pRegs->FR & LM3Sxx_UART_FR_TXFF))) { BT_FifoRead(hUart->hTxFifo, 1, &ucData, 0); pRegs->DR = ucData; } pRegs->IM |= LM3Sxx_UART_INT_TX; // Enable the interrupt break; } default: break; } return slWritten; }
static BT_s32 uartRead(BT_HANDLE hUart, BT_u32 ulFlags, BT_u32 ulSize, BT_u8 *pucDest) { volatile LM3Sxx_UART_REGS *pRegs = hUart->pRegs; BT_ERROR Error = BT_ERR_NONE; BT_s32 slRead = 0; switch(hUart->eMode) { case BT_UART_MODE_POLLED: { while(ulSize) { while((pRegs->FR & LM3Sxx_UART_FR_RXFE)) { if (slRead) return slRead; else BT_ThreadYield(); } *pucDest++ = pRegs->DR & 0x000000FF; ulSize--; slRead++; } break; } case BT_UART_MODE_BUFFERED: { // Get bytes from RX buffer very quickly. slRead = BT_FifoRead(hUart->hRxFifo, ulSize, pucDest, 0); break; } default: // ERR, invalid handle configuration. break; } return slRead; }
/** * Note, this doesn't implement ulFlags specific options yet! **/ static BT_ERROR canWrite(BT_HANDLE hCan, BT_CAN_MESSAGE *pCanMessage) { volatile LPC17xx_CAN_REGS *pRegs = hCan->pRegs; BT_CAN_MESSAGE oMessage; BT_ERROR Error = BT_ERR_NONE; switch(hCan->eMode) { case BT_CAN_MODE_POLLED: { BT_u32 ulIndex; while ((ulIndex = canFindFreeBuffer(hCan)) == LPC17xx_CAN_NO_FREE_BUFFER) { BT_ThreadYield(); } CanTransmit(hCan, pCanMessage); break; } case BT_CAN_MODE_BUFFERED: { BT_FifoWrite(hCan->hTxFifo, 1, pCanMessage, &Error); while (!BT_FifoIsEmpty(hCan->hTxFifo, &Error) && (canFindFreeBuffer(hCan) != LPC17xx_CAN_NO_FREE_BUFFER)) { BT_FifoRead(hCan->hTxFifo, 1, &oMessage, &Error); CanTransmit(hCan, &oMessage); } pRegs->CANIER |= LPC17xx_CAN_IER_TIE; // Enable the interrupt break; } default: break; } return Error; }
/** * This assumes a single write request will be generated. **/ static BT_s32 devcfg_write(BT_HANDLE hDevcfg, BT_u32 ulFlags, BT_u32 ulSize, const void *pBuffer) { BT_u32 user_count = ulSize; BT_u32 kmem_size = ulSize + hDevcfg->residue_len; bt_paddr_t kmem = bt_page_alloc_coherent(kmem_size); if(!kmem) { BT_kPrint("xdevcfg: Cannot allocate memory."); return BT_ERR_NO_MEMORY; } BT_u8 *buf = (BT_u8 *) bt_phys_to_virt(kmem); // Collect stragglers from last time (0 to 3 bytes). memcpy(buf, hDevcfg->residue_buf, hDevcfg->residue_len); // Copy the user data. memcpy(buf + hDevcfg->residue_len, pBuffer, ulSize); // Include straggles in total to be counted. ulSize += hDevcfg->residue_len; // Check if header? if(hDevcfg->offset == 0 && ulSize > 4) { BT_u32 i; for(i = 0; i < ulSize - 4; i++) { if(!memcmp(buf + i, "\x66\x55\x99\xAA", 4)) { BT_kPrint("xdevcfg: found normal sync word."); hDevcfg->bEndianSwap = 0; break; } if(!memcmp(buf + i, "\xAA\x99\x55\x66", 4)) { BT_kPrint("xdevcfg: found byte-swapped sync word."); hDevcfg->bEndianSwap = 1; break; } } if(i != ulSize - 4) { ulSize -= i; memmove(buf, buf + i, ulSize); // ulSize - i ?? } } // Save stragglers for next time. hDevcfg->residue_len = ulSize % 4; ulSize -= hDevcfg->residue_len; memcpy(hDevcfg->residue_buf, buf + ulSize, hDevcfg->residue_len); // Fixup the endianness if(hDevcfg->bEndianSwap) { BT_u32 i; for (i = 0; i < ulSize; i += 4) { BT_u32 *p = (BT_u32 *) &buf[i]; p[0] = __builtin_bswap32(p[0]); } } // Transfer the data. hDevcfg->pRegs->DMA_SRC_ADDR = (BT_u32 ) kmem | 1; hDevcfg->pRegs->DMA_DST_ADDR = 0xFFFFFFFF; BT_u32 transfer_len = 0; if(ulSize % 4) { transfer_len = (ulSize / 4) + 1; } else { transfer_len = (ulSize / 4); } hDevcfg->pRegs->DMA_SRC_LEN = transfer_len; hDevcfg->pRegs->DMA_DST_LEN = 0; while(!(hDevcfg->pRegs->INT_STS & INT_STS_DMA_DONE_INT)) { BT_ThreadYield(); } hDevcfg->pRegs->INT_STS = INT_STS_DMA_DONE_INT; // Clear DMA_DONE status hDevcfg->offset += user_count; bt_page_free_coherent(kmem, kmem_size); return user_count; }
long bt_sys_yield(void) { BT_ThreadYield(); return 0; }