void thinkos_cond_hook(void) { int32_t * arg = (int32_t *)cm3_sp_get(); unsigned int ret = arg[0]; unsigned int mwq = arg[1]; unsigned int mutex; uint32_t lr = cm3_lr_get(); int self = thinkos_rt.active; int th = self; mutex = mwq - THINKOS_MUTEX_BASE; (void)lr; (void)ret; (void)mwq; (void)mutex; DCC_LOG3(LOG_TRACE, "<%d> mutex=%d lr=0x%08x...", th, mwq, lr); for(;;); if (thinkos_rt.lock[mutex] == -1) { thinkos_rt.lock[mutex] = th; DCC_LOG2(LOG_TRACE, "<%d> mutex %d locked", th, mwq); return; } /* insert into the mutex wait queue */ __thinkos_wq_insert(mwq, th); DCC_LOG2(LOG_TRACE , "<%d> waiting on mutex %d...", th, mwq); }
/* Receive a file and write it into the flash using the YMODEM preotocol */ int dmon_ymodem_flash(struct dmon_comm * comm, uint32_t addr, unsigned int size) { /* FIXME: generalize the application load by removing the low level flash calls dependency */ #ifdef STM32_FLASH_MEM /* The YMODEM state machine is allocated at the top of the stack, make sure there is no app running before calling the dmon_ymodem_flash()! */ struct ymodem_rcv * ry = ((struct ymodem_rcv *)&_stack) - 1; uint32_t base = (uint32_t)STM32_FLASH_MEM; uint32_t offs = addr - base; int ret; DCC_LOG2(LOG_INFO, "sp=%p ry=%p", cm3_sp_get(), ry); DCC_LOG2(LOG_INFO, "offs=0x%08x size=%d", offs, size); dmon_ymodem_rcv_init(ry, true, false); ry->fsize = size; DCC_LOG(LOG_INFO, "Starting..."); while ((ret = dmon_ymodem_rcv_pkt(comm, ry)) >= 0) { if ((ret == 0) && (ry->xmodem) ) break; int len = ret; if (ry->pktno == 1) { char * cp; int fsize; cp = (char *)ry->pkt.data; DCC_LOGSTR(LOG_INFO, "fname='%s'", cp); while (*cp != '\0') cp++; /* skip null */ cp++; fsize = dec2int(cp); if (fsize == 0) { ret = 0; break; } DCC_LOG1(LOG_INFO, "fsize='%d'", fsize); ry->fsize = fsize; DCC_LOG(LOG_INFO, "YMODEM first packet..."); } else { if (ry->pktno == 2) { stm32_flash_erase(offs, ry->fsize); } stm32_flash_write(offs, ry->pkt.data, len); offs += len; } } return ret; #else return -1; #endif }
void __attribute__((noreturn)) usb_xflash(uint32_t offs, uint32_t len) { uint32_t * xflash_code = __data_start; int (* xflash_ram)(uint32_t, uint32_t) = ((void *)xflash_code) + 1; DCC_LOG3(LOG_TRACE, "sp=%08x offs=%08x len=%d", cm3_sp_get(), offs, len); cm3_cpsid_i(); memcpy(xflash_code, usb_xflash_pic, sizeof_usb_xflash_pic); xflash_ram(offs, len); cm3_sysrst(); }
static int db_json_parse(struct fs_file * json, struct db_cfg * db) { struct microjs_json_parser jsn; uint8_t tok_buf[JSON_TOK_BUF_MAX]; const char * text = (const char *)json->data; unsigned int len = json->size; int ret; DCC_LOG(LOG_INFO, "1. JSON tokenizer."); microjs_json_init(&jsn, tok_buf, JSON_TOK_BUF_MAX, db_label); if ((ret = microjs_json_open(&jsn, text, len)) < 0) { DCC_LOG(LOG_ERROR, "microjs_json_open() failed!"); return ret; } DCC_LOG(LOG_INFO, "5. parsing JSON."); /* skip to the object oppening to allow object by object parsing */ microjs_json_flush(&jsn); /* parse the JASON file with the microjs tokenizer */ while ((ret = microjs_json_scan(&jsn)) == MICROJS_OK) { /* decode the token stream */ if ((ret = microjs_json_parse_obj(&jsn, db_desc, db)) < 0) { DCC_LOG(LOG_ERROR, "microjs_json_parse_obj() failed!"); return ret; } microjs_json_flush(&jsn); } if (ret != MICROJS_EMPTY_STACK) { DCC_LOG(LOG_ERROR, "microjs_json_scan() failed!"); return -1; } DCC_LOG2(LOG_INFO, "6. done, root=0x%08x sp=0x%08x.", db->root, cm3_sp_get()); return 0; }
void __attribute__((noreturn)) monitor_task(struct dmon_comm * comm) { struct monitor monitor; uint32_t sigmask = 0; uint32_t sigset; #if THINKOS_ENABLE_CONSOLE uint8_t * ptr; int cnt; #endif int tick_cnt = 0; uint8_t buf[1]; monitor.comm = comm; #if (MONITOR_THREADINFO_ENABLE) monitor.thread_id = -1; #endif #if (MONITOR_DUMPMEM_ENABLE) monitor.memdump.addr = this_board.application.start_addr; monitor.memdump.size = this_board.application.block_size; #endif DCC_LOG1(LOG_TRACE, "Monitor sp=%08x ...", cm3_sp_get()); #if (THINKOS_ENABLE_EXCEPTIONS) sigmask |= (1 << DBGMON_THREAD_FAULT); sigmask |= (1 << DBGMON_EXCEPT); #endif sigmask |= (1 << DBGMON_COMM_RCV); #if THINKOS_ENABLE_CONSOLE sigmask |= (1 << DBGMON_COMM_CTL); sigmask |= (1 << DBGMON_TX_PIPE); sigmask |= (1 << DBGMON_RX_PIPE); #endif sigmask |= (1 << DBGMON_SOFTRST); #if (MONITOR_WATCHPOINT_ENABLE) sigmask |= (1 << DBGMON_BREAKPOINT); #endif if (!__thinkos_active()) { DCC_LOG1(LOG_TRACE, "first call...", cm3_sp_get()); /* first time we run the monitor, start a timer to call the board_tick() periodically */ sigmask |= (1 << DBGMON_ALARM); dbgmon_alarm(125); } for(;;) { sigset = dbgmon_select(sigmask); DCC_LOG1(LOG_MSG, "sigset=%08x", sigset); if (sigset & (1 << DBGMON_SOFTRST)) { DCC_LOG(LOG_TRACE, "Soft reset."); this_board.softreset(); dbgmon_clear(DBGMON_SOFTRST); } #if THINKOS_ENABLE_CONSOLE if (sigset & (1 << DBGMON_COMM_CTL)) { DCC_LOG(LOG_MSG, "Comm Ctl."); dbgmon_clear(DBGMON_COMM_CTL); } #endif #if (THINKOS_ENABLE_EXCEPTIONS) if (sigset & (1 << DBGMON_THREAD_FAULT)) { DCC_LOG(LOG_TRACE, "Thread fault."); monitor_on_fault(comm); dbgmon_clear(DBGMON_THREAD_FAULT); } if (sigset & (1 << DBGMON_EXCEPT)) { DCC_LOG(LOG_TRACE, "System exception."); monitor_on_fault(comm); dbgmon_clear(DBGMON_EXCEPT); } #endif #if (MONITOR_WATCHPOINT_ENABLE) if (sigset & (1 << DBGMON_BREAKPOINT)) { monitor_on_bkpt(&monitor); dbgmon_clear(DBGMON_BREAKPOINT); } #endif if (sigset & (1 << DBGMON_COMM_RCV)) { #if THINKOS_ENABLE_CONSOLE /* receive from the COMM driver one bye at the time */ if (dmon_comm_recv(comm, buf, 1) > 0) { int c = buf[0]; /* process the input character */ if (!monitor_process_input(&monitor, c)) { /* if the character was not consumed by the monitor insert into the console pipe */ /* get a pointer to the head of the pipe. __console_rx_pipe_ptr() will return the number of consecutive spaces in the buffer. We need only one. */ if (__console_rx_pipe_ptr(&ptr) > 0) { /* copy the character into the RX fifo */ ptr[0] = c; /* commit the fifo head */ __console_rx_pipe_commit(1); } } } #else if (dmon_comm_recv(comm, buf, 1) > 0) { /* process the input character */ monitor_process_input(&monitor, buf[0]); } #endif } #if THINKOS_ENABLE_CONSOLE if (sigset & (1 << DBGMON_RX_PIPE)) { if ((cnt = __console_rx_pipe_ptr(&ptr)) > 0) { DCC_LOG1(LOG_TRACE, "RX Pipe. rx_pipe.free=%d. " "Unmaksing DBGMON_COMM_RCV!", cnt); sigmask |= (1 << DBGMON_COMM_RCV); } else { DCC_LOG(LOG_TRACE, "RX Pipe empty!!!"); } dbgmon_clear(DBGMON_RX_PIPE); } if (sigset & (1 << DBGMON_TX_PIPE)) { DCC_LOG(LOG_MSG, "TX Pipe."); if ((cnt = __console_tx_pipe_ptr(&ptr)) > 0) { DCC_LOG1(LOG_INFO, "TX Pipe, %d pending chars.", cnt); cnt = dmon_comm_send(comm, ptr, cnt); __console_tx_pipe_commit(cnt); } else { DCC_LOG(LOG_INFO, "TX Pipe empty!!!"); dbgmon_clear(DBGMON_TX_PIPE); } } #endif if (sigset & (1 << DBGMON_ALARM)) { dbgmon_clear(DBGMON_ALARM); if (this_board.autoboot(tick_cnt++) && dmon_app_exec(this_board.application.start_addr, false)) { sigmask &= ~(1 << DBGMON_ALARM); this_board.on_appload(); } else { /* reastart the alarm timer */ dbgmon_alarm(125); } } } }
void __attribute__((naked)) gdb_bootstrap(struct dmon_comm * comm) { DCC_LOG1(LOG_TRACE, "sp=0x%08x", cm3_sp_get()); gdb_stub_task(comm); dbgmon_exec(monitor_task); }