static void loras_timer_poll_timeout(LORA* lora) { int last_error; #if (LORA_DEBUG) uint32_t duration_ms; ++lora->polls_cnt; #endif if (lora->status != LORA_STATUS_TRANSFER_IN_PROGRESS) { loras_fatal(lora); #if (LORA_DEBUG) printf("[loras] [fatal error] unexpected status %d => server closed\n", lora->status); #endif return; } (lora->tx ? loras_hw_tx_async_wait : loras_hw_rx_async_wait)(lora); last_error = get_last_error(); #if (LORA_DEBUG) //check for internal unexpected errors (ex. ERROR_INVALID_STATE -- chip is in invalid state) if (!(last_error >= ERROR_OK || last_error == ERROR_TIMEOUT)) { loras_fatal(lora); printf("[loras] [fatal error] unexpected error %d => server closed\n", last_error); return; } #endif switch (lora->status) { case LORA_STATUS_TRANSFER_IN_PROGRESS: timer_start_ms(lora->timer_poll_timeout, LORA_POLL_TIMEOUT_MS); //note: do not check if last_error == ERROR_OK (should be) ipc_post_inline(lora->process, HAL_CMD(HAL_LORA, LORA_TRANSFER_IN_PROGRESS), 0, 0, last_error); break; case LORA_STATUS_TRANSFER_COMPLETED: timer_stop(lora->timer_txrx_timeout, 0, HAL_LORA); #if (LORA_DEBUG) duration_ms = loras_get_uptime_ms() - lora->transfer_in_progress_ms; printf("[loras] [info] poll completed duration_ms:%u polls_cnt:%u\n", duration_ms, lora->polls_cnt); #endif ipc_post_inline(lora->process, HAL_CMD(HAL_LORA, LORA_TRANSFER_COMPLETED), 0, 0, last_error); break; default: error(ERROR_NOT_SUPPORTED); break; } }
static inline void lpc_usb_suspend(CORE* core) { IPC ipc; ipc.process = core->usb.device; ipc.cmd = HAL_CMD(HAL_USB, USB_SUSPEND); ipc.param1 = USB_HANDLE_DEVICE; ipc_ipost(&ipc); }
static inline void lpc_usb_wakeup(CORE* core) { IPC ipc; ipc.process = core->usb.device; ipc.cmd = HAL_CMD(HAL_USB, USB_WAKEUP); ipc.param1 = USB_HANDLE_DEVICE; ipc_ipost(&ipc); }
static inline void usb_suspend(EXO* exo) { IPC ipc; OTG_FS_GENERAL->INTMSK &= ~OTG_FS_GENERAL_INTMSK_USBSUSPM; ipc.process = exo->usb.device; ipc.param1 = USB_HANDLE_DEVICE; ipc.cmd = HAL_CMD(HAL_USB, USB_SUSPEND); ipc_ipost(&ipc); }
static inline void usb_wakeup(EXO* exo) { IPC ipc; OTG_FS_GENERAL->INTMSK |= OTG_FS_GENERAL_INTMSK_USBSUSPM; ipc.process = exo->usb.device; ipc.param1 = USB_HANDLE_DEVICE; ipc.cmd = HAL_CMD(HAL_USB, USB_WAKEUP); ipc_ipost(&ipc); }
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 inline void lpc_usb_setup(CORE* core) { IPC ipc; ipc.process = core->usb.device; ipc.cmd = HAL_CMD(HAL_USB, USB_SETUP); ipc.param1 = 0; ipc.param2 = *((uint32_t*)(USB_SETUP_BUF_BASE)); ipc.param3 = *((uint32_t*)(USB_SETUP_BUF_BASE + 4)); ipc_ipost(&ipc); }
void ksystime_soft_timer_timeout(void* param) { SOFT_TIMER* timer = (SOFT_TIMER*)param; IPC ipc; ipc.process = timer->owner; ipc.cmd = HAL_CMD(timer->hal, IPC_TIMEOUT); ipc.param1 = timer->param; ipc.param2 = (unsigned int)timer; kipc_post(KERNEL_HANDLE, &ipc); }
static inline void usb_enumdne(EXO* exo) { OTG_FS_GENERAL->INTMSK |= OTG_FS_GENERAL_INTMSK_USBSUSPM; IPC ipc; ipc.process = exo->usb.device; ipc.param1 = USB_HANDLE_DEVICE; ipc.param2 = stm32_otg_get_speed(exo); ipc.cmd = HAL_CMD(HAL_USB, USB_RESET); ipc_ipost(&ipc); }
static inline int hidd_kbd_set_report(USBD* usbd, HIDD_KBD* hidd, IO* io, unsigned int length) { uint8_t* report = io_data(io); #if (USBD_HID_DEBUG_REQUESTS) printf("HIDD KBD: set LEDs %#X\n", report[0]); #endif if (hidd->kbd.leds != report[0]) usbd_post_user(usbd, hidd->iface, 0, HAL_CMD(HAL_USBD_IFACE, USB_HID_KBD_LEDS_STATE_CHANGED), report[0], 0); hidd->kbd.leds = report[0]; return 0; }
static inline void lpc_usb_reset(CORE* core) { //enable device LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DEV_EN; IPC ipc; ipc.process = core->usb.device; ipc.cmd = HAL_CMD(HAL_USB, USB_RESET); ipc.param1 = USB_HANDLE_DEVICE; ipc.param2 = lpc_usb_get_speed(core); ipc_ipost(&ipc); }
static void lpc_eth_conn_check(EXO* exo) { ETH_CONN_TYPE new_conn; new_conn = eth_phy_get_conn_status(exo->eth.phy_addr); if (new_conn != exo->eth.conn) { exo->eth.conn = new_conn; exo->eth.connected = ((exo->eth.conn != ETH_NO_LINK) && (exo->eth.conn != ETH_REMOTE_FAULT)); kexo_post(exo->eth.tcpip, HAL_CMD(HAL_ETH, ETH_NOTIFY_LINK_CHANGED), exo->eth.phy_addr, exo->eth.conn, 0); if (exo->eth.connected) { //set speed and duplex switch (exo->eth.conn) { case ETH_10_HALF: LPC_ETHERNET->MAC_CONFIG &= ~(ETHERNET_MAC_CONFIG_DM_Msk | ETHERNET_MAC_CONFIG_FES_Msk); break; case ETH_10_FULL: LPC_ETHERNET->MAC_CONFIG &= ~ETHERNET_MAC_CONFIG_FES_Msk; LPC_ETHERNET->MAC_CONFIG |= ETHERNET_MAC_CONFIG_DM_Msk; break; case ETH_100_HALF: LPC_ETHERNET->MAC_CONFIG &= ~ETHERNET_MAC_CONFIG_DM_Msk; LPC_ETHERNET->MAC_CONFIG |= ETHERNET_MAC_CONFIG_FES_Msk; break; case ETH_100_FULL: LPC_ETHERNET->MAC_CONFIG |= ETHERNET_MAC_CONFIG_DM_Msk | ETHERNET_MAC_CONFIG_FES_Msk; break; default: break; } //Looks like some timeout is required after connection mode is changed to setup state machin //in other case there is chance it will hang #ifdef EXODRIVERS exodriver_delay_us(1 * 1000); #else sleep_ms(1); #endif //EXODRIVERS //enable RX/TX, PAD/CRC strip LPC_ETHERNET->MAC_CONFIG |= ETHERNET_MAC_CONFIG_RE_Msk | ETHERNET_MAC_CONFIG_TE_Msk | ETHERNET_MAC_CONFIG_ACS_Msk; LPC_ETHERNET->DMA_OP_MODE |= ETHERNET_DMA_OP_MODE_SR_Msk | ETHERNET_DMA_OP_MODE_ST_Msk; } else { lpc_eth_flush(exo); LPC_ETHERNET->DMA_OP_MODE &= ~(ETHERNET_DMA_OP_MODE_SR_Msk | ETHERNET_DMA_OP_MODE_ST_Msk); LPC_ETHERNET->MAC_CONFIG &= ~(ETHERNET_MAC_CONFIG_RE_Msk | ETHERNET_MAC_CONFIG_TE_Msk | ETHERNET_MAC_CONFIG_ACS_Msk); } } ksystime_soft_timer_start_ms(exo->eth.timer, 1000); }
static void udps_flush(TCPIPS* tcpips, HANDLE handle) { IO* io; UDP_HANDLE* uh; int err; uh = so_get(&tcpips->udps.handles, handle); if (uh == NULL) return; err = ERROR_IO_CANCELLED; #if (ICMP) if (uh->err != ERROR_OK) err = uh->err; #endif //ICMP while ((io = udps_peek_head(tcpips, uh)) != NULL) io_complete_ex(uh->process, HAL_CMD(HAL_UDP, IPC_READ), handle, io, err); }
//------------------------------------------------------------------------ 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; }
static void loras_timer_txrx_timeout(LORA* lora) { if (lora->status != LORA_STATUS_TRANSFER_IN_PROGRESS) { loras_fatal(lora); #if (LORA_DEBUG) printf("[loras] [fatal error] unexpected status %d => server closed\n", lora->status); #endif return; } #if (LORA_DEBUG) printf("[loras] [info] timer_txrx_timeout expired -> transfer completed\n"); #endif timer_stop(lora->timer_poll_timeout, 0, HAL_LORA); if (lora->tx || !LORA_CONTINUOUS_RECEPTION_ON) loras_hw_sleep(lora); #if (LORA_DO_ERROR_COUNTING) lora->tx ? ++lora->stats_tx.timeout_num : ++lora->stats_rx.timeout_num; #endif lora->status = LORA_STATUS_TRANSFER_COMPLETED; ipc_post_inline(lora->process, HAL_CMD(HAL_LORA, LORA_TRANSFER_COMPLETED), 0, 0, ERROR_TIMEOUT); }
void gpio_disable_pin(unsigned int pin) { ipc_post_exo(HAL_CMD(HAL_GPIO, IPC_GPIO_DISABLE_PIN), pin, 0, 0); }
static inline void hidd_kbd_write_complete(USBD* usbd, HIDD_KBD* hidd) { usbd_post_user(usbd, hidd->iface, 0, HAL_CMD(HAL_USBD_IFACE, hidd->state), 0, 0); hidd->state = USB_HID_KBD_IDLE; }
void power_set_mode(POWER_MODE mode) { ipc_post_exo(HAL_CMD(HAL_POWER, POWER_SET_MODE), mode, 0, 0); }
static void icmps_echo_complete(TCPIPS* tcpips, int err) { ipc_post_inline(tcpips->icmps.process, HAL_CMD(HAL_ICMP, ICMP_PING), tcpips->icmps.echo_ip.u32.ip, err == ERROR_OK ? 0 : INVALID_HANDLE, err); tcpips->icmps.process = INVALID_HANDLE; }
void gpio_reset_pin(unsigned int pin) { ipc_post_exo(HAL_CMD(HAL_GPIO, IPC_GPIO_RESET_PIN), pin, 0, 0); }
void gpio_enable_pin(unsigned int pin, GPIO_MODE mode) { ipc_post_exo(HAL_CMD(HAL_GPIO, IPC_GPIO_ENABLE_PIN), pin, mode, 0); }
void gpio_set_data_in(unsigned int port, unsigned int mask) { ipc_post_exo(HAL_CMD(HAL_GPIO, IPC_GPIO_SET_DATA_IN), port, mask, 0); }
void gpio_reset_mask(unsigned int port, unsigned int mask) { ipc_post_exo(HAL_CMD(HAL_GPIO, IPC_GPIO_RESET_MASK), port, mask, 0); }
void lpc_usb_on_isr(int vector, void* param) { int i; CORE* core = (SHARED_USB_DRV*)param; uint32_t sta = LPC_USB->INTSTAT; EP* ep; #if (USB_DEBUG_ERRORS) IPC ipc; switch (LPC_USB->INFO & USB_INFO_ERR_CODE_MASK) { case USB_INFO_ERR_CODE_NO_ERROR: case USB_INFO_ERR_CODE_IONAK: //no error break; default: ipc.process = process_iget_current(); ipc.cmd = HAL_CMD(HAL_USB, LPC_USB_ERROR); ipc.param1 = USB_HANDLE_DEVICE; ipc.param2 = (LPC_USB->INFO & USB_INFO_ERR_CODE_MASK) >> USB_INFO_ERR_CODE_POS; ipc_ipost(&ipc); LPC_USB->INFO &= ~USB_INFO_ERR_CODE_MASK; } #endif if (sta & USB_INTSTAT_DEV_INT) { sta = LPC_USB->DEVCMDSTAT; //Don't care on connection change, just clear pending bit if (sta & USB_DEVCMDSTAT_DCON_C) LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DCON_C; if (sta & USB_DEVCMDSTAT_DSUS_C) { if (sta & USB_DEVCMDSTAT_DSUS) lpc_usb_suspend(core); else lpc_usb_wakeup(core); LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DSUS_C; } if (sta & USB_DEVCMDSTAT_DRES_C) { lpc_usb_reset(core); LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DRES_C; } LPC_USB->INTSTAT = USB_INTSTAT_DEV_INT; return; } if ((sta & USB_INTSTAT_EP0OUT) && (LPC_USB->DEVCMDSTAT & USB_DEVCMDSTAT_SETUP)) { lpc_usb_setup(core); LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_SETUP; LPC_USB->INTSTAT = USB_INTSTAT_EP0OUT; return; } for (i = 0; i < USB_EP_COUNT_MAX; ++i) { if (sta & USB_EP_INT_BIT(i)) { ep = core->usb.out[i]; if (ep && ep->io_active) lpc_usb_out(core, i); LPC_USB->INTSTAT = USB_EP_INT_BIT(i); } if (sta & USB_EP_INT_BIT(USB_EP_IN | i)) { ep = core->usb.in[i]; if (ep && ep->io_active) lpc_usb_in(core, i | USB_EP_IN); LPC_USB->INTSTAT = USB_EP_INT_BIT(USB_EP_IN | i); } } }
static inline void lpc_sdmmc_io(CORE* core, HANDLE process, HANDLE user, IO* io, unsigned int size, bool read) { SHA1_CTX sha1; unsigned int count; STORAGE_STACK* stack = io_stack(io); io_pop(io, sizeof(STORAGE_STACK)); if (!core->sdmmc.active) { error(ERROR_NOT_CONFIGURED); return; } if (core->sdmmc.state != SDMMC_STATE_IDLE) { error(ERROR_IN_PROGRESS); return; } if ((user != core->sdmmc.user) || (size == 0)) { error(ERROR_INVALID_PARAMS); return; } //erase if (!read && ((stack->flags & STORAGE_MASK_MODE) == 0)) { sdmmcs_erase(&core->sdmmc.sdmmcs, stack->sector, size); return; } if (size % core->sdmmc.sdmmcs.sector_size) { error(ERROR_INVALID_PARAMS); return; } count = size / core->sdmmc.sdmmcs.sector_size; core->sdmmc.total = size; if (core->sdmmc.total > LPC_SDMMC_TOTAL_SIZE) { error(ERROR_INVALID_PARAMS); return; } if ((core->sdmmc.activity != INVALID_HANDLE) && !(stack->flags & STORAGE_FLAG_IGNORE_ACTIVITY_ON_REQUEST)) { ipc_post_inline(core->sdmmc.activity, HAL_CMD(HAL_SDMMC, STORAGE_NOTIFY_ACTIVITY), core->sdmmc.user, read ? 0 : STORAGE_FLAG_WRITE, 0); core->sdmmc.activity = INVALID_HANDLE; } core->sdmmc.io = io; core->sdmmc.process = process; lpc_sdmmc_prepare_descriptors(core); if (read) { io->data_size = 0; core->sdmmc.state = SDMMC_STATE_READ; if (sdmmcs_read(&core->sdmmc.sdmmcs, stack->sector, count)) error(ERROR_SYNC); } else { switch (stack->flags & STORAGE_MASK_MODE) { case STORAGE_FLAG_WRITE: core->sdmmc.state = SDMMC_STATE_WRITE; if (sdmmcs_write(&core->sdmmc.sdmmcs, stack->sector, count)) error(ERROR_SYNC); break; default: //verify/verify write sha1_init(&sha1); sha1_update(&sha1, io_data(io), core->sdmmc.total); sha1_final(&sha1, core->sdmmc.hash); core->sdmmc.sector = stack->sector; switch (stack->flags & STORAGE_MASK_MODE) { case STORAGE_FLAG_VERIFY: core->sdmmc.state = SDMMC_STATE_VERIFY; if (sdmmcs_read(&core->sdmmc.sdmmcs, stack->sector, count)) error(ERROR_SYNC); break; case (STORAGE_FLAG_VERIFY | STORAGE_FLAG_WRITE): core->sdmmc.state = SDMMC_STATE_WRITE_VERIFY; if (sdmmcs_write(&core->sdmmc.sdmmcs, stack->sector, count)) error(ERROR_SYNC); break; default: error(ERROR_NOT_SUPPORTED); return; } } } }