Reading UART Rx count register on Mesa 5i25/6i25

  • sirop
  • sirop's Avatar Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
22 Jan 2016 15:10 - 22 Jan 2016 17:02 #68927 by sirop
Hallo.

I am trying to work with UART on Mesa 5i25/6i25.

My datagrams - to be sent from a gyro - would have a size of about 60 bytes.
I calculated that I'll have to work with at least 57.600 bit/s or rather 115.200 bit/s
in order to receive 100 datagrams per second with the usual overhead.

The Rx FIFO is only 16 bytes, so reading the Rx FIFO in time might get an issue,
if one does not want to loose any incoming data

That's why I looked at UART RX FIFO count register and RX MODE/STATUS Register
as defined in freeby.mesanet.com/regmap .

As both registers are mentioned in github.com/LinuxCNC/linuxcnc/blob/master.../hostmot2.h#L803-822 , I guess that I can use them with 5i25/6i25, can't I?

It seems that reading the Rx FIFO count register would be as simple as
i = hm2_get_uart(&hm2, name);
inst = &hm2->uart.instance[i];
hm2->llio->read(hm2->llio, inst->rx_fifo_count_addr, &buff, sizeof(rtapi_u32));
Guess it is similar for RX MODE/STATUS Register .

So if I can read RX FIFO count register,
then I would know how many new bytes already arrived since the last time the UART RX FIFO count register was cleared/written to?

I wonder why RX FIFO count register is not cleared/written to at the end of int hm2_uart_read(char *name, unsigned char data[]),
so that the 16 byte deep Rx FIFO register is cleared thus but this may be a matter of taste.

My queations are:
  1. If I want to add such read/write functions for RX FIFO count register and RX MODE/STATUS Register,
    then I have to add them to github.com/LinuxCNC/linuxcnc/blob/master...mesa-hostmot2/uart.c ?
  2. Or can I use/define these functions solely within my own component by merely including github.com/LinuxCNC/linuxcnc/blob/master...-hostmot2/hostmot2.h ?
  3. A kind of callback function called each time from within my component if n <=16 bytes are written to the Rx FIFO
    would be nice, but I do not know how to do this - at least at the moment.


Thanks in advance.
Last edit: 22 Jan 2016 17:02 by sirop. Reason: typo

Please Log in or Create an account to join the conversation.

More
22 Jan 2016 18:25 #68928 by PCW
If you are going to write new low level interface code, you might consider the PacketUART

Its more oriented towards packetized data (with interpacket timeouts settable from 1 to 255 bittimes for RX framing)
and also can have RX/TX buffers of up to 1024 bytes
The following user(s) said Thank You: sirop

Please Log in or Create an account to join the conversation.

  • sirop
  • sirop's Avatar Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
22 Jan 2016 18:55 #68929 by sirop

If you are going to write new low level interface code, you might consider the PacketUART

Its more oriented towards packetized data (with interpacket timeouts settable from 1 to 255 bittimes for RX framing)
and also can have RX/TX buffers of up to 1024 bytes


Yes, I saw PacketUART in regmap and wondered why I find nothing about this tag in hostmot2.h .

The manufacturer of my gyro promises between the lines that datagrams are sent out at equal time intervals
and can be timestamped with nanosecond precision.

So if I do not manage to use the 16 byte FIFO just relying on some empirical pause intervals,
then let me first implement the proposal of reading/writing to RX FIFO count register first.

If this does not help, then I'll have to implement the PacketUART interface.

Please Log in or Create an account to join the conversation.

