void A(void) { int num; int sender_pid; while (1) { msg* p = (msg*)request_memory_block(); uart1_put_string("Waiting for KCD\r\n"); p = (msg*)(receive_message(&sender_pid)); if (p->mtext[0] == '%' && p->mtext[1] == 'Z') { uart1_put_string("Received %Z from KCD\r\n"); release_memory_block(p); break; } else { release_memory_block(p); } } num = 0; while (1) { char b[8]; msg* p = (msg*)request_memory_block(); itoa(num, b); p->mtype = 3; p->mtext = b; send_message(6,p); uart1_put_string(b); uart1_put_string("Sent Message from A to B\r\n"); num++; release_processor(); } // note that Process A does not de-allocate // any received envelopes in the second loop }
/** * Prints five numbers and then releases a memory block */ void test_proc_p1_b_2(void) { int i = 0; int ret_val = 20; void* p_mem_blk; p_mem_blk = request_memory_block(); set_process_priority(PID_P2, MEDIUM); while ( 1) { if ( i != 0 && i % 5 == 0 ) { uart1_put_string("\n\r"); ret_val = release_memory_block(p_mem_blk); #ifdef DEBUG_0 printf("proc2: ret_val=%d\n", ret_val); #endif /* DEBUG_0 */ if ( ret_val == -1 ) { break; } } uart1_put_char('0' + i % 10); i++; } uart1_put_string("proc2: end of testing\n\r"); set_process_priority(PID_P2, LOWEST); while ( 1 ) { release_processor(); } }
/** * @brief: a process that prints 4x5 numbers */ void test_proc_p1_a_2(void) { int i = 0; int ret_val = 20; int counter = 0; while ( 1) { if ( i != 0 && i % 5 == 0 ) { uart1_put_string("\n\r"); counter++; if ( counter == 4 ) { ret_val = set_process_priority(PID_P1, HIGH); break; } else { ret_val = release_processor(); } #ifdef DEBUG_0 printf("proc2: ret_val=%d\n", ret_val); #endif /* DEBUG_0 */ } uart1_put_char('0' + i % 10); i++; } uart1_put_string("proc2 end of testing\n\r"); while ( 1 ) { release_processor(); } }
/** * @brief: c UART0 IRQ Handler */ void c_UART0_IRQHandler(void) { uint8_t IIR_IntId; // Interrupt ID from IIR LPC_UART_TypeDef *pUart = (LPC_UART_TypeDef *)LPC_UART0; #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 */ 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 g_buffer[12] = g_char_in; // nasty hack g_send_char = 1; } else if (IIR_IntId & IIR_THRE) { /* THRE Interrupt, transmit holding register becomes empty */ if (*gp_buffer != '\0' ) { g_char_out = *gp_buffer; #ifdef DEBUG_0 //uart1_put_string("Writing a char = "); //uart1_put_char(g_char_out); //uart1_put_string("\n\r"); // you could use the printf instead printf("Writing a char = %c \n\r", g_char_out); #endif // DEBUG_0 pUart->THR = g_char_out; gp_buffer++; } else { #ifdef DEBUG_0 uart1_put_string("Finish writing. Turning off IER_THRE\n\r"); #endif // DEBUG_0 pUart->IER ^= IER_THRE; // toggle the IER_THRE bit pUart->THR = '\0'; g_send_char = 0; gp_buffer = g_buffer; } } else { /* not implemented yet */ #ifdef DEBUG_0 uart1_put_string("Should not get here!\n\r"); #endif // DEBUG_0 return; } }
void k_rtx_init(void) { __disable_irq(); uart_irq_init(0); // uart0, interrupt-driven timer_init(0); // uart0, interrupt-driven uart1_init(); // uart1, polling memory_init(); process_init(); __enable_irq(); uart1_put_string("Type 'S' in COM0 terminal to switch between proc1 and proc2 or wait for them to switch between themselves\n\r"); uart1_put_string("An input other than 'S' in COM0 terminal will be have no effect.\n\r"); /* start the first process */ k_release_processor(); }
int main() { LPC_UART_TypeDef *pUart; SystemInit(); __disable_irq(); uart0_irq_init(); // uart0 interrupt driven, for RTX console uart1_init(); // uart1 polling, for debugging #ifdef DEBUG_0 init_printf(NULL, putc); #endif // DEBUG_0 __enable_irq(); uart1_put_string("COM1> Type a character at COM0 terminal\n\r"); pUart = (LPC_UART_TypeDef *) LPC_UART0; //while( 1 ) { if (g_send_char == 0) { /* Enable RBR, THRE is disabled */ pUart->IER = IER_RLS | IER_RBR; } else if (g_send_char == 1) { /* Enable THRE, RBR left as enabled */ pUart->IER = IER_THRE | IER_RLS | IER_RBR; } //} }
void test_proc_p1_a_3(void) { while (1) { uart1_put_string("proc3: \n\r"); release_processor(); } }
int k_delayed_send(int destination_proc_id, void *message_envelope, int delay) { msg_metadata *metadata = reserve_message_metadata(message_envelope); if (metadata == NULL) { return RTX_ERR; } if (message_envelope == NULL) { uart1_put_string("k_send_message is NULL. Bad!\n"); return RTX_ERR; } __disable_irq(); metadata->sender_pid = gp_current_process->pid; metadata->destination_pid = destination_proc_id; metadata->send_time = k_get_time() + delay; if (g_delayed_messages_count == (BLOCK_SIZE / sizeof(void *))) { // Overflow is... unlikely. ASSERT(0) } g_delayed_messages[g_delayed_messages_count++] = message_envelope; __enable_irq(); return RTX_OK; }
void proc6(void) { while(1) { uart1_put_string("proc6: \n\r"); release_processor(); } }
void B(void) { int sender_pid; while (1) { msg* p; p = (msg*)(receive_message(&sender_pid)); uart1_put_string("Sent Message from B to C\r\n"); send_message(7,p); release_processor(); } }
//TC 2: Blocked on receive & preemption void proc2(void) { MSG_BUF* envelope = 0; char* msg1 = "SE 350"; char* msg2 = "LAB"; envelope = (MSG_BUF*)request_memory_block(); strcpy(envelope->mtext, msg1); send_message(1, envelope); //TC 3: IPC envelope = (MSG_BUF*)request_memory_block(); strcpy(envelope->mtext, msg2); send_message(3, envelope); envelope = (MSG_BUF*)receive_message(NULL); if (strcmp(envelope->mtext, msg2) == 0) { prev_success = 1; } else { prev_success = 0; } release_memory_block(envelope); if (prev_success) { uart1_put_string("G003_test: test "); uart1_put_char(3 + 48); uart1_put_string(" OK\n\r"); pass = pass + 1; } else { uart1_put_string("G003_test: test "); uart1_put_char(3 + 48); uart1_put_string(" FAIL\n\r"); } set_process_priority(4, HIGH); while (1) { release_processor(); } }
void test_proc_p1_b_6(void) { int i = 0; while (1) { if ( i < 2 ) { uart1_put_string("proc6: \n\r"); } release_processor(); i++; } }
void proc5(void) { int i=0; while(1) { if ( i < 2 ) { uart1_put_string("proc5: \n\r"); } release_processor(); i++; } }
/** * @brief: c UART0 IRQ Handler */ void c_UART0_IRQHandler(void) { uint8_t IIR_IntId; // Interrupt ID from IIR uint8_t g_char_in; LPC_UART_TypeDef *pUart = (LPC_UART_TypeDef *)LPC_UART0; #ifdef DEBUG_1 uart1_put_string("Entering c_UART0_IRQHandler\n\r"); #endif // DEBUG_1 /* 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 */ g_char_in = pUart->RBR; //call iprocess hander for uart UART_IProcessHandler(g_char_in); } else if (IIR_IntId & IIR_THRE) { /* THRE Interrupt, transmit holding register becomes empty */ UART_IProcessHandler(NULL); #ifdef DEBUG_1 uart1_put_string("Finish writing. Turning off IER_THRE\n\r"); #endif // DEBUG_1 pUart->IER ^= IER_THRE; // toggle the IER_THRE bit //pUart->THR = '\0'; } else { /* not implemented yet */ #ifdef DEBUG_1 uart1_put_string("Should not get here!\n\r"); #endif // DEBUG_1 } }
/** * Prints five uppercase letters and request a memory block. */ void test_proc_p1_b_1(void) { int i = 0; void* p_mem_blk; while ( 1 ) { if ( i != 0 && i % 5 == 0 ) { uart1_put_string("\n\r"); p_mem_blk = request_memory_block(); #ifdef DEBUG_0 printf("proc1: p_mem_blk=0x%x\n", p_mem_blk); #endif /* DEBUG_0 */ } uart1_put_char('A' + i % 26); i++; } }
/** * @brief call back function for printf * NOTE: first paramter p is not used for now. */ void putc(void *p, char c) { if (p != NULL) { if (active_uart == 0) { uart0_put_string("putc: first parameter needs to be NULL"); } else { uart1_put_string("putc: first parameter needs to be NULL"); } } else { if (active_uart == 0) { uart0_put_char(c); } else { uart1_put_char(c); } } }
/** * @brief: a process that prints 5x6 numbers * and then yields the cpu. */ void proc2(void) { int i = 0; int ret_val = 20; int x = 0; while ( 1) { if ( i != 0 && i%5 == 0 ) { uart1_put_string("\n\r"); if ( i%30 == 0 ) { ret_val = release_processor(); #ifdef DEBUG_0 printf("proc2: ret_val=%d\n", ret_val); #endif /* DEBUG_0 */ } for ( x = 0; x < 500000; x++); // some artifical delay } uart1_put_char('0' + i%10); i++; } }
int k_send_message(int destination_proc_id, void *message_envelope) { PCB *receiving_proc; msg_metadata *metadata = reserve_message_metadata(message_envelope); if (metadata == NULL) { return RTX_ERR; } if (message_envelope == NULL) { uart1_put_string("k_send_message is NULL. Bad!\n"); return RTX_ERR; } __disable_irq(); metadata->sender_pid = gp_current_process->pid; metadata->destination_pid = destination_proc_id; receiving_proc = k_get_pcb_from_pid(destination_proc_id); list_push(&receiving_proc->msg_queue, message_envelope); if (receiving_proc->state == BLOCKED_ON_RECEIVE) { receiving_proc->state = READY; k_dequeue_process(destination_proc_id); k_enqueue_process(destination_proc_id); if (k_get_proc_table_from_pid(destination_proc_id)->m_priority < k_get_proc_table_from_pid(metadata->sender_pid)->m_priority) { __enable_irq(); k_release_processor(); __disable_irq(); } } __enable_irq(); return RTX_OK; }
void null_proc(void) { uart1_put_string("Running null process\n\r"); while(1) { release_processor(); } }
//TC 4: KCD and CRT void proc4(void) { MSG_BUF* msg = NULL; msg = (MSG_BUF*)request_memory_block(); msg->mtype = KCD_REG; msg->mtext[0] = '%'; msg->mtext[1] = 'T'; msg->mtext[2] = 'E'; msg->mtext[3] = 'S'; msg->mtext[4] = 'T'; msg->mtext[4] = '\0'; send_message(PID_KCD, msg); msg = (MSG_BUF*)request_memory_block(); msg->mtype = CRT_DISPLAY; strcpy(msg->mtext, "Input %TEST and press enter:\n\r"); send_message(PID_CRT, msg); msg = receive_message(NULL); if (strcmp(msg->mtext, "%TEST") == 0) { prev_success = 1; } else { prev_success = 0; } release_memory_block(msg); if (prev_success) { uart1_put_string("G003_test: test "); uart1_put_char(4 + 48); uart1_put_string(" OK\n\r"); pass = pass + 1; } else { uart1_put_string("G003_test: test "); uart1_put_char(4 + 48); uart1_put_string(" FAIL\n\r"); } uart1_put_string("G003_test: "); uart1_put_char(pass + 48); uart1_put_string("/"); uart1_put_char(total + 48); uart1_put_string(" tests OK\n\r"); uart1_put_string("G003_test: "); uart1_put_char((total - pass) + 48); uart1_put_string("/"); uart1_put_char(total + 48); uart1_put_string(" tests FAIL\n\r"); uart1_put_string("G003_test: END\n\r"); while (1) { release_processor(); } }
//TC 1: Delayed message sending & no preemption void proc1(void) { MSG_BUF* envelope = NULL; char* msg = "SE 350"; uart1_put_string("\n\r"); uart1_put_string("G003_test: START\n\r"); uart1_put_string("G003_test: total "); uart1_put_char(total + 48); uart1_put_string(" tests\n\r"); prev_pid = 1; envelope = (MSG_BUF*)request_memory_block(); strcpy(envelope->mtext, msg); delayed_send(1, envelope, 5000); envelope = (MSG_BUF*)receive_message(NULL); if (strcmp(envelope->mtext, msg) == 0) { prev_success = 1; } else { prev_success = 0; } release_memory_block(envelope); if (prev_success) { uart1_put_string("G003_test: test "); uart1_put_char(1 + 48); uart1_put_string(" OK\n\r"); pass = pass + 1; } else { uart1_put_string("G003_test: test "); uart1_put_char(1 + 48); uart1_put_string(" FAIL\n\r"); } //TC 2: Blocked on receive & preemption envelope = (MSG_BUF*)receive_message(NULL); prev_success = 1; // Checks if you ever get here. release_memory_block(envelope); if (prev_success) { uart1_put_string("G003_test: test "); uart1_put_char(2 + 48); uart1_put_string(" OK\n\r"); pass = pass + 1; } else { uart1_put_string("G003_test: test "); uart1_put_char(2 + 48); uart1_put_string(" FAIL\n\r"); } while (1) { release_processor(); } }
void proc5(void) { //END of TC 3d: all processes except proc5 are blocked if (prev_pid == 4 && prev_success) { uart1_put_string("G003_test: test "); uart1_put_char(3 + 48); uart1_put_string(" OK\n\r"); pass = pass + 1; } else { uart1_put_string("G003_test: test "); uart1_put_char(3 + 48); uart1_put_string(" FAIL\n\r"); } uart1_put_string("G003_test: "); uart1_put_char(pass + 48); uart1_put_string("/"); uart1_put_char(total + 48); uart1_put_string(" tests OK\n\r"); uart1_put_string("G003_test: "); uart1_put_char((total - pass) + 48); uart1_put_string("/"); uart1_put_char(total + 48); uart1_put_string(" tests FAIL\n\r"); uart1_put_string("G003_test: END\n\r"); while (1) { mem[index++] = request_memory_block(); } }
void proc6(void) { // TC 2a: change itself to be lower than the max: PASS if prev pid is 1 if (prev_pid != 1) { prev_success = 0; // At here, priority of the procs: // 1: LOW // 2, 3, 4, 5: LOWEST // 6: MEDIUM } //TC 2b: set itself to a higher one with currently being the higeest -> still itself prev_pid = 6; set_process_priority(6, HIGH); //TC 2b: set itself to a higher one with currently being the higeest -> still itself: PASS if prev_pid is 6 if (prev_pid != 6) { prev_success = 0; // At here, priority of the procs: // 1: LOW // 2, 3, 4, 5: LOWEST // 6: HIGH } //TC 2c: set itself to be the same as the currently highest other than itself -> switch to that highest prev_pid = 6; set_process_priority(6, LOW); // TC 2d: change a proc s.t. B=A to B>A, A is current if (prev_pid != 1) { prev_success = 0; // At here, priority of the procs: // 1: LOW // 2, 3, 4, 5: LOWEST // 6: HIGH } // TC 2e: change a proc s.t. B<A to B=A, A is current, then B should be run prev_pid = 6; set_process_priority(1, HIGH); // TC 2g: change a proc s.t. B<A to B>A, A is current, then jump to B if (prev_pid != 1) { prev_success = 0; // At here, priority of the procs: // 1: MEDIUM // 2, 3, 4, 5: LOWEST // 6: HIGH } // TC 2h: change itself to be the same priority of itself: no change prev_pid = 6; set_process_priority(6, HIGH); // Finish TC 2 if (prev_pid == 6 && prev_success) { uart1_put_string("G003_test: test "); uart1_put_char(2 + 48); uart1_put_string(" OK\n\r"); pass = pass + 1; } else { uart1_put_string("G003_test: test "); uart1_put_char(2 + 48); uart1_put_string(" FAIL\n\r"); } // END of TC 2 prev_success = 1; // Start of TC 3 // TC 3a: null process operations // 1: MEDIUM // 2, 3, 4, 5: LOWEST // 6: HIGH if (set_process_priority(0, LOW) != RTX_ERR) { prev_success = 0; } set_process_priority(1, LOW); set_process_priority(2, MEDIUM); // TC 3b: allocate all memory blocks, free one, return // 1: LOW // 2: MEDIUM // 3, 4, 5: LOWEST // 6: HIGH, will be blocked while (prev_pid == 6) { mem[index++] = request_memory_block(); } // proc 6 should be preempted and go to 2 // TC 3b: proc_6 is return from blocked queue to ready queue and is the highest priority process if (prev_pid != 2) { prev_success = 0; } prev_pid = 6; // TC 3c: with 2 procs at highest priority, block both procs, then release memory in another proc to return to proc_6 set_process_priority(3, HIGH); // jumps to proc_3 // 1: LOW // 2: MEDIUM // 3: HIGH, blocked // 4, 5: LOWEST // 6: HIGH, will be blocked prev_pid = 6; mem[index++] = request_memory_block(); // blocks proc_6, goes to proc_2 }
void proc1(void) { // Start of TC 1 //TC 1: allocation and deallocation void* test_blk1 = NULL; void* test_blk2 = NULL; int status1 = 1; int status2 = 1; uart1_put_string("\n\r"); uart1_put_string("G003_test: START\n\r"); uart1_put_string("G003_test: total "); uart1_put_char(total + 48); uart1_put_string(" tests\n\r"); test_blk1 = request_memory_block(); test_blk2 = request_memory_block(); if (test_blk1 == test_blk2 || test_blk1 == NULL || test_blk2 == NULL) { prev_success = 0; } status1 = release_memory_block(test_blk1); status2 = release_memory_block(test_blk2); if (status1 != 0 || status2 != 0) { prev_success = 0; } // End of TC 1 if (prev_success) { uart1_put_string("G003_test: test "); uart1_put_char(1 + 48); uart1_put_string(" OK\n\r"); pass = pass + 1; } else { uart1_put_string("G003_test: test "); uart1_put_char(1 + 48); uart1_put_string(" FAIL\n\r"); } prev_success = 1; // Start of TC 2 // TC 2a: change itself to be lower than the max prev_pid = 1; set_process_priority(1, LOW); // set_process_priority(1, HIGH); if (prev_pid != 6) { prev_success = 0; } // At here, priority of the procs: // 1: LOW // 2, 3, 4, 5: LOWEST // 6: LOW // TC 2d: change a proc s.t. B=A to B>A, A is current prev_pid = 1; set_process_priority(6, HIGH); // should go to 6 // TC 2e: change a proc s.t. B<A to B=A, A is current, then B should be run if (prev_pid != 6) { prev_success = 0; } // At here, priority of the procs: // 1: HIGH // 2, 3, 4, 5: LOWEST // 6: HIGH // TC 2f: change a proc s.t. B=A to B<A, A is current, then still A prev_pid = 1; set_process_priority(6, LOW); // TC 2f: change a proc s.t. B=A to B<A, A is current, then still A if (prev_pid != 1) { prev_success = 0; } // At here, priority of the procs: // 1: HIGH // 2, 3, 4, 5: LOWEST // 6: LOW // TC 2g: change a proc s.t. B<A to B>A, A is current, then jump to B // First, change itself to be MEDIUM set_process_priority(1, MEDIUM); if (prev_pid != 1) { prev_success = 0; } prev_pid = 1; // Then, change 6 to HIGH set_process_priority(6, HIGH); // If TC 2 ever reaches here, TC 2 fails if (prev_pid == 1) { uart1_put_string("G003_test: test "); uart1_put_char(2 + 48); uart1_put_string(" FAIL\n\r"); } // TC 3d: Block everything and preempt to null process after starvation if (prev_pid != 3) { prev_success = 0; } // 1: MEDIUM // 2: LOW // 3: HIGH, blocked // 4, 5: LOWEST // 6: HIGH, blocked prev_pid = 1; mem[index++] = request_memory_block(); }
/** * @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 print_debug(char* message) { #ifdef DEBUG_0 uart1_put_string(message); #endif }