System lags while reading CAN network and working with SQLite

I’m working with a system that needs to read the CAN network and register the read status in the database.

While I’m working without the DATABASE the reading Cycle takes less than 1ms to finish, but when I start to record the values in the DB, it start to lag some cycles, reaching even 15ms, and it is not possible to this application, because we are reading inputs that are really fast.

Have anybody ever worked with SQLite and CAN using C# and WINCE2013 at the same time that can help me ?

Thank you all for the attention

Dear @rafagcf,

Thank you for contacting the Toradex community!

Could you write more detailed about how your C# application designed?

Maybe, you are reading the CAN message and immeditely writing using the SQLLite APIs in a thread. I guess SQLLite is taking more time to complete the API calls.
If this is the case then you need to create 2 separate threads, one for reading the CAN message and put the messages into the circular buffer and 2nd thread for if there are any messages in the circular buffer then write it the DB using SQL Lite APIs.
Once you made 2 threads, you can leverage CeSetThreadPriority and CeSetThreadAffinity APIs, find the best possible setting for your application.

I hope the above solution would help solve your issue.

We have Toradex task manager to monitor the CPU performance.

Please let us know if it doesn’t help.

Hello,

They are working in separated Threads, and the CAN Thread is set in higher priotity

It is really weird because it is not only regarding the SQLite

When I even try to write anything on a text file, it lags a little bit.

Regarding the Task Manager, the CPU is not a problem .

Dear @rafagcf,

Thank you for your reply. Glad to know that you found a solution.

It depends on which memory you are writing. Memory writing should be faster on following order: DDR, NAND, SD card. If you really want faster write performance, you could choose to write on DDR and after some timeout period sync DDR file to Flash or SD card. Please be remember that such methods won’t prevent data corruption during a power failure.

Actually I’ve not found the solution.
I’ve said that even writing a text file while reading the CAN network, generates a lag in the system, and we don’t know what to do. Even working with a C++ project the problem keeps happening.

Dear @rafagxf,

Could you share the issue reproducible application with us? It will help us to look at the issue quickly.
Also, which version of the WinCE release image you are using? Is it V1.5 or v1.6?

