📄 synth_intr.c
字号:
request[SYNTH_REQUEST_TXLEN_OFFSET + 1] = (txlen >> 8) & 0x0FF; request[SYNTH_REQUEST_TXLEN_OFFSET + 2] = (txlen >> 16) & 0x0FF; request[SYNTH_REQUEST_TXLEN_OFFSET + 3] = (txlen >> 24) & 0x0FF; request[SYNTH_REQUEST_RXLEN_OFFSET + 0] = (rxlen >> 0) & 0x0FF; request[SYNTH_REQUEST_RXLEN_OFFSET + 1] = (rxlen >> 8) & 0x0FF; request[SYNTH_REQUEST_RXLEN_OFFSET + 2] = (rxlen >> 16) & 0x0FF; request[SYNTH_REQUEST_RXLEN_OFFSET + 3] = ((rxlen >> 24) & 0x0FF) | (((int*)0 != result) ? 0x080 : 0); // sizeof(synth_auxiliary_request) < PIPE_BUF (4096) so a single write should be atomic, // subject only to incoming clock or SIGIO or child-related signals. do { rc = cyg_hal_sys_write(to_aux, (const void*) &request, SYNTH_REQUEST_LENGTH); } while (-CYG_HAL_SYS_EINTR == rc); // Is there any more data to be sent? if (0 < txlen) { int sent = 0; CYG_LOOP_INVARIANT(synth_auxiliary_running, "The auxiliary cannot just disappear"); while (sent < txlen) { rc = cyg_hal_sys_write(to_aux, (const void*) &(txdata[sent]), txlen - sent); if (-CYG_HAL_SYS_EINTR == rc) { continue; } else if (rc < 0) { diag_printf("Internal error: unexpected result %d when sending buffer to auxiliary.\n", rc); diag_printf(" : this application is exiting immediately.\n"); cyg_hal_sys_exit(1); } else { sent += rc; } } CYG_ASSERT(sent <= txlen, "Amount of data sent should not exceed requested size"); } // The auxiliary can now process this entire request. Is a reply expected? if ((int*)0 != result) { // The basic reply is also only a small number of bytes, so should be atomic. do { rc = cyg_hal_sys_read(from_aux, (void*) &reply, SYNTH_REPLY_LENGTH); } while (-CYG_HAL_SYS_EINTR == rc); if (rc <= 0) { if (rc < 0) { diag_printf("Internal error: unexpected result %d when receiving data from auxiliary.\n", rc); } else { diag_printf("Internal error: EOF detected on pipe from auxiliary.\n"); } diag_printf(" : this application is exiting immediately.\n"); cyg_hal_sys_exit(1); } CYG_ASSERT(SYNTH_REPLY_LENGTH == rc, "The correct amount of data should have been read"); // Replies are packed in Tcl and assumed to be two 32-bit // little-endian integers. *result = (reply[SYNTH_REPLY_RESULT_OFFSET + 3] << 24) | (reply[SYNTH_REPLY_RESULT_OFFSET + 2] << 16) | (reply[SYNTH_REPLY_RESULT_OFFSET + 1] << 8) | (reply[SYNTH_REPLY_RESULT_OFFSET + 0] << 0); reply_rxlen = (reply[SYNTH_REPLY_RXLEN_OFFSET + 3] << 24) | (reply[SYNTH_REPLY_RXLEN_OFFSET + 2] << 16) | (reply[SYNTH_REPLY_RXLEN_OFFSET + 1] << 8) | (reply[SYNTH_REPLY_RXLEN_OFFSET + 0] << 0); CYG_ASSERT(reply_rxlen <= rxlen, "The auxiliary should not be sending more data than was requested."); if ((int*)0 != actual_rxlen) { *actual_rxlen = reply_rxlen; } if (reply_rxlen) { int received = 0; while (received < reply_rxlen) { rc = cyg_hal_sys_read(from_aux, (void*) &(rxdata[received]), reply_rxlen - received); if (-CYG_HAL_SYS_EINTR == rc) { continue; } else if (rc <= 0) { if (rc < 0) { diag_printf("Internal error: unexpected result %d when receiving data from auxiliary.\n", rc); } else { diag_printf("Internal error: EOF detected on pipe from auxiliary.\n"); } diag_printf(" : this application is exiting immediately.\n"); } else { received += rc; } } CYG_ASSERT(received == reply_rxlen, "Amount received should be exact"); } } } HAL_RESTORE_INTERRUPTS(old_isrstate);}// Instantiate a device. This takes arguments such as// devs/eth/synth/ecosynth, current, ethernet, eth0, and 200x100 If// the package and version are NULL strings then the device being// initialized is application-specific and does not belong to any// particular package.intsynth_auxiliary_instantiate(const char* pkg, const char* version, const char* devtype, const char* devinst, const char* devdata){ int result = -1; char buf[512 + 1]; const char* str; int index; CYG_ASSERT((const char*)0 != devtype, "Device instantiations must specify a valid device type"); CYG_ASSERT((((const char*)0 != pkg) && ((const char*)0 != version)) || \ (((const char*)0 == pkg) && ((const char*)0 == version)), "If a package is specified then the version must be supplied as well"); index = 0; str = pkg; if ((const char*)0 == str) { str = ""; } while ( (index < 512) && ('\0' != *str) ) { buf[index++] = *str++; } if (index < 512) buf[index++] = '\0'; str = version; if ((const char*)0 == str) { str = ""; } while ((index < 512) && ('\0' != *str) ) { buf[index++] = *str++; } if (index < 512) buf[index++] = '\0'; for (str = devtype; (index < 512) && ('\0' != *str); ) { buf[index++] = *str++; } if (index < 512) buf[index++] = '\0'; if ((const char*)0 != devinst) { for (str = devinst; (index < 512) && ('\0' != *str); ) { buf[index++] = *str++; } } if (index < 512) buf[index++] = '\0'; if ((const char*)0 != devdata) { for (str = devdata; (index < 512) && ('\0' != *str); ) { buf[index++] = *str++; } } if (index < 512) { buf[index++] = '\0'; } else { diag_printf("Internal error: buffer overflow constructing instantiate request for auxiliary.\n"); diag_printf(" : this application is exiting immediately.\n"); cyg_hal_sys_exit(1); } if (synth_auxiliary_running) { synth_auxiliary_xchgmsg(SYNTH_DEV_AUXILIARY, SYNTH_AUXREQ_INSTANTIATE, 0, 0, buf, index, &result, (unsigned char*) 0, (int *) 0, 0); } return result;}// ----------------------------------------------------------------------------// SIGPIPE and SIGCHLD are special, related to the auxiliary process.//// A SIGPIPE can only happen when the application is writing to the// auxiliary, which only happens inside synth_auxiliary_xchgmsg() (this// assumes that no other code is writing down a pipe, e.g. to interact// with a process other than the standard I/O auxiliary). Either the// auxiliary has explicitly closed the pipe, which it is not supposed// to do, or more likely it has exited. Either way, there is little// point in continuing - unless we already know that the system is// shutting down.static voidsynth_pipe_sighandler(int sig){ CYG_ASSERT(CYG_HAL_SYS_SIGPIPE == sig, "The right signal handler should be invoked"); if (synth_auxiliary_running) { synth_auxiliary_running = false; diag_printf("Internal error: communication with the I/O auxiliary has been lost.\n"); diag_printf(" : this application is exiting immediately.\n"); cyg_hal_sys_exit(1); }}// Similarly it is assumed that there will be no child processes other than// the auxiliary. Therefore a SIGCHLD indicates that the auxiliary has// terminated unexpectedly. This is bad: normal termination involves// the application exiting and the auxiliary terminating in response,// not the other way around.//// As a special case, if it is known that the auxiliary is not currently// usable then the signal is ignored. This copes with the situation where// the auxiliary has just been fork()'d but has failed to initialize, or// alternatively where the whole system is in the process of shutting down// cleanly and it happens that the auxiliary got there first.static voidsynth_chld_sighandler(int sig){ CYG_ASSERT(CYG_HAL_SYS_SIGCHLD == sig, "The right signal handler should be invoked"); if (synth_auxiliary_running) { synth_auxiliary_running = false; diag_printf("Internal error: the I/O auxiliary has terminated unexpectedly.\n"); diag_printf(" : this application is exiting immediately.\n"); cyg_hal_sys_exit(1); }}// ----------------------------------------------------------------------------// Initializationvoidsynth_hardware_init(void){ struct cyg_hal_sys_sigaction action; struct cyg_hal_sys_sigset_t blocked; int i; // Set up a sigprocmask to block all signals except the ones we // particularly want to handle. However do not block the tty // signals - the ability to ctrl-C a program is important. CYG_HAL_SYS_SIGFILLSET(&blocked); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGILL); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGBUS); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGFPE); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGSEGV); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGPIPE); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGCHLD); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGALRM); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGIO); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGHUP); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGINT); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGQUIT); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGTERM); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGCONT); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGSTOP); CYG_HAL_SYS_SIGDELSET(&blocked, CYG_HAL_SYS_SIGTSTP); if (0 != cyg_hal_sys_sigprocmask(CYG_HAL_SYS_SIG_SETMASK, &blocked, (cyg_hal_sys_sigset_t*) 0)) { CYG_FAIL("Failed to initialize sigprocmask"); } // Now set up the VSR and ISR statics synth_VSR = &synth_default_vsr; for (i = 0; i < CYGNUM_HAL_ISR_COUNT; i++) { synth_isr_handlers[i].isr = &synth_default_isr; synth_isr_handlers[i].data = (CYG_ADDRWORD) 0; synth_isr_handlers[i].obj = (CYG_ADDRESS) 0; synth_isr_handlers[i].pri = CYGNUM_HAL_ISR_COUNT; } // Install signal handlers for SIGIO and SIGALRM, the two signals // that may cause the VSR to run. SA_NODEFER is important: it // means that the current signal will not be blocked while the // signal handler is running. Combined with a mask of 0, it means // that the sigprocmask does not change when a signal handler is // invoked, giving eCos the flexibility to switch to other threads // instead of having the signal handler return immediately. action.hal_mask = 0; action.hal_flags = CYG_HAL_SYS_SA_NODEFER; action.hal_bogus = (void (*)(int)) 0; action.hal_handler = &synth_alrm_sighandler; if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGALRM, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGALRM"); } action.hal_handler = &synth_io_sighandler; if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGIO, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGIO"); } // Install handlers for the various exceptions. For now these also // operate with unchanged sigprocmasks, allowing nested // exceptions. It is not clear that this is entirely a good idea, // but in practice these exceptions will usually be handled by gdb // anyway. action.hal_handler = &synth_exception_sighandler; if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGILL, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGILL"); } if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGBUS, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGBUS"); } if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGFPE, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGFPE"); } if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGSEGV, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGSEGV"); } // Also cope with SIGCHLD and SIGPIPE. SIGCHLD indicates that the // auxiliary has terminated, which is a bad thing. SIGPIPE // indicates that a write to the auxiliary has terminated, but // the error condition was caught at a different stage. action.hal_handler = &synth_pipe_sighandler; if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGPIPE, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGPIPE"); } action.hal_handler = &synth_chld_sighandler; action.hal_flags |= CYG_HAL_SYS_SA_NOCLDSTOP | CYG_HAL_SYS_SA_NOCLDWAIT; if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGCHLD, &action, (struct cyg_hal_sys_sigaction*) 0)) { CYG_FAIL("Failed to install signal handler for SIGCHLD"); } // Start up the auxiliary process. synth_start_auxiliary(); // All done. At this stage interrupts are still disabled, no ISRs // have been installed, and the clock is not yet ticking. // Exceptions can come in and will be processed normally. SIGIO // and SIGALRM could come in, but nothing has yet been done // to make that happen.}// Second-stage hardware init. This is called after all C++ static// constructors have been run, which should mean that all device// drivers have been initialized and will have performed appropriate// interactions with the I/O auxiliary. There should now be a// message exchange with the auxiliary to let it know that there will// not be any more devices, allowing it to remove unwanted frames,// run the user's mainrc.tcl script, and so on. Also this is the// time that the various toplevels get mapped on to the display.//// This request blocks until the auxiliary is ready. The return value// indicates whether or not any errors occurred on the auxiliary side,// and that those errors have not been suppressed using --keep-goingvoidsynth_hardware_init2(void){ if (synth_auxiliary_running) { int result; synth_auxiliary_xchgmsg(SYNTH_DEV_AUXILIARY, SYNTH_AUXREQ_CONSTRUCTORS_DONE, 0, 0, (const unsigned char*) 0, 0, &result, (unsigned char*) 0, (int*) 0, 0); if ( !result ) { cyg_hal_sys_exit(1); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -