static inline void lpc_sdmmc_verify(CORE* core) { SHA1_CTX sha1; uint8_t hash_in[SHA1_BLOCK_SIZE]; if ((core->sdmmc.state != SDMMC_STATE_VERIFY) && (core->sdmmc.state != SDMMC_STATE_WRITE_VERIFY)) return; sha1_init(&sha1); sha1_update(&sha1, io_data(core->sdmmc.io), core->sdmmc.total); sha1_final(&sha1, core->sdmmc.state == SDMMC_STATE_VERIFY ? hash_in : core->sdmmc.hash); if (core->sdmmc.state == SDMMC_STATE_WRITE_VERIFY) { core->sdmmc.state = SDMMC_STATE_VERIFY; lpc_sdmmc_prepare_descriptors(core); if (sdmmcs_read(&core->sdmmc.sdmmcs, core->sdmmc.sector, core->sdmmc.total / core->sdmmc.sdmmcs.sector_size)) return; } else { if (memcmp(core->sdmmc.hash, hash_in, SHA1_BLOCK_SIZE) == 0) { io_complete(core->sdmmc.process, HAL_IO_CMD(HAL_SDMMC, IPC_WRITE), core->sdmmc.user, core->sdmmc.io); core->sdmmc.io = NULL; core->sdmmc.process = INVALID_HANDLE; core->sdmmc.state = SDMMC_STATE_IDLE; return; } } io_complete_ex(core->sdmmc.process, HAL_IO_CMD(HAL_SDMMC, IPC_WRITE), core->sdmmc.user, core->sdmmc.io, get_last_error()); core->sdmmc.io = NULL; core->sdmmc.process = INVALID_HANDLE; core->sdmmc.state = SDMMC_STATE_IDLE; }
static void lpc_eth_flush(EXO* exo) { IO* io; //flush TxFIFO controller LPC_ETHERNET->DMA_OP_MODE |= ETHERNET_DMA_OP_MODE_FTF_Msk; while(LPC_ETHERNET->DMA_OP_MODE & ETHERNET_DMA_OP_MODE_FTF_Msk) {} #if (ETH_DOUBLE_BUFFERING) int i; for (i = 0; i < 2; ++i) { exo->eth.rx_des[0].size = ETH_RDES1_RCH; exo->eth.rx_des[0].buf2_ndes = &exo->eth.rx_des[1]; exo->eth.rx_des[1].size = ETH_RDES1_RCH; exo->eth.rx_des[1].buf2_ndes = &exo->eth.rx_des[0]; exo->eth.tx_des[0].ctl = ETH_TDES0_TCH | ETH_TDES0_IC; exo->eth.tx_des[0].buf2_ndes = &exo->eth.tx_des[1]; exo->eth.tx_des[1].ctl = ETH_TDES0_TCH | ETH_TDES0_IC; exo->eth.tx_des[1].buf2_ndes = &exo->eth.tx_des[0]; __disable_irq(); exo->eth.rx_des[i].ctl = 0; io = exo->eth.rx[i]; exo->eth.rx[i] = NULL; __enable_irq(); if (io != NULL) kexo_io_ex(exo->eth.tcpip, HAL_IO_CMD(HAL_ETH, IPC_READ), exo->eth.phy_addr, io, ERROR_IO_CANCELLED); __disable_irq(); exo->eth.tx_des[i].ctl = ETH_TDES0_TCH | ETH_TDES0_IC;; io = exo->eth.tx[i]; exo->eth.tx[i] = NULL; __enable_irq(); if (io != NULL) kexo_io_ex(exo->eth.tcpip, HAL_IO_CMD(HAL_ETH, IPC_WRITE), exo->eth.phy_addr, io, ERROR_IO_CANCELLED); } exo->eth.cur_rx = (LPC_ETHERNET->DMA_CURHOST_REC_BUF == (unsigned int)(&exo->eth.rx_des[0]) ? 0 : 1); exo->eth.cur_tx = (LPC_ETHERNET->DMA_CURHOST_TRANS_BUF == (unsigned int)(&exo->eth.tx_des[0]) ? 0 : 1); #else __disable_irq(); io = exo->eth.rx; exo->eth.rx = NULL; __enable_irq(); if (io != NULL) kexo_io_ex(exo->eth.tcpip, HAL_IO_CMD(HAL_ETH, IPC_READ), exo->eth.phy_addr, io, ERROR_IO_CANCELLED); __disable_irq(); io = exo->eth.tx; exo->eth.tx = NULL; __enable_irq(); if (io != NULL) kexo_io_ex(exo->eth.tcpip, HAL_IO_CMD(HAL_ETH, IPC_WRITE), exo->eth.phy_addr, io, ERROR_IO_CANCELLED); #endif }
static void udps_send_user(TCPIPS* tcpips, IP* src, IO* io, HANDLE handle) { IO* user_io; unsigned int offset, size; UDP_STACK* udp_stack; UDP_HANDLE* uh; UDP_HEADER* hdr = io_data(io); uh = so_get(&tcpips->udps.handles, handle); for (offset = sizeof(UDP_HEADER); uh->head && offset < io->data_size; offset += size) { user_io = udps_peek_head(tcpips, uh); udp_stack = io_push(user_io, sizeof(UDP_STACK)); udp_stack->remote_addr.u32.ip = src->u32.ip; udp_stack->remote_port = be2short(hdr->src_port_be); size = io_get_free(user_io); if (size > io->data_size - offset) size = io->data_size - offset; memcpy(io_data(user_io), (uint8_t*)io_data(io) + offset, size); user_io->data_size = size; io_complete(uh->process, HAL_IO_CMD(HAL_UDP, IPC_READ), handle, user_io); } #if (UDP_DEBUG) if (offset < io->data_size) printf("UDP: %d byte(s) dropped\n", io->data_size - offset); #endif //UDP_DEBUG }
void lpc_sdmmc_on_isr(int vector, void* param) { CORE* core = (CORE*)param; if (LPC_SDMMC->IDSTS & SDMMC_IDSTS_NIS_Msk) { switch (core->sdmmc.state) { case SDMMC_STATE_READ: case SDMMC_STATE_WRITE: if (core->sdmmc.state == SDMMC_STATE_READ) core->sdmmc.io->data_size = core->sdmmc.total; iio_complete(core->sdmmc.process, HAL_IO_CMD(HAL_SDMMC, core->sdmmc.state == SDMMC_STATE_READ ? IPC_READ : IPC_WRITE), core->sdmmc.user, core->sdmmc.io); core->sdmmc.io = NULL; core->sdmmc.process = INVALID_HANDLE; core->sdmmc.state = SDMMC_STATE_IDLE; break; case SDMMC_STATE_VERIFY: case SDMMC_STATE_WRITE_VERIFY: //write is taking some also as hash, so it's better to switch to userspace for completion ipc_ipost_inline(process_iget_current(), HAL_CMD(HAL_SDMMC, LPC_SDMMC_VERIFY), 0, 0, 0); break; default: break; } LPC_SDMMC->IDSTS = SDMMC_IDSTS_RI_Msk | SDMMC_IDSTS_TI_Msk | SDMMC_IDSTS_NIS_Msk; } if (LPC_SDMMC->IDSTS & SDMMC_IDSTS_AIS_Msk) { if (LPC_SDMMC->IDSTS & SDMMC_IDSTS_FBE_Msk) { lpc_sdmmc_error(core, ERROR_HARDWARE); LPC_SDMMC->IDSTS = SDMMC_IDSTS_FBE_Msk; } if (LPC_SDMMC->IDSTS & SDMMC_IDSTS_CES_Msk) { if (LPC_SDMMC->RINTSTS & SDMMC_RINTSTS_DRTO_BDS_Msk) { lpc_sdmmc_error(core, ERROR_TIMEOUT); LPC_SDMMC->RINTSTS = SDMMC_RINTSTS_DRTO_BDS_Msk; } if (LPC_SDMMC->RINTSTS & SDMMC_RINTSTS_DCRC_Msk) { lpc_sdmmc_error(core, ERROR_CRC); LPC_SDMMC->RINTSTS = SDMMC_RINTSTS_DCRC_Msk; } if (LPC_SDMMC->RINTSTS & (SDMMC_RINTSTS_SBE_Msk | SDMMC_RINTSTS_EBE_Msk)) { lpc_sdmmc_error(core, ERROR_HARDWARE); LPC_SDMMC->RINTSTS = SDMMC_RINTSTS_SBE_Msk | SDMMC_RINTSTS_EBE_Msk; } LPC_SDMMC->IDSTS = SDMMC_IDSTS_CES_Msk; } LPC_SDMMC->IDSTS = SDMMC_IDSTS_AIS_Msk; } }
static void lpc_sdmmc_error(CORE* core, int error) { if (core->sdmmc.state != SDMMC_STATE_IDLE) { iio_complete_ex(core->sdmmc.process, HAL_IO_CMD(HAL_SDMMC, core->sdmmc.state == SDMMC_STATE_READ ? IPC_READ : IPC_WRITE), 0, core->sdmmc.io, error); core->sdmmc.io = NULL; core->sdmmc.process = INVALID_HANDLE; core->sdmmc.state = SDMMC_STATE_IDLE; } }
static inline void lpc_usb_out(CORE* core, int num) { EP* ep = core->usb.out[USB_EP_NUM(num)]; unsigned int cnt = ep->mps - (((*USB_EP_LISTSTS(num, 0)) & USB_EP_LISTST_NBYTES_MASK) >> USB_EP_LISTST_NBYTES_POS); io_data_append(ep->io, ep->fifo, cnt); if (ep->io->data_size >= ep->size || cnt < ep->mps) { ep->io_active = false; iio_complete(core->usb.device, HAL_IO_CMD(HAL_USB, IPC_READ), num, ep->io); ep->io = NULL; } else lpc_usb_rx_prepare(core, num); }
void usb_on_isr(int vector, void* param) { int i; EXO* exo = param; unsigned int sta = OTG_FS_GENERAL->INTSTS; //first two most often called if ((OTG_FS_GENERAL->INTMSK & OTG_FS_GENERAL_INTMSK_RXFLVLM) && (sta & OTG_FS_GENERAL_INTSTS_RXFLVL)) { //mask interrupts, will be umasked by process after FIFO read OTG_FS_GENERAL->INTMSK &= ~OTG_FS_GENERAL_INTMSK_RXFLVLM; stm32_otg_on_isr_rx(exo); return; } for (i = 0; i < USB_EP_COUNT_MAX; ++i) if (exo->usb.in[i] != NULL && exo->usb.in[i]->io_active && (OTG_FS_DEVICE->INEP[i].INT & OTG_FS_DEVICE_ENDPOINT_INT_XFRC)) { OTG_FS_DEVICE->INEP[i].INT = OTG_FS_DEVICE_ENDPOINT_INT_XFRC; if (exo->usb.in[i]->size >= exo->usb.in[i]->io->data_size) { exo->usb.in[i]->io_active = false; iio_complete(exo->usb.device, HAL_IO_CMD(HAL_USB, IPC_WRITE), USB_EP_IN | i, exo->usb.in[i]->io); exo->usb.in[i]->io = NULL; } else stm32_otg_tx(exo, USB_EP_IN | i); return; } //rarely called if (sta & OTG_FS_GENERAL_INTSTS_ENUMDNE) { usb_enumdne(exo); OTG_FS_GENERAL->INTSTS |= OTG_FS_GENERAL_INTSTS_ENUMDNE; return; } if ((sta & OTG_FS_GENERAL_INTSTS_USBSUSP) && (OTG_FS_GENERAL->INTMSK & OTG_FS_GENERAL_INTMSK_USBSUSPM)) { usb_suspend(exo); OTG_FS_GENERAL->INTSTS |= OTG_FS_GENERAL_INTSTS_USBSUSP; return; } if (sta & OTG_FS_GENERAL_INTSTS_WKUPINT) { usb_wakeup(exo); OTG_FS_GENERAL->INTSTS |= OTG_FS_GENERAL_INTSTS_WKUPINT | OTG_FS_GENERAL_INTSTS_USBSUSP; } OTG_FS_GENERAL->OTGINT = 0xFFFFFF;// clear other request }
bool stm32_otg_ep_flush(EXO* exo, int num) { EP* ep = ep_data(exo, num); if (ep == NULL) { kerror(ERROR_NOT_CONFIGURED); return false; } if (ep->io != NULL) { kexo_io_ex(exo->usb.device, HAL_IO_CMD(HAL_USB, (num & USB_EP_IN) ? IPC_WRITE : IPC_READ), num, ep->io, ERROR_IO_CANCELLED); ep->io = NULL; ep_reg_data(num)->CTL |= OTG_FS_DEVICE_ENDPOINT_CTL_SNAK; } ep->io_active = false; return true; }
bool lpc_usb_ep_flush(CORE* core, int num) { EP* ep = ep_data(core, num); if (ep == NULL) { error(ERROR_NOT_CONFIGURED); return false; } ep->io_active = false; lpc_usb_ep_reset(core, num); if (ep->io != NULL) { io_complete_ex(core->usb.device, HAL_IO_CMD(HAL_USB, (num & USB_EP_IN) ? IPC_WRITE : IPC_READ), num, ep->io, ERROR_IO_CANCELLED); ep->io = NULL; } return true; }
static inline void lpc_usb_in(CORE* core, int num) { EP* ep = core->usb.in[USB_EP_NUM(num)]; //handle STATUS in for set address if (core->usb.addr && ep->size == 0) { LPC_USB->DEVCMDSTAT |= core->usb.addr; core->usb.addr = 0; } if (ep->size >= ep->io->data_size) { ep->io_active = false; iio_complete(core->usb.device, HAL_IO_CMD(HAL_USB, IPC_WRITE), USB_EP_IN | num, ep->io); ep->io = NULL; } else lpc_usb_tx(core, num); }
static void lpc_sdmmc_flush(CORE* core) { IO* io; HANDLE process; SDMMC_STATE state = SDMMC_STATE_IDLE; __disable_irq(); if (core->sdmmc.state != SDMMC_STATE_IDLE) { process = core->sdmmc.process; io = core->sdmmc.io; state = core->sdmmc.state; core->sdmmc.state = SDMMC_STATE_IDLE; } __enable_irq(); if (state != SDMMC_STATE_IDLE) { sdmmcs_stop(&core->sdmmc.sdmmcs); io_complete_ex(process, HAL_IO_CMD(HAL_SDMMC, state == SDMMC_STATE_READ ? IPC_READ : IPC_WRITE), core->sdmmc.user, io, ERROR_IO_CANCELLED); } }
//------------------------------------------------------------------------ static inline void stm32_otg_on_isr_rx(EXO* exo) { IPC ipc; unsigned int sta = OTG_FS_GENERAL->RXSTSP; unsigned int pktsts = sta & OTG_FS_GENERAL_RXSTSR_PKTSTS; int bcnt = (sta & OTG_FS_GENERAL_RXSTSR_BCNT) >> OTG_FS_GENERAL_RXSTSR_BCNT_POS; unsigned int ep_num = (sta & OTG_FS_GENERAL_RXSTSR_EPNUM) >> OTG_FS_GENERAL_RXSTSR_EPNUM_POS; EP* ep = exo->usb.out[ep_num]; if (pktsts == OTG_FS_GENERAL_RXSTSR_PKTSTS_SETUP_RX) { //ignore all data on setup packet exo->usb.setup_lo = ((uint32_t*)(OTG_FS_FIFO_BASE + ep_num * 0x1000))[0]; exo->usb.setup_hi = ((uint32_t*)(OTG_FS_FIFO_BASE + ep_num * 0x1000))[1]; } else if ((pktsts == OTG_FS_GENERAL_RXSTSR_PKTSTS_SETUP_DONE)) { ipc.process = exo->usb.device; ipc.cmd = HAL_CMD(HAL_USB, USB_SETUP); ipc.param1 = USB_HANDLE(USB_0, 0); ipc.param2 = exo->usb.setup_lo; ipc.param3 = exo->usb.setup_hi; ipc_ipost(&ipc); } else if ((pktsts == OTG_FS_GENERAL_RXSTSR_PKTSTS_OUT_RX) && bcnt) { memcpy4(io_data(ep->io) + ep->io->data_size, (void*)(OTG_FS_FIFO_BASE + ep_num * 0x1000), bcnt); ep->io->data_size += bcnt; if (ep->io->data_size >= ep->size || bcnt < ep->mps ) { iio_complete(exo->usb.device, HAL_IO_CMD(HAL_USB, IPC_READ), ep_num, ep->io); ep->io_active = false; ep->io = NULL; } else stm32_otg_rx_prepare(exo, ep_num); } OTG_FS_GENERAL->INTMSK |= OTG_FS_GENERAL_INTMSK_RXFLVLM; }
void lpc_eth_isr(int vector, void* param) { #if (ETH_DOUBLE_BUFFERING) int i; #endif //ETH_DOUBLE_BUFFERING uint32_t sta; EXO* exo = (EXO*)param; sta = LPC_ETHERNET->DMA_STAT; if (sta & ETHERNET_DMA_STAT_RI_Msk) { #if (ETH_DOUBLE_BUFFERING) for (i = 0; i < 2; ++i) { if ((exo->eth.rx[exo->eth.cur_rx] != NULL) && ((exo->eth.rx_des[exo->eth.cur_rx].ctl & ETH_RDES0_OWN) == 0)) { exo->eth.rx[exo->eth.cur_rx]->data_size = (exo->eth.rx_des[exo->eth.cur_rx].ctl & ETH_RDES0_FL_MASK) >> ETH_RDES0_FL_POS; iio_complete(exo->eth.tcpip, HAL_IO_CMD(HAL_ETH, IPC_READ), exo->eth.phy_addr, exo->eth.rx[exo->eth.cur_rx]); exo->eth.rx[exo->eth.cur_rx] = NULL; exo->eth.cur_rx = (exo->eth.cur_rx + 1) & 1; } else break; }
static inline void lpc_sdmmc_get_media_descriptor(CORE* core, HANDLE process, HANDLE user, IO* io) { STORAGE_MEDIA_DESCRIPTOR* media; if (!core->sdmmc.active) { error(ERROR_NOT_CONFIGURED); return; } if (user != core->sdmmc.user) { error(ERROR_INVALID_PARAMS); return; } media = io_data(io); media->num_sectors = core->sdmmc.sdmmcs.num_sectors; //SDSC/HC media->num_sectors_hi = 0; media->sector_size = core->sdmmc.sdmmcs.sector_size; sprintf(STORAGE_MEDIA_SERIAL(media), "%08X", core->sdmmc.sdmmcs.serial); io->data_size = sizeof(STORAGE_MEDIA_DESCRIPTOR) + 8 + 1; io_complete(process, HAL_IO_CMD(HAL_SDMMC, STORAGE_GET_MEDIA_DESCRIPTOR), core->sdmmc.user, io); error(ERROR_SYNC); }