void * rs485_pkt_drain(struct rs485_link * lnk) { struct stm32_usart * uart = lnk->uart; void * pend_pkt = NULL; uint32_t sr; uint32_t cr; if (lnk->tx.pend_pkt) { /* wait for the DMA transfer to complete */ while (!lnk->tx.isr[TCIF_BIT]) { if (lnk->tx.isr[TEIF_BIT]) { lnk->tx.ifcr[TEIF_BIT] = 1; } thinkos_irq_wait(lnk->tx.dma_irq); } /* clear the the DMA trasfer complete flag */ lnk->tx.ifcr[TCIF_BIT] = 1; /* return a reference to the packet just transmitted */ pend_pkt = lnk->tx.pend_pkt; if ((sr = uart->sr) & USART_TC) { /* pulse the TE bit to generate an idle frame */ cr = uart->cr1; uart->cr1 = cr & ~USART_TE; uart->cr1 = cr | USART_TE; } else { thinkos_sleep(lnk->idle_tm); } } lnk->tx.pend_pkt = NULL; /* return previous pending packet */ return pend_pkt; }
int __rs485_pkt_receive(struct rs485_link * lnk, void ** ppkt, int max_len) { struct stm32f_dma_stream * dma_strm = lnk->rx.dma_strm; struct stm32_usart * uart = lnk->uart; void * rcvd_pkt; uint32_t sr; int len; DCC_LOG2(LOG_INFO, "DMA stream[%d]=0x%p", lnk->rx.dma_id, dma_strm); // tracef("."); if (lnk->rx.pend_pkt == NULL) { rcvd_pkt = NULL; len = 0; } else { DCC_LOG(LOG_TRACE, "pending packet..."); trace("pending packet..."); /* wait for completion of DMA transfer */ while (!lnk->rx.isr[TCIF_BIT]) { if (lnk->rx.isr[TEIF_BIT]) { DCC_LOG(LOG_ERROR, "DMA transfer error!"); trace("DMA transfer error..."); lnk->rx.ifcr[TEIF_BIT] = 1; } if (lnk->rx.isr[FEIF_BIT]) { trace("DMA fifo error..."); lnk->rx.ifcr[FEIF_BIT] = 1; } if (lnk->rx.isr[HTIF_BIT]) { // trace("DMA half transfer..."); lnk->rx.ifcr[HTIF_BIT] = 1; } trace("wait..."); thinkos_irq_wait(lnk->rx.dma_irq); } /* return a reference to the packet just received */ rcvd_pkt = lnk->rx.pend_pkt; /* Number of data items transfered... */ len = lnk->rx.max_len - dma_strm->ndtr; /* clear the the DMA trasfer complete flag */ lnk->rx.ifcr[TCIF_BIT] = 1; tracef("DMA received len=%d max_len=%d.", len, max_len); } if (dma_strm->cr & DMA_EN) { DCC_LOG(LOG_ERROR, "DMA enabled"); trace("ERROR: DMA enabled!"); } lnk->rx.pend_pkt = *ppkt; lnk->rx.max_len = max_len; /* set DMA memory address */ dma_strm->m0ar = (void *)lnk->rx.pend_pkt; /* set DMA number of data items to transfer */ dma_strm->ndtr = max_len; /* clear the TC bit to start transfer */ if ((sr = uart->sr) & USART_TC) { DCC_LOG(LOG_INFO, "TC=1"); trace("TC=1"); uart->sr = 0; } /* enable DMA */ dma_strm->cr |= DMA_EN; /* return previous pending packet */ *ppkt = rcvd_pkt; return len; }
void * rs485_pkt_enqueue(struct rs485_link * lnk, void * pkt, int len) { struct stm32_usart * uart = lnk->uart; struct stm32f_dma_stream * dma_strm = lnk->tx.dma_strm; uint32_t sr; uint32_t cr; void * pend_pkt = NULL; DCC_LOG2(LOG_TRACE, "DMA stream[%d]=0x%p", lnk->tx.dma_id, dma_strm); if (lnk->tx.pend_pkt) { DCC_LOG(LOG_TRACE, "pending packet..."); /* wait for the DMA transfer to complete */ while (!lnk->tx.isr[TCIF_BIT]) { if (lnk->tx.isr[TEIF_BIT]) { DCC_LOG(LOG_ERROR, "DMA transfer error!"); lnk->tx.ifcr[TEIF_BIT] = 1; } thinkos_irq_wait(lnk->tx.dma_irq); } /* clear the the DMA trasfer complete flag */ lnk->tx.ifcr[TCIF_BIT] = 1; /* return a reference to the packet just transmitted */ pend_pkt = lnk->tx.pend_pkt; if ((sr = uart->sr) & USART_TC) { // trace("USART TC=1, generating an idle frame"); /* pulse the TE bit to generate an idle frame */ cr = uart->cr1; uart->cr1 = cr & ~USART_TE; uart->cr1 = cr | USART_TE; } else { DCC_LOG(LOG_TRACE, "IDLE"); thinkos_sleep(lnk->idle_tm); } } if (dma_strm->cr & DMA_EN) { DCC_LOG(LOG_ERROR, "DMA enabled"); trace("ERROR: DMA enabled!"); } /* set this packet as pending */ lnk->tx.pend_pkt = pkt; /* set DMA memory address */ dma_strm->m0ar = (void *)pkt; /* set DMA number of data items to transfer */ dma_strm->ndtr = len; /* clear the TC bit */ if ((sr = uart->sr) & USART_TC) { DCC_LOG(LOG_INFO, "TC=1"); uart->sr = 0; } /* enable DMA */ dma_strm->cr |= DMA_EN; /* return previous pending packet */ return pend_pkt; }
int lis302_rd(int reg, void * buf, unsigned int len) { struct stm32f_spi * spi = STM32F_SPI1; uint8_t * data = (uint8_t *)buf; unsigned int addr; unsigned int sr; unsigned int dummy; int i; if (len == 0) return 0; addr = (reg & 0x3f) | 0x80 | ((len > 1) ? 0x40 : 0x00); gpio_clr(lis302_cs); udelay(1); sr = spi->sr; if (!(sr & SPI_TXE)) return -1; if (sr & SPI_MODF) return -2; if (sr & SPI_RXNE) { /* clear input buffer */ dummy = spi->dr; (void)dummy; } /* send the address */ spi->dr = addr; while (!((sr = spi->sr) & SPI_TXE)) { thinkos_irq_wait(STM32F_IRQ_SPI1); } /* send first dummy data */ spi->dr = 0; /* wait for incomming data */ while (!((sr = spi->sr) & SPI_RXNE)) { thinkos_irq_wait(STM32F_IRQ_SPI1); } /* discard */ dummy = spi->dr; (void)dummy; for (i = 0; i < (len - 1); ++i) { while (!((sr = spi->sr) & SPI_TXE)) { thinkos_irq_wait(STM32F_IRQ_SPI1); } /* send dummy data */ spi->dr = 0; /* wait for incomming data */ while (!((sr = spi->sr) & SPI_RXNE)) { thinkos_irq_wait(STM32F_IRQ_SPI1); } data[i] = spi->dr; } while (!((sr = spi->sr) & SPI_RXNE)) { thinkos_irq_wait(STM32F_IRQ_SPI1); } data[i] = spi->dr; udelay(1); gpio_set(lis302_cs); return len; }