Multidrop mode in MQX on 52259

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Multidrop mode in MQX on 52259

1,791 Views
ARQuattr
Contributor IV

I'm trying to implement 9-bit multidrop mode UART under MQX.  I'm wondering what the best way to do this would be.

Can/should I modify the MCF_UARTx_UMR1, MCF_UARTx_UCR registers directly as needed ?  Or should I be trying to adjust the UART init_struct (MCF52XX_UART_SERIAL_INIT_STRUCT)?  Or is there some other better way?   Is MQX able to handle the multidrop bit for me?

I'm able to achieve the result I'm looking for by directly accessing the MCF_... registers, and the required code is minimal so I'm satisfied with this solution, but I guess I'm just concerned that doing it like this will confilct in some way with MQX.

Thanks for your input,
Angelo

PS. Sorry I'm reposting this - I posted in the Coldfire forum but I realized it should probably be in the MQX forum.

0 Kudos
7 Replies

721 Views
PetrM
Senior Contributor I

Sorry, this feature is not currently implemented.

The better way than direct register access is to modify IO_IOCTL_SERIAL_SET_PARITY command in the driver code and use it with new "MULTIDROP" parameter.

 

PetrM

 

0 Kudos

721 Views
big_al
Contributor I

PetrM,

 

 I'm a H/W type, can you explain it more detail? Trying to run a Multidrop RS-485 on the MCF52259 using MQX and could use some direction....

 

Big Al

0 Kudos

721 Views
PetrM
Senior Contributor I

You should add something like this in serial driver (serl_pol_mcf52xx.c):

 

_mcf52xx_uart_serial_polled_ioctl():

 

      case IO_IOCTL_SERIAL_SET_PARITY:
         tmp = io_info_ptr->INIT.UMR1_VALUE & ~MCF52XX_UART_UMR1_MD_ADDRESS;
         switch (*param_ptr) {
            case IO_SERIAL_PARITY_NONE:
               tmp |= MCF52XX_UART_UMR1_NO_PARITY;
               break;
            case IO_SERIAL_PARITY_ODD:
               tmp |= MCF52XX_UART_UMR1_ODD_PARITY;
               break;
            case IO_SERIAL_PARITY_EVEN:
               tmp |= MCF52XX_UART_UMR1_EVEN_PARITY;
               break;
            case IO_SERIAL_PARITY_MARK:
               tmp |= MCF52XX_UART_UMR1_HI_PARITY;
               break;
            case IO_SERIAL_PARITY_SPACE:
               tmp |= MCF52XX_UART_UMR1_LOW_PARITY;
               break;
            case IO_SERIAL_PARITY_MULTI_DATA:
               tmp |= MCF52XX_UART_UMR1_MULTI_DROP;
               break;
            case IO_SERIAL_PARITY_MULTI_ADDRESS:
               tmp |= MCF52XX_UART_UMR1_MD_ADDRESS;
               break;
            default:
               return MQX_INVALID_PARAMETER;
         }
         io_info_ptr->INIT.UMR1_VALUE = tmp;
         uart_ptr->WRITE.UCR = MCF52XX_UART_UCR_RESET_POINTER;
         uart_ptr->WRITE.UMR = io_info_ptr->INIT.UMR1_VALUE;
         uart_ptr->WRITE.UMR = io_info_ptr->INIT.UMR2_VALUE;
         break;

 

      case IO_IOCTL_SERIAL_SET_HW_SIGNAL:  /* Assert */
         if (*param_ptr & IO_SERIAL_RTS) {
            if (io_info_ptr->INIT.UMR1_VALUE & MCF52XX_UART_UMR1_RXRTS) {
               return MQX_IO_OPERATION_NOT_AVAILABLE;
            }
            io_info_ptr->CONTROL_BITS |= MCF52XX_UART_UOP_RTS;
         }
         else {
            return MQX_INVALID_PARAMETER;
         }
         uart_ptr->WRITE.UOP1 = MCF52XX_UART_UOP_RTS;
         break;


      case IO_IOCTL_SERIAL_CLEAR_HW_SIGNAL:  /* Negate */
         if (*param_ptr & IO_SERIAL_RTS) {
            if (io_info_ptr->INIT.UMR1_VALUE & MCF52XX_UART_UMR1_RXRTS) {
               return MQX_IO_OPERATION_NOT_AVAILABLE;
            }
            io_info_ptr->CONTROL_BITS &= ~MCF52XX_UART_UOP_RTS;
         }
         else {
            return MQX_INVALID_PARAMETER;
         }
         uart_ptr->WRITE.UOP0 = MCF52XX_UART_UOP_RTS;
         break;

 

 

... and define the new/missing macros in serial.h.

You can use IO_IOCTL_SERIAL_SET_PARITY to set proper multidrop mode, IO_IOCTL_SERIAL_SET_HW_SIGNAL and IO_IOCTL_SERIAL_CLEAR_HW_SIGNAL with parameter IO_SERIAL_RTS to control the 485 direction via RTS line. Enable the signal in BSP gpio_init.c:

 

_bsp_serial_io_init():

 

 reg_ptr->GPIO.PUAPAR |= MCF5225_GPIO_PUAPAR_TXD0 | MCF5225_GPIO_PUAPAR_RXD0 | MCF5225_GPIO_PUAPAR_RTS0;

 

 

PetrM

 

0 Kudos

721 Views
ARQuattr
Contributor IV

