// Sends a message to the process int k_send_message (uint32_t pid, void *message) { MessageEnvelope *menv = (MessageEnvelope *)k_request_memory_block(); if (message == 0) return; menv->sender_id = (current_process())->m_pid; // Field 1: Sender menv->receiver_id = pid; // Field 2: Receiver menv->message_type = 0; // Field 3: Message Type menv->message = message; // Field 4: Message enqueue_envelope(pid, menv); if ((get_process(pid))->m_state == MSG_BLOCKED) move_to_ready(pid); }
void uart_i_proc(void) { uint8_t IIR_IntId; // Interrupt ID from IIR LPC_UART_TypeDef *pUart = (LPC_UART_TypeDef *)LPC_UART0; ENVELOPE* msg; __disable_irq(); uart_asm_preemption_flag = 0; /* Reading IIR automatically acknowledges the interrupt */ IIR_IntId = (pUart->IIR) >> 1 ; // skip pending bit in IIR if (IIR_IntId & IIR_RDA) { // Receive Data Available /* read UART. Read RBR will clear the interrupt */ g_char_in = pUart->RBR; // Avoid interuption by only sending when mem blocks are avaliable // Sends input to crt display if (mem_empty() == 0) { int display_size; char display_msg[3]; if (g_char_in == '\r') { display_size = 3; display_msg[0] = '\n'; display_msg[1] = g_char_in; display_msg[2] = '\0'; } else { display_size = 2; display_msg[0] = g_char_in; display_msg[1] = '\0'; } msg = (ENVELOPE*) k_request_memory_block(); msg->sender_pid = UART_IPROC_PID; msg->destination_pid = CRT_PID; msg->nextMsg = NULL; msg->message_type = MSG_CRT_DISPLAY; msg->delay = 0; set_message(msg, display_msg, display_size*sizeof(char)); k_send_message(CRT_PID, msg); uart_asm_preemption_flag = 1; } #ifdef DEBUG_HOTKEYS if (g_char_in == DEBUG_HOTKEY_1) k_print_ready_queue(); else if (g_char_in == DEBUG_HOTKEY_2) k_print_blocked_on_memory_queue(); else if (g_char_in == DEBUG_HOTKEY_3) k_print_blocked_on_receive_queue(); #endif if (g_char_in != '\r') // Any char not an enter { #ifdef DEBUG_HOTKEYS if ((g_char_in != DEBUG_HOTKEY_1)&&(g_char_in != DEBUG_HOTKEY_2)&&(g_char_in != DEBUG_HOTKEY_3)) { g_input_buffer[g_input_buffer_index] = g_char_in; g_input_buffer_index++; } #else g_input_buffer[g_input_buffer_index] = g_char_in; g_input_buffer_index++; #endif } else // Enter is pressed { g_input_buffer[g_input_buffer_index] = '\0'; g_input_buffer_index++; // Avoid interuption by only sending when mem blocks are avaliable if (mem_empty() == 0) { msg = (ENVELOPE*) k_request_memory_block(); msg->sender_pid = UART_IPROC_PID; msg->destination_pid = KCD_PID; msg->nextMsg = NULL; msg->message_type = MSG_CONSOLE_INPUT; msg->delay = 0; set_message(msg, g_input_buffer, g_input_buffer_index*sizeof(char)); k_send_message(KCD_PID, msg); g_input_buffer_index = 0; uart_asm_preemption_flag = 1; } } g_input_buffer[g_input_buffer_index] = g_char_in; } else if (IIR_IntId & IIR_THRE) { char* g_input; if (g_curr_p == NULL) g_curr_p = (ENVELOPE*) k_non_block_receive_message(UART_IPROC_PID); if (g_curr_p != NULL) { g_input = (char*) g_curr_p->message; if (g_input[g_char_out_index] != '\0') { // print normal char pUart->THR = g_input[g_char_out_index]; g_char_out_index++; } else { // done printing if (gp_pcb_nodes[UART_IPROC_PID]->p_pcb->env_q.head == NULL) pUart->IER &= (~IER_THRE); pUart->THR = g_input[g_char_out_index]; k_non_block_release_memory_block(g_curr_p); g_curr_p = NULL; g_char_out_index = 0; } } } __enable_irq(); }
/** * @brief: c UART0 IRQ Handler */ void uart_iprocess(void) { uint8_t IIR_IntId; // Interrupt ID from IIR LPC_UART_TypeDef *pUart = (LPC_UART_TypeDef *)LPC_UART0; __disable_irq(); #ifdef DEBUG_0 //uart1_put_string("Entering c_UART0_IRQHandler\n\r"); #endif // DEBUG_0 /* Reading IIR automatically acknowledges the interrupt */ IIR_IntId = (pUart->IIR) >> 1 ; // skip pending bit in IIR if (IIR_IntId & IIR_RDA) { // Receive Data Avaialbe /* read UART. Read RBR will clear the interrupt */ // Perform a 'context switch' PCB *old_proc = gp_current_process; gp_current_process = k_get_process(PID_UART_IPROC); g_char_in = pUart->RBR; #ifdef DEBUG_0 uart1_put_string("Reading a char = "); uart1_put_char(g_char_in); uart1_put_string("\n\r"); #endif // DEBUG_0 // process the character. If it is a hotkey, call the corresponding function // If we are reading, fall through to default and add to the command buffer switch (g_char_in) { case '\r': case '\n': if (g_is_reading) { // We've finished reading a command, send it to the KCD process MSG_BUF *message; g_is_reading = 0; strcpy("\n\r", (char *)(g_in_buffer + g_in_index)); if (is_memory_available()) { message = k_request_memory_block(); message->mtype = DEFAULT; strcpy((char *)g_in_buffer, message->mtext); k_send_message(PID_KCD, message); } g_in_index = 0; } break; case '%': if (!g_is_reading) { // Start reading a command g_is_reading = 1; g_in_index = 1; g_in_buffer[0] = '%'; break; } #if defined(DEBUG_0) && defined(_DEBUG_HOTKEYS) case READY_Q_COMMAND: if (!g_is_reading) { print_ready(); break; } case MEMORY_Q_COMMAND: if (!g_is_reading) { print_mem_blocked(); break; } case RECEIVE_Q_COMMAND: if (!g_is_reading) { print_receive_blocked(); break; } case MESSAGE_COMMAND: if (!g_is_reading) { print_messages(); break; } #endif /* DEBUG HOTKEYS */ default: if (g_is_reading) { // TODO: check bounds g_in_buffer[g_in_index++] = g_char_in; } } gp_current_process = old_proc; } else if (IIR_IntId & IIR_THRE) { /* THRE Interrupt, transmit holding register becomes empty */ // Check for messages and load the buffer // Perform a 'context switch' to the i-process MSG_BUF *message; PCB *old_proc = gp_current_process; gp_current_process = k_get_process(PID_UART_IPROC); // Don't block waiting for a message while (is_message(PID_UART_IPROC)) { int sender = PID_CRT; char *c; // Receive message and copy it to the buffer message = k_receive_message(&sender); c = message->mtext; //dprintf("Copying message to buffer: %s\n\r", message->mtext); if (*c != '\0') { do { g_out_buffer[g_out_end] = *c; g_out_end = (g_out_end + 1) % OUTPUT_BUFF_SIZE; c++; } while (g_out_end != g_out_start && *c != '\0'); } k_release_memory_block(message); } // Check if there is something in the circular buffer if (g_out_start != g_out_end) { g_char_out = g_out_buffer[g_out_start]; pUart->THR = g_char_out; g_out_start = (g_out_start + 1) % OUTPUT_BUFF_SIZE; } else { // nothing to print, disable the THRE interrupt pUart->IER ^= IER_THRE; // toggle (disable) the IER_THRE bit } gp_current_process = old_proc; } else { /* not implemented yet */ #ifdef DEBUG_0 //uart1_put_string("Should not get here!\n\r"); #endif // DEBUG_0 __enable_irq(); return; } __enable_irq(); }
void execute_uart() { char c; /* IER - Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential UART interrupts. IIR - Interrupt ID Register. Identifies which interrupt(s) are pending. LSR - Line Status Register. Contains flags for transmit and receive status, including line errors. */ // Information about the interrupt uint8_t IIR_IntId; // Interrupt ID from IIR // Line Status Register value uint8_t LSR_Val; // LSR Value uint8_t dummy = dummy; // dummy variable to clear interrupt upon LSR error LPC_UART_TypeDef * pUart = (LPC_UART_TypeDef *)LPC_UART0; // Reading IIR automatically acknowledges the interrupt IIR_IntId = (pUart->IIR) >> 1 ; // skip pending bit in IIR if (IIR_IntId & IIR_Receive_Data_Available) { // Receive Data Available Envelope * message = 0; int hot_key_exec = 0; // Note: read RBR will clear the interrupt c = pUart->RBR; // read from the uart buffer[0] = c; i++; buffer[1] = 0; hot_key_exec = do_hot_key(*buffer); if (hot_key_exec == 0) { /* If we have space, parse and echo the buffer contents Sending the messages takes 2 blocks so we need at least that many */ if(numberOfMemoryBlocksCurrentlyAllocated < MAX_ALLOWED_MEMORY_BLOCKS -1){ message = k_request_memory_block(); message->sender_pid = get_uart_pcb()->processId; message->receiver_pid = get_kcd_pcb()->processId; message->message_type = KEYBOARD_INPUT; set_message_bytes(message, buffer, 2); k_send_message(message->receiver_pid, message); }else{ // Otherwise just use polling since we have no choice uart0_polling_put_string(buffer); uart0_polling_put_string("Insufficient memory: Unable to pass message to KCD.\r\n"); } } } else if (IIR_IntId & IIR_THR_Empty) { // THRE Interrupt, transmit holding register empty LSR_Val = pUart->LSR; if(LSR_Val & LSR_THR_Empty) { g_UART0_TX_empty = 1; // UART is ready to transmit } else { g_UART0_TX_empty = 0; // UART is not ready to transmit yet } } else if (IIR_IntId & IIR_Receive_Line_Status) { LSR_Val = pUart->LSR; if (LSR_Val & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) ) { // There are errors or break interrupt // Read LSR will clear the interrupt dummy = pUart->RBR; //Dummy read on RX to clear interrupt, then bail out return ; // error occurs, return } // If no error on RLS, normal ready, save into the data buffer. // Note: read RBR will clear the interrupt if (LSR_Val & LSR_Unread_Character) { // Receive Data Ready g_UART0_buffer[g_UART0_count++] = pUart->RBR; // read from the uart if ( g_UART0_count == BUFSIZE ) { g_UART0_count = 0; // buffer overflow } } } else { // IIR_CTI and reserved combination are not implemented yet return; } }