This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to use nrfjprog.dll

We are trying to use nrfjprog.dll in a c# program to help us with manufacturing and quality assurance. We are able to load and call the functions from c# and all the functions work one by one, but if we call NRFJPROG_open_dll and then one of the other functions we get an error saying:

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

This happens no matter which of the functions we are calling after calling NRFJPROG_is_dll_open even if it is NRFJPROG_close_dll or NRFJPROG_is_dll_open.

This is the code we are using:

   [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
   private static extern nrfjprogdll_err_t NRFJPROG_dll_version(out UInt32 major, out UInt32 minor, [MarshalAs(UnmanagedType.LPWStr)] out string revision);

   [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
   private static extern nrfjprogdll_err_t NRFJPROG_is_dll_open(out bool opened);

   [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
   private static extern nrfjprogdll_err_t NRFJPROG_open_dll(string jlink_path, msg_callback_cb cb, device_family_t family);

   [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
   private static extern nrfjprogdll_err_t NRFJPROG_close_dll();

   public static void TestNrfj()
   {
       UInt32 major, minor;
       string revision = "";
       bool open;
       nrfjprogdll_err_t return_value;

       return_value = NRFJPROG_open_dll(JLinkPath, msg_callback, device_family_t.NRF52_FAMILY);
       return_value = NRFJPROG_is_dll_open(out open);
       return_value = NRFJPROG_dll_version(out major, out minor, out revision);
       return_value = NRFJPROG_close_dll();        
  • Hard to say what the cuase is, apparently Attempted to read or write protected memory. This is often an indication that other memory is corrupt could be anything according to Google. I spoke to one of the developers and his comment was that this is not an error returned by our dll, but the function import looks good and that he cant see any obvious mistakes. He suggested that you take a look at the 64-bit dll distributed with pynrfjprog if you're running this in 64-bit Windows.

  • Could you check the return_value from NRFJPROG_open_dll()? The developer also suggested replacing out with * .

  • After a lot of debugging we found out the cause of the error was how the msg_callback_cb was defined. After changing that to use a IntPtr and making sure the garbage collector didn't interfere, it worked.

    We managed to test all the functions we needed, so I will add the entire code here if someone is in the same problem in the future.

        public class NrfjprogHandler
    {
        static string JLinkPath = "C:\\Program Files (x86)\\SEGGER\\JLink_V612a\\JLinkARM.dll";
    
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void msg_callback_cb([In, MarshalAs(UnmanagedType.LPStr)] string msg_str);
    
        private void msg_callback([In, MarshalAs(UnmanagedType.LPStr)] string msg_str)
        {
            return;
        }
        //Instance to keep the garbage collector from removing it.
        private msg_callback_cb mCallBack;
    
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_dll_version(out int major, out int minor, out char revision);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_is_dll_open(out bool opened);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_open_dll(string jlink_path, System.IntPtr cb, device_family_t family);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void NRFJPROG_close_dll();
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_connect_to_emu_with_snr(out int serial_number, out int clock_speed_in_khz);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_connect_to_emu_without_snr(int clock_speed_in_khz);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_connect_to_device();
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_is_rtt_started(out bool started);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_rtt_set_control_block_address(int address);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_rtt_start();
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_rtt_is_control_block_found(out bool is_control_block_found);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_rtt_stop();
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_rtt_read(int up_channel_index, out char data, int data_len, out int data_read);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_rtt_write(int down_channel_index, [In, MarshalAs(UnmanagedType.LPWStr)]  string data, int data_len, out int data_written);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_rtt_read_channel_count(out int down_channel_number, out int up_channel_number);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_read_device_family(out device_family_t family);
    
        [DllImport("Flash/nrfjprog/nrfjprog.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern nrfjprogdll_err_t NRFJPROG_read_device_version(out device_version_t version);
    
        public NrfjprogHandler()
        {
            //Create an instance of the callback
            mCallBack = new msg_callback_cb(msg_callback);
        }
    
        public void TestNrfj()
        {
            int major, minor;
            char revision;
            bool open, started, found;
            nrfjprogdll_err_t return_value;
            int clock_speed_in_khz = 4000;
            int down_channel_number, up_channel_number;
            
            NRFJPROG_close_dll();
    
            return_value = NRFJPROG_open_dll(JLinkPath, Marshal.GetFunctionPointerForDelegate<msg_callback_cb>(mCallBack), device_family_t.NRF52_FAMILY);
    
            return_value = NRFJPROG_is_dll_open(out open);
    
            return_value = NRFJPROG_dll_version(out major, out minor, out revision);
            
            return_value = NRFJPROG_connect_to_emu_without_snr(clock_speed_in_khz);
    
            return_value = NRFJPROG_connect_to_device();
    
            device_family_t device_family;
            device_version_t device_version;
    
            return_value = NRFJPROG_read_device_family(out device_family);  //This function seems to be returning a NRF51_FAMILY even though we are using a NRF52832
            return_value = NRFJPROG_read_device_version(out device_version);    //This function does a better job than the previous one.
    
            return_value = NRFJPROG_rtt_start();
    
            return_value = NRFJPROG_is_rtt_started(out started);
    
            return_value = NRFJPROG_rtt_is_control_block_found(out found);
    
            return_value = NRFJPROG_rtt_read_channel_count( out down_channel_number,out up_channel_number);
            
            int dataWritten;
    
            //This only works if sending one char at a time
            return_value = NRFJPROG_rtt_write(0, "T", 1, out dataWritten);
            return_value = NRFJPROG_rtt_write(0, "1", 1, out dataWritten);
    
            int dataRead;
            char read_char;
            //This only works if reading one char at a time
            return_value = NRFJPROG_rtt_read(0, out read_char, 1, out dataRead);
    
    
            return;
        }
    
    }
    
  • NRFJPROG_read_device_family is not implemented on the device specific DLLs, and probably returned an invalid operation warning. It's only implemented for the unknown-family DLL, where it attempts to read the family from the device, this wouldn't make much sense in the nrf51 and nrf52 dlls where we assume we already know what family we are using. As for the return value it probably did nothing, and left your device_family with it's 0-initalized value, which corresponds to NRF51_family.

  • Yes you are right. That was exactly what happened I just missed that the return_value wasn't success.

    We tried to pass both strings and char arrays to the NRFJPROG_rtt_read and NRFJPROG_rtt_write functions, but we couldn't make it work. In the end we ended up trying with a single char and it worked. Is there any reason for this?

Related