Exemplo n.º 1
0
/**
 * @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();
}
/*
 * This function is called by the assembly STUB function
 */
void uart_handler() {
	
	// Disable all interupts
	atomic_up();
	
	#ifdef _IO_DEBUG
		rtx_dbug_outs((CHAR *) "Enter: uart_handler\r\n");
		rtx_dbug_outs((CHAR *) "Reading data...\r\n");
	#endif

	// irene said this should be enough - would be
	// very rare if it wasn't ready to read
	while (!(SERIAL1_UCSR & 1)) { }
	
	char_in = SERIAL1_RD;

	#ifdef _IO_DEBUG
		rtx_dbug_outs((CHAR *) "Determining what to do with char...\r\n");
	#endif

	struct io_message * msg;

	switch(char_in) {
		#ifdef _HOTKEYS_DEBUG
			case '!':
				rtx_dbug_outs((CHAR *) "'!' hotkey detected...\r\n");
				print_queues();	// print processes on ready queue and priorities
				break;
			case '@':
				rtx_dbug_outs((CHAR *) "'@' hotkey detected...\r\n");
				print_mem_blocked();	// print processes on memory blocked queue and priorities
				break;
			case '#':
				rtx_dbug_outs((CHAR *) "'#' hotkey detected...\r\n");
				print_msg_blocked();	// print processes on message blocked queue and priorities
				break;
			case '$':
				rtx_dbug_outs((CHAR *) "'$' hotkey detected...\r\n");
				print_availible_mem_queue();	// print available memory queue
				break;
			case '^':
				rtx_dbug_outs((CHAR *) "'^' hotkey detected...\r\n");
				print_used_mem_queue();	// print used memory queue
				break;
			case '&':
				rtx_dbug_outs((CHAR *) "'&' hotkey detected...\r\n");		
				output_kcd_buffer();	// print kcd buffer
				break;
			case '*':
				rtx_dbug_outs((CHAR *) "'*' hotkey detected...\r\n");
				print_cmds();	// print valid commands
				break;
		#endif
		
		default:
			#ifdef _IO_DEBUG
				rtx_dbug_outs((CHAR *) "Sending message to KCD proc...\r\n");
			#endif
			
			if (!are_blocks_available()) {
				atomic_down();
				return;
			}

			msg = (io_message *)request_memory_block();
			
			// reset tx/rx and send it to kcd
			msg->tx = UART_PID;
			msg->rx = KCD_PID;
			msg->msg[0] = char_in;
			send_message(KCD_PID, msg);
			break;
	}
	
	// Enable all interupts
	atomic_down();
}