More
23 Jan 2016 16:32 #68975 by andypugh

  • Or can I use/define these functions solely within my own component by merely including github.com/LinuxCNC/linuxcnc/blob/master...-hostmot2/hostmot2.h ?

  • You ought to be able to "get" the UART in a driver written in the halcompile preprocessor.

    There is a sample driver here: git.linuxcnc.org/gitweb?p=linuxcnc.git;a...7ba00fa52631;hb=HEAD

    Basically the hostmot2 driver exports a function that returns a pointer to the UART structure, and you can ask for that pointer.

    Please Log in or Create an account to join the conversation.

    More
    23 Jan 2016 16:33 #68976 by andypugh
    Right at the bottom of the docs, under "hostmot2 API calls"

    linuxcnc.org/docs/2.7/html/
    The following user(s) said Thank You: sirop

    Please Log in or Create an account to join the conversation.

    • sirop
    • sirop's Avatar Topic Author
    • Offline
    • Elite Member
    • Elite Member
    More
    23 Jan 2016 16:49 #68978 by sirop


    Basically the hostmot2 driver exports a function that returns a pointer to the UART structure, and you can ask for that pointer.


    Seems to be this one:
     213 EXPORT_SYMBOL_GPL(hm2_get_uart);
     214 int hm2_get_uart(hostmot2_t** hm2, char *name){
     215     struct rtapi_list_head *ptr;
     216     int i;
     217     rtapi_list_for_each(ptr, &hm2_list) {
     218         *hm2 = rtapi_list_entry(ptr, hostmot2_t, list);
     219         if ((*hm2)->uart.num_instances > 0) {
     220             for (i = 0; i < (*hm2)->uart.num_instances ; i++) {
     221                 if (!strcmp((*hm2)->uart.instance[i].name, name)) {return i;}
     222             }
     223         }
     224     }
     225     return -1;
     226 }

    Ok, I'll test tommorrow if it helps.

    Please Log in or Create an account to join the conversation.

    • sirop
    • sirop's Avatar Topic Author
    • Offline
    • Elite Member
    • Elite Member
    More
    28 Jan 2016 12:54 #69194 by sirop
    I got stuck a little bit as we found out an electric problem on our RS 232 connection,
    probably, due to voltage difference on the ground pins.

    However I could test these lines
    unsigned char Replyd[16]={[0 ... 15] = 0xFF }; // reply to expect: 7565 0C04 04F1 1100 F0CC in case of success
    	
    hm2_uart_instance_t *inst = &hm2->uart.instance[0];
    u32 buffer_bytes = 0; //(u32)((bitrate * 1048576.0)/inst->clock_freq)
    hm2->llio->read(hm2->llio, inst->rx_fifo_count_addr, &buffer_bytes, sizeof(u32));
    	
    while ((buffer_bytes & 0x1F)<10)
    	{
    	  buffer_bytes=0;
    	  usleep(100);
    	  retval=hm2->llio->read(hm2->llio, inst->rx_fifo_count_addr, &buffer_bytes, sizeof(u32));
    	  if (retval<0)
    	         {
    		   rtapi_print_msg(RTAPI_MSG_ERR, "UART: hm2->llio->read failure %s\n", name);
                       return -1;
    		}
    	}
    	
    retval= hm2_uart_read(name, Replyd);
    buffer_bytes=0;
    retval=hm2->llio->write(hm2->llio, inst->rx_fifo_count_addr, &buffer_bytes, sizeof(u32));
    if (retval<0)
    	    {
    		   rtapi_print_msg(RTAPI_MSG_ERR, "UART: hm2->llio->write failure %s\n", name);
                       return -1;
    	   }
    on the basis of git.linuxcnc.org/gitweb?p=linuxcnc.git;a...7ba00fa52631;hb=HEAD

    with Prolific USB-RS232 connector plugged into a Windows PC and using hterm www.der-hammer.info/terminal/ .
    These lines work with 115200 Baud, however I do not know what happens if we increase the load on the machine or try to use more than one UART.

    So I think it's worth implementing the PktUART driver which I'll try in the next days...

    Please Log in or Create an account to join the conversation.

    • sirop
    • sirop's Avatar Topic Author
    • Offline
    • Elite Member
    • Elite Member
    More
    30 Jan 2016 15:48 #69272 by sirop
    I am trying now to implement PktUART driver following the pattern of the UART driver

    freeby.mesanet.com/regmap says:

    PktUARTx data register (write only)

    [...]

    0x6100 PktUARTx 0 data register
    0x6104 PktUARTx 1 data register
    0x6108 PktUARTx 2 data register
    0x610c PktUARTx 3 data register
    0x6110 PktUARTx 4 data register

    ...

    PktUARTx send count register read/write

    [...]

    0x6200 PktUARTx 0 send count register
    0x6204 PktUARTx 1 send count register
    0x6208 PktUARTx 2 send count register
    0x620C PktUARTx 3 send count register


    Why are there five Tx data registers, but only four (corresponding ?) send count registers?
    Is 0x6110 PktUARTx 4 data register kind of overflow data register?

    Thanks.

    Please Log in or Create an account to join the conversation.

    More
    30 Jan 2016 16:23 - 30 Jan 2016 16:42 #69273 by PCW
    Those are just illustrations of possible register base addresses of _multiple_ packet UARTs
    (you can have up to 64 PktUARTs in a config)

    if you have a single PktUART, you only have one data TX data register at 0x6100 (or wherever the IDROM says it is)
    Last edit: 30 Jan 2016 16:42 by PCW.
    The following user(s) said Thank You: sirop

    Please Log in or Create an account to join the conversation.

    • sirop
    • sirop's Avatar Topic Author
    • Offline
    • Elite Member
    • Elite Member
    More
    03 Feb 2016 11:27 - 04 Feb 2016 17:05 #69504 by sirop
    Ok, just commited the first draft:
    github.com/sirop/machinekit/commit/1f68e...1abde3e2319f4853fa82

    It is machinekit, as I have more experience with building it from source and github does not let me fork linuxcnc somehow
    making me land at my machinekit fork.

    It compiles without errors.

    Some questions/remarks:
    • Hope I got the difference between UART and PktUART correctly.
      My hm2_pktuart_instance_t looks like:
      typedef struct {
          u32 clock_freq;
          u32 bitrate;
          u32 tx_fifo_count_addr;
          u32 tx_bitrate_addr;
          u32 tx_addr;
          u32 tx_mode_addr;
          u32 rx_fifo_count_addr;
          u32 rx_bitrate_addr;
          u32 rx_addr;
          u32 rx_mode_addr;
          char name[HAL_NAME_LEN+1];
      } hm2_pktuart_instance_t;
      So there is only one rx_addr and tx_addr per instance of PktUART?

    • I defined Module Descriptor constants for PktUART as:

      #define HM2_GTAG_PKTUART_TX (90) // PktUART uses same addresses as normal UART with
      #define HM2_GTAG_PKTUART_RX (110) // the assumption you would not use both in one config

      Hope that's ok.
      #define HM2_GTAG_PKTUART_TX        (27)  // PktUART uses same addresses as normal UART with 
      #define HM2_GTAG_PKTUART_RX        (28) // the assumption you would not use both in one config
      because IDROMConst.vhd says:
      constant PktUARTTTag : std_logic_vector(7 downto 0) := x"1B";     --  =27
      		constant PktUTDataPin : std_logic_vector(7 downto 0) := x"81";
      		constant PktUTDrvEnPin : std_logic_vector(7 downto 0) := x"82";		
      
      	constant PktUARTRTag : std_logic_vector(7 downto 0) := x"1C";  -- =28
      		constant PktURDataPin : std_logic_vector(7 downto 0) := x"01"


    • I do not quite understand how the burst mode of PktUARTx send count register functions.
      Suppose I want to send two datagrams of 10 bytes length each.
      Let the datagram be: 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A .
      Then I do for the first datagram:

      write 0x04030201 to PktUARTx data register
      write 0x08070605 to PktUARTx data register
      write 0x00000A09 to PktUARTx data register
      and then do the same for the second datagram .

      Writing 0x0000000A to PktUARTx sendcount register sends out the first datagram.
      Will writing 0x0000000A to PktUARTx sendcount register send out the second datagram?

    I have not tested the code with a bit file, but will do it today or tomorrow.

    Thanks.
    Last edit: 04 Feb 2016 17:05 by sirop. Reason: const definition error

    Please Log in or Create an account to join the conversation.

    Time to create page: 0.089 seconds
    Powered by Kunena Forum