Of course @raja.tx

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace TesteCAN { 
    public static class SontheimCAN
    {
        static bool _parar = false;
        static IntPtr hCAN = IntPtr.Zero;
        static public bool Initialize()
        {
            try
            {

                string CANChannel = "CAN1";                       ///< get selected channel (CAN1/CAN2/SP1..4)
                UInt32 CANBitRate = Convert.ToUInt32(1000000);           ///< get BitRate
                string CANFrameFormat = "extended";                         ///< get frame format (standard/extended)
                bool success = true;
                UInt32 busStatus = 1;                                                              ///< CAN bus status (0,1,2)

                hCAN = can.Can_Init(CANChannel);                                                        ///< initialize CAN chaneel
                if (hCAN == IntPtr.Zero)
                {
                    return false;
                }

                ///< refer to CAN configuration options in Toradex_CE_Libraries.chm for more options
                success &= can.Can_SetConfigString(hCAN, "FilterFrameFormat", CANFrameFormat, TdxCommon.ParamStorageType.StoreVolatile);    ///< configurae FiletFrameFormat
                success &= can.Can_SetConfigInt(hCAN, "BitRateHz", CANBitRate, TdxCommon.ParamStorageType.StoreVolatile);                   ///< configure BitRate

                if (!success)
                {
                    return false
                        ;
                }

                if (!can.Can_Open(hCAN))
                {
                    return false;
                }
                can.Can_GetConfigInt(hCAN, "BusStatus", ref busStatus);
                canBuf = new can.tCanMsg();
                UInt32 CANDataLength = Convert.ToUInt32(8);             ///< get data length (1-8bytes)
                Byte[] data = { 0x40, 0x00, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00 };                  ///< get data entered by user
                canBuf.id = 0x610;                                                 ///< message id
                canBuf.dataLen = CANDataLength;                                                       ///< data length
                canBuf.canMsgFlags = 0;
                canBuf.data = new Byte[8];                                                         ///< initialize array
                canBuf.data = data;
                return true;

            }
            catch (Exception)
            {

                return false;
            }
        }
   static     can.tCanMsg canBuf = new can.tCanMsg();
        static Thread ReadingThread;
        static public void StartReading()
        {
            ReadingThread = new Thread(new ThreadStart(() =>
            {
                while (true)
                {
                    if (_parar)
                        break;
                    CicloLeitura();


                }
            }));
            ReadingThread.IsBackground = true;
            var id = ReadingThread.ManagedThreadId;
           var retorno = Utils.CeSetThreadAffinity((IntPtr)id, 4);
            var prioridade = CeSetThreadPriority((IntPtr)id,0);
            ReadingThread.Start();
   
        }
        [DllImport("coredll.dll")]
        static extern bool CeSetThreadPriority(IntPtr hProcess, int dwProcessor);

        static byte anterior1 = 0;
        static byte anterior2 = 0;

        static bool ativo = false;
        static int count = 0;

      static  private can.tCanMsg canBufLeitura = new can.tCanMsg();
        static public bool CicloLeitura()
        {
            try
            {
                Thread.Sleep(1);
                DateTime ag = DateTime.Now;
                IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(canBuf));                                  ///< initialize unmanged memory to hold the struct.
                Marshal.StructureToPtr(canBuf, ptr, false);                                                 ///< Copy the struct to unmanaged memory.
                can.Can_Write(hCAN, ptr);                                                         ///< transfer CAN data

                Marshal.FreeHGlobal(ptr);
                //Thread.Sleep(1);
                //      DateTime n = DateTime.Now;
                canBufLeitura = new can.tCanMsg();                                                   ///< initialize structure
                                                                                                     ///< Configure timeout (optional) to 5 sec, by default it is set to 1 sec
                can.Can_SetConfigInt(hCAN, "Timeout", 0, TdxCommon.ParamStorageType.StoreVolatile);
                ptr = Marshal.AllocHGlobal(Marshal.SizeOf(canBufLeitura));                                  ///< Initialize unmanged memory to hold the struct.
                if (can.Can_Read(hCAN, ptr) != 0)                                                           ///< receive CAN data
                {
                    can.tCanMsg ptr2 = (can.tCanMsg)Marshal.PtrToStructure(ptr, typeof(can.tCanMsg));

                    //          var t = new string((Convert.ToInt64(Convert.ToString(ptr2.data[4], 2)) + 100000000).ToString().Reverse().ToArray());

                    if ((ptr2.data[4] != anterior1 || ptr2.data[5] != anterior2) && ptr2.id == 1424)
                    {
                        // ALTERAÇÃO PARA ANALISE JOABEL
                        anterior1 = ptr2.data[4];
                        anterior2 = ptr2.data[5];
                        VariaveisEstaticas.FormPrincipal.EnqueueTask(new byte[] { anterior2, anterior1 });
                    }
                }
                var temp = (DateTime.Now - ag).TotalMilliseconds;
                if (temp >= 5)
                {
                    Debug.WriteLine(temp + "     BOAaS: " + q);
                    q = 0;
                }
                else
                    q++;
                Marshal.FreeHGlobal(ptr);

            }
            catch (Exception) { }
            return true;

        }


        static double q = 0;

        public static String convert(byte b)
        {
            StringBuilder str = new StringBuilder(8);
            int[] bl = new int[8];

            for (int i = 0; i < bl.Length; i++)
            {
                bl[bl.Length - 1 - i] = ((b & (1 << i)) != 0) ? 1 : 0;
            }

            foreach (int num in bl) str.Append(num);

            return str.ToString();
        }
    }
}

Even Using just this thread, the system each 6000 cycle lags over 7ms

Dear @rafagcf,

Could you share C++ reproducible application, I am more comfortable work with C++ code and it will help me to quickly look and hack the code. I might take more time if I look at it in the C# project.

It would be very helpful if you use our “Toradex CE Libraries\libDemos\Can_Demo\src” code and modify it for reproducing the issue.

Thank you in advance for your effort.