sprintf or snprintf does not work in SLDRT kernel mode

조회 수: 5 (최근 30일)
Howard Loewen
Howard Loewen 2023년 5월 16일
댓글: Howard Loewen 2023년 5월 18일
Hello,
I was using the following code which uses snprintf() to create a GPS message within a S-function builder and it worked well in the connected I/O mode. But, when I tried to run the same code in kernel mode, the output becomes all 0s. I was wondering if there is a workaround or another similar function that I can use to get the same result in the kernel mode.
I tried both MINGW 6.3 and Visual C++ 2017 compilers.
// Packing the data
(void)snprintf(temp_packet, sizeof temp_packet, "$GPGGA," // Message ID
"%02d%02d%06.3f," // UTC_Time
"%02d%08.5f," // Latitude
"%1c," // N/S Indicator
"%03d%08.5f," // Longitude
"%1c," // E/W Indicator
"%1u," // Position Fix Indicator
"%02u," // Satellites used
"%.2f," // HDOP
"%.1f," // MSL Altitude
"M," // M, meters
"," // Geoid Separation, not used
"M," // M, meters
"," // Age of Differential Corrections, not used
"%u" // Diff Reference Station ID
"*" // Start of a checksum
,(int)time_hh, (int)time_mm, time_ss, // UTC_Time
(int)lat_dd, lat_mm, // Latitude
lat_ns, // N/S Indicator
(int)lon_ddd, lon_mm, // Longitude
lon_ew, // E/W Indicator
*Position_Fix, // Position Fix Indicator
*Satellites, // Satellites used
*HDOP, // HDOP
*MSL_Altitude_m, // MSL Altitude
// Age of Differential Corrections, not used
*Diff_Station_ID // Diff Reference Station ID
// Start of a checksum
);
Thank you

답변 (1개)

Jan Houska
Jan Houska 2023년 5월 18일
Hi Howard,
I'm not sure what is exactly your use case, but if you are using snprintf to form a message you will then send to some device e.g. over UDP, you may want to consider the Stream Output block. This block accepts numeric inputs and formats them according to a C-like format string to create text message. Using this block is typically much easier than writing a S-function that does the same. The block also provides other benefits, like automatic data type conversion, and such.
That said, snprintf (which should be always used instead of sprintf) should work and it is in fact internally used by the Stream Output block. I don't quite understand what do you mean by "all zeros" - does this mean the numbers are correctly formatted, but zeros? Like e.g. 00.00000 for latitude? Could you please try literal constants instead of the variables, like e.g. 19.23456 instead of lat_mm ? Do these also come out as zeros? You can also try to shorten the format string to just one or two values - is the problem still there?
And, a final remark - Simulink Desktop Real-Time always uses its own built-in compiler (Clang), so it is not relevant which compiler you use to build your S-function.
Jan
  댓글 수: 1
Howard Loewen
Howard Loewen 2023년 5월 18일
Hi Jan,
Thank you again for the detailed explanation. I was able to get this one resolved myself. If I explain the problem (in kernel mode) that I had before in detail, when I was using sprintf(), the output character array (temp_packet) became all 0s meaning there was no decimal value other than 0. When I switched to snprintf() (presumably a much safer option when it comes to memeory management) only the "GPGGA," term correctly converted into decimals. the rest of the bytes in the temp_packet was all 0s. As you have already mentioned that got me thinking may be this was an issue / a limitation with the number of arguments that I was using.
So, I split the single snprintf() call into multiple calls along with strncpy() to make the complete message. Now I can get the message out successfully using packet output block on to a com port (using byte by byte as I am otputting different GNSS messages with different lengths on to the same com port at the same time) and the receiving device decodes it correctly.
Thank you

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Reference Applications에 대해 자세히 알아보기

제품


릴리스

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by