0

I recently got a sas expander card.

The one who gave card to me said:

It has a firmware on the chip and it can show sensor's temperature.

He wants me to develop a C# Console app to execute the firmware.

I didn't know the firmware source code looks like.

But it could be executed by PuTTy and it's connection was via RS232 Serial Port.

PuTTy connection setting:

enter image description here

enter image description here

After I click Open,press Enter and type command sys:

enter image description here enter image description here enter image description here

What I try in my C# code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Threading;


namespace SerialPortExample
{
    class SerialPortProgram
    {
        // Create the serial port with basic settings
        [STAThread]
        static void Main()
        {
           
           
            SerialPort mySerialPort = new SerialPort("COM5");

            mySerialPort.BaudRate = 115200;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.RtsEnable = true;
            mySerialPort.DtrEnable = true;
            mySerialPort.ReadTimeout = 2000;
            mySerialPort.WriteTimeout = 1000;
            mySerialPort.Open();
            if(mySerialPort.IsOpen)
            { 
                string str= "Enter";
                mySerialPort.Write(str);
 
            }
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            
            Console.ReadLine();
            
        }
        private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            string indata = sp.ReadExisting();
            Console.WriteLine("Data Received:");
            Console.Write(indata);
        }


    }
}

What my code execute:

enter image description here

What is the problem with my code?

How can I execute firmware via RS232 and interact like PuTTy have done?

My Console app is using .Net Framework 4.7.2.

CherryDT
  • 25,571
  • 5
  • 49
  • 74
Jacky
  • 865
  • 2
  • 12
  • 27
  • The term "execute firmware" is misleading here (it sounds like you want to flash a new firmware onto the device or possibly load code into RAM and execute it on the fly), that's why I updated the title of your question. The firmware is executed the moment you apply power to the card. What you want to do is interact with the (already running) firmware through the serial console interface it exposes. – CherryDT Oct 06 '21 at 08:39

1 Answers1

1

You are sending the string Enter (like typing E, N, T, E, R). You should probably send the ⏎ Enter key, which is represented on a terminal with the ASCII code 13, i.e. \r in a C# string.

Also you don't yet send any actual command. Try something like counters\r or sys\r.

(You currently receive the Enter back as response because that's what you sent out, and the card echoes any incoming characters so it can be used like a shell without blind typing. There is no other response yet because from the card's perspective you basically started typing the (invalid) command Enter but haven't yet submitted it with the ⏎ Enter key.)

Also I'd suggest adding the event listener for received data before sending any data, otherwise there would be a race condition in which the card could be responding before you even set up your listener and you would lose part of the data.


Additional note: Using the DataRecieved event may not even be desirable in your case.

According to docs:

The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer.

This means that your DataReceived event may not even fire at all if there wasn't enough data sent in total yet (it may fire some time later with all the data at once) - but if you quit your program before that, you will never see.

As suggested here (emphasis mine):

Here is my general approach:

Use event-driven (DataReceived) code for streaming data. That is, where data is delivered at regular intervals, without specific associated commands that originate from your application.

Use polling for Command/Response protocols. These might involve a thread the you create to poll, but more frequently would be simple loops that may or may not block other operations until they complete.

So, it would be recommended to use one of the Read methods instead (see docs). There is also ReadTo and ReadLine which you may find useful. You may choose to use ReadTo(" bp1 >") for instance.

CherryDT
  • 25,571
  • 5
  • 49
  • 74
  • I changed my code on console app. The execute result comes up bp1>.After I press ``enter`` key, the app closed. How to continuously accept command and receive command result?just keep adding mySerialPort.DataReceived event? – Jacky Oct 06 '21 at 08:56
  • Adding the event handler once will suffice. Just don't quit your program - for example if you want to query `counters` every second, create a loop which sleeps for 1s and then sends `counters\r`, over and over. – CherryDT Oct 06 '21 at 08:59
  • Sorry, my bad. The question's word ``continuously`` is ``synchronously``. I just got sys command result but it doesn't show up. I have to close app and reopen it.The result would show up. – Jacky Oct 06 '21 at 09:34
  • This would be a different question - see https://stackoverflow.com/questions/55026042/wait-for-response-from-the-serial-port-and-then-send-next-data and https://stackoverflow.com/questions/17850011/c-sharp-waiting-for-the-data-on-serial-port – CherryDT Oct 06 '21 at 09:43
  • Also just to make sure: You are sending the enter key (`\r`) _after_ sending the command, right? Not the other way round? You said you got `bp1>` but no `sys` response, which would suggest that you sent an empty command (like just `\r` without command before it), that's why I'm asking... and "shows up next time" would also make sense then if it would submit the previous run's command at that point... Make sure you send `sys\r` and not `\rsys`. – CherryDT Oct 06 '21 at 09:49
  • Well, I just use ``mySerialPort.Write("sys");``without ``\r`` and result would show in the reopening app. If I use ``mySerialPort.Write("sys\r")``, there will no response even I reopened it. Thanks for the link question. I will do some research. – Jacky Oct 06 '21 at 10:48
  • I added information into my answer. – CherryDT Oct 06 '21 at 11:44