Rev 113 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
#include "maindefs.h"#include "interrupts.h"#include "msg_queues.h"#include <delays.h>#include <string.h>// The key to making this code safe for interrupts is that// each queue is filled by only one writer and read by one reader.// ToMainQueueFromLow: Writer is a low priority interrupt, Reader is main()// ToMainQueueFromHigh: Writer is a high priority interrupt, Reader is main()// FromMainQueueToLow: Writer is main(), Reader is a low priority interrupt// FromMainQueueToHigh: Writer is main(), Reader is a high priority interrupt#pragma udata msgqueue1_1unsigned char MQ_ToMainFromLow_Data_1[MSGLEN];#pragma udata msgqueue1_2unsigned char MQ_ToMainFromLow_Data_2[MSGLEN];#pragma udata msgqueue2_1unsigned char MQ_ToMainFromHigh_Data_1[MSGLEN];#pragma udata msgqueue2_2unsigned char MQ_ToMainFromHigh_Data_2[MSGLEN];#pragma udata msgqueue3_1unsigned char MQ_FromMainToLow_Data_1[MSGLEN];#pragma udata msgqueue3_2unsigned char MQ_FromMainToLow_Data_2[MSGLEN];#pragma udata msgqueue4_1unsigned char MQ_FromMainToHigh_Data_1[MSGLEN];#pragma udata msgqueue4_2unsigned char MQ_FromMainToHigh_Data_2[MSGLEN];#pragma udatamsg_queue MQ_ToMainFromLow;msg_queue MQ_ToMainFromHigh;msg_queue MQ_FromMainToLow;msg_queue MQ_FromMainToHigh;unsigned char MQ_Main_Willing_To_Block;void MQ_init_queue(msg_queue *qptr) {unsigned char i;qptr->cur_write_index = 0;qptr->cur_read_index = 0;for (i=0;i<MSGQUEUELEN;i++) {qptr->queue[i].full = 0;}}void MQ_init() {MQ_Main_Willing_To_Block = 0;MQ_ToMainFromLow.queue[0].data = MQ_ToMainFromLow_Data_1;MQ_ToMainFromLow.queue[1].data = MQ_ToMainFromLow_Data_2;MQ_ToMainFromHigh.queue[0].data = MQ_ToMainFromHigh_Data_1;MQ_ToMainFromHigh.queue[1].data = MQ_ToMainFromHigh_Data_2;MQ_FromMainToLow.queue[0].data = MQ_FromMainToLow_Data_1;MQ_FromMainToLow.queue[1].data = MQ_FromMainToLow_Data_2;MQ_FromMainToHigh.queue[0].data = MQ_FromMainToHigh_Data_1;MQ_FromMainToHigh.queue[1].data = MQ_FromMainToHigh_Data_2;MQ_init_queue(&MQ_ToMainFromLow);MQ_init_queue(&MQ_ToMainFromHigh);MQ_init_queue(&MQ_FromMainToLow);MQ_init_queue(&MQ_FromMainToHigh);}signed int MQ_send_msg(msg_queue *qptr,unsigned char length,unsigned char msgtype, void *data) {unsigned char slot;msg *qmsg;size_t tlength = length;#ifdef DEBUGif (length > MSGLEN) {return(MSG_BAD_LEN);} else if (length < 0) {return(MSG_BAD_LEN);}#endif// Get the index in the msg queue to write toslot = qptr->cur_write_index;// Retrieve the address of the slot in the queue to write toqmsg = &qptr->queue[slot];// If the slot isn't empty, then we should returnif (qmsg->full != 0) {return(MSG_QUEUE_FULL);}// Otherwise fill in the message detailsqmsg->length = length;qmsg->msgtype = msgtype;// Copy the message itselfmemcpy(qmsg->data,data,tlength);// Increment the next location in the queue to write to// Note: the index will loop back to the start (implements a FIFO queue)qptr->cur_write_index = (qptr->cur_write_index + 1) % MSGQUEUELEN;// Mark the slot in the queue as filled and returnqmsg->full = 1;return(MSG_SEND_OKAY);}signed int MQ_recv_msg(msg_queue *qptr, unsigned char maxlength, unsigned char *msgtype, void *data) {unsigned char slot;msg *qmsg;size_t tlength;// Get the index in the message queue to read fromslot = qptr->cur_read_index;// Retrieve the address of the message in the queue to read fromqmsg = &qptr->queue[slot];// If the retrieved message contains data..if (qmsg->full == 1) {// Check if the recieving buffer can hold the message dataif (qmsg->length > maxlength) {return(MSG_BUFFER_TOOSMALL);}// Get the length of the message datatlength = qmsg->length;// Copy the message data into *datamemcpy(data,(const void*)qmsg->data,tlength);// Increment the read index to the next message to be readqptr->cur_read_index = (qptr->cur_read_index + 1) % MSGQUEUELEN;// Copy the message type to the returned message(*msgtype) = qmsg->msgtype;// Mark the slot in the queue as emptyqmsg->full = 0;// Return the size of the message returnedreturn (tlength);// Slot does not contain any messages} else {return(MSG_QUEUE_EMPTY);}}unsigned char MQ_peek_msg(msg_queue *qptr) {unsigned char slot;msg *qmsg;// Get the index in the message queue to read fromslot = qptr->cur_read_index;// Retrieve the address of the message in the queue to read fromqmsg = &qptr->queue[slot];if (qmsg->full == 1) {// Return the message type of the first message in queuereturn qmsg->msgtype;} else {// If there are no messages in the queue, return 0return 0;}}// Check if there is an unread message in the queueunsigned char MQ_check_msg_queue_unread(msg_queue *qptr) {return (qptr->queue[qptr->cur_read_index].full);}void MQ_enter_sleep_mode(void) {OSCCONbits.IDLEN = 1; // set to idle on sleep_asmsleep_endasm}/* Message Queue 1 - Low Interrupt -> Main */signed int MQ_sendmsg_ToMainFromLow(unsigned char length, unsigned char msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_low_interrupt_routine()) {return (MSG_NOT_IN_LOW);}#endifreturn (MQ_send_msg(&MQ_ToMainFromLow, length, msgtype, data));}signed int MQ_recvmsg_ToMainFromLow(unsigned char maxlength, unsigned char *msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_main_routine()) {return (MSG_NOT_IN_MAIN);}#endifreturn (MQ_recv_msg(&MQ_ToMainFromLow, maxlength, msgtype, data));}unsigned int MQ_peek_ToMainFromLow() {return (MQ_peek_msg(&MQ_ToMainFromLow));}/* Message Queue 2 - High Interrupt -> Main */signed int MQ_sendmsg_ToMainFromHigh(unsigned char length, unsigned char msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_high_interrupt_routine()) {return (MSG_NOT_IN_HIGH);}#endifreturn (MQ_send_msg(&MQ_ToMainFromHigh, length, msgtype, data));}signed int MQ_recvmsg_ToMainFromHigh(unsigned char maxlength, unsigned char *msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_main_routine()) {return (MSG_NOT_IN_MAIN);}#endifreturn (MQ_recv_msg(&MQ_ToMainFromHigh, maxlength, msgtype, data));}unsigned int MQ_peek_ToMainFromHigh() {return (MQ_peek_msg(&MQ_ToMainFromHigh));}/* Message Queue 3 - Main -> Low Interrupt */signed int MQ_sendmsg_FromMainToLow(unsigned char length, unsigned char msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_main_routine()) {return (MSG_NOT_IN_MAIN);}#endifreturn (MQ_send_msg(&MQ_FromMainToLow, length, msgtype, data));}signed int MQ_recvmsg_FromMainToLow(unsigned char maxlength, unsigned char *msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_low_interrupt_routine()) {return (MSG_NOT_IN_LOW);}#endifreturn (MQ_recv_msg(&MQ_FromMainToLow, maxlength, msgtype, data));}unsigned int MQ_peek_FromMainToLow() {return (MQ_peek_msg(&MQ_FromMainToLow));}/* Message Queue 4 - Main -> High Interrupt */signed int MQ_sendmsg_FromMainToHigh(unsigned char length, unsigned char msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_main_routine()) {return (MSG_NOT_IN_MAIN);}#endifreturn (MQ_send_msg(&MQ_FromMainToHigh, length, msgtype, data));}signed int MQ_recvmsg_FromMainToHigh(unsigned char maxlength, unsigned char *msgtype, void *data) {#ifdef DEBUGif (!interrupt_in_high_interrupt_routine()) {return (MSG_NOT_IN_HIGH);}#endifreturn (MQ_recv_msg(&MQ_FromMainToHigh, maxlength, msgtype, data));}unsigned int MQ_peek_FromMainToHigh() {return (MQ_peek_msg(&MQ_FromMainToHigh));}// This should only be called from a High Priority Interruptvoid MQ_sleep_high_interrupt_if_okay() {// Check to see if main is willing to blockif (MQ_Main_Willing_To_Block == 0) {return;}// Dont sleep if currently handling low interruptif (interrupt_in_low_interrupt_routine()) {return;}// Check to make sure that we're in high interruptif (!interrupt_in_high_interrupt_routine()) {return;}// Since we are the only thing executing that could be// putting something into a message queue destined for main()// we can safely check the message queues now// Check the message queues to make sure that they're emptyif (MQ_check_msg_queue_unread(&MQ_ToMainFromHigh)) {return;}if (MQ_check_msg_queue_unread(&MQ_ToMainFromLow)) {return;}// If everything checks out, go to sleepMQ_enter_sleep_mode();}/* Called from main(), blocks until message recieved in queue to main */void MQ_wait_on_incoming_msg_queues() {// Only run from the main functionif (!interrupt_in_main_routine()) {return;}MQ_Main_Willing_To_Block = 1;while (1) {// If any incoming message queues are not empty, break out of waitif (MQ_check_msg_queue_unread(&MQ_ToMainFromHigh)) {MQ_Main_Willing_To_Block = 0;return;}if (MQ_check_msg_queue_unread(&MQ_ToMainFromLow)) {MQ_Main_Willing_To_Block = 0;return;}// Sleep for a period of time before checking againDelay1KTCYx(10);}}