PetrM,

  Sorry for the late response - I didn't realize there was any activity on the thread until now (I must have negelected to enable the notifications for the message).

 

  Also, thank you for your replies.  I haven't tried implementing the code you provided yet, but I reviewed it carefully and it seems to be doing what I have (below).  The code produces address bytes most of the time, however often they come out as data bytes (parity type bit 0).  I have tried with both polled and interrupt drivers, with similar results.  Do you see any problems with what I've done? 

 

 

//Sends first byte of message as address, and remaining bytes as data.
//Automatically calculates checksum and appends it to the packet (as data).
void MDB_send_msg (FILE_PTR fh_ptr, char *msg, uint_8 len) {
 uint_8 i;
 char chk_sum = 0;
 uint_8 init_UMR;

 printf ("MDB_send_msg, len: %d, msg: ", len);

 for (i=0; i<len; i++) {
  printf ("0x%02X ", msg[i]);
  chk_sum += msg[i];  //accumulate checksum
 }
 printf ("\n");

 //First byte is address parity type
 MCF_UART1_UCR = MCF_UART_UCR_RESET_MR; //reset the internal pointer to UMR1
 init_UMR = MCF_UART1_UMR & ~MCF_UART_UMR_PM_MULTI_ADDR; //get the current value and clear the Parity Type (PT) and Parity Mode (PM) bits
 MCF_UART1_UCR = MCF_UART_UCR_RESET_MR; //reset the internal pointer to UMR1
 MCF_UART1_UMR = init_UMR | MCF_UART_UMR_PM_MULTI_ADDR; //set mode to multidrop for address character
 write(fh_ptr,msg,1);   //send address/command

 //Remaining bytes are all data parity type
 MCF_UART1_UCR = MCF_UART_UCR_RESET_MR; //reset the internal pointer to UMR1
 init_UMR = MCF_UART1_UMR & ~MCF_UART_UMR_PM_MULTI_ADDR; //get the current value and clear the Parity Type (PT) and Parity Mode (PM) bits
 MCF_UART1_UCR = MCF_UART_UCR_RESET_MR; //reset the internal pointer to UMR1
 MCF_UART1_UMR = init_UMR | MCF_UART_UMR_PM_MULTI_DATA; //set mode to multidrop for data character

 if (len > 1) {
  msg++;           //increment msg pointer
  write(fh_ptr,msg,len-1); //send data bytes
 }

 write(fh_ptr,&chk_sum,1);  //send checksum
}

 

 

  I also wanted to ask about the code you sent, regarding this line:

 

tmp = io_info_ptr->INIT.UMR1_VALUE & ~MCF52XX_UART_UMR1_MD_ADDRESS;

 

 

  Is it guaranteed that the UMR pointer will already be reset at this point?  I wasn't sure so I have it resetting every time it changes the parity type.

 

 

  My second problem comes when I try to receive.  I'm trying to check the received parity type using the code below ( if (MCF_UART1_USR & MCF_UART_USR_PE) ), but it always returns as data type, even when the data coming in is address type.

 

 

//Returns received message up to first address byte, and length including checksum byte.//If no address byte is received within timeout, return false.  Message buffer and length will contain message received up to point of timeout.uint_8 MDB_read_msg (FILE_PTR fh_ptr, char *msg, uint_8 *len, TIME_STRUCT timeout) { TIME_STRUCT StartTime, CurrentTime, TimeDifference; char c; printf ("MDB_read_msg: "); _time_get(&StartTime);  //Get start time  *len = 0;  do {  if (fstatus(fh_ptr)) {   c = fgetc(fh_ptr);   if (c==IO_ERROR)    break;   *msg = c;   msg++;   len++;      printf ("0x%02X ", c);      //all messages from MDB peripherals must end with an address byte   if (MCF_UART1_USR & MCF_UART_USR_PE) {    printf ("\n");    return TRUE;
                        }  }    _time_get(&CurrentTime);   _time_diff(&StartTime, &CurrentTime, &TimeDifference); } while((TimeDifference.SECONDS >= timeout.SECONDS) &&   
                (TimeDifference.MILLISECONDS >= timeout.MILLISECONDS)); printf ("timed out\n"); return FALSE;}

 

Thanks again for your help,

Angelo

 

0 Kudos

721 Views
ARQuattr
Contributor IV

PetrM,

Update:
1. I tried to implement the code you provided (only the IO_IOCTL_SERIAL_SET_PARITY case since I'm not doing h/w flow control) and I added the two new cases to the serial.h file.  I rebuilt the bsp and application but it doesn't seem to be having any effect.  I'm not sure the changes are being included in the build.  I'm having trouble debugging in CW10, but I tried to set an I/O pin within the case and it doesn't change.  Do I need to build any other projects aside from the bsp?

2. I'm wondering if the mode that the port was opened with is related to the product.  I was originally using IO_SERIAL_XON_XOFF.  I also tried IO_SERIAL_RAW_IO and it had a similar problem, but seemed worse (fewer address bytes came out as data).  I tried some various other combinations, some of which didn't even allow the port to be opened.

 

Thanks,

Angelo

0 Kudos

721 Views
ARQuattr
Contributor IV

I figured out the issue with transmitting - I was changing the parity type to data immediately after writing the address byte, and it was apparently affecting the previous write.  I'm now checking the TXRDY bit in the USR before changing the parity type and it works fine.

 

I still haven't got it working with the changes in serl_pol_mcf52xx.c however, but I'll write the registers directly until I figure that out.

0 Kudos

721 Views
big_al
Contributor I

Thanks PetrM, I'll give it a shot...

0 Kudos