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

Test development using CLI/python/RTT

Hi,

I'd like to start developing automated tests for my custom NRF52840 board.

Currently I use the CLI library (with RTT backend) for communicating with the board.

Any ideas for how I could communicate with my board via a python script?

Thanks

Tim

Parents
  • Hi Tim,

    If you want to continue using CLI over RTT for your communication with the board, you can look into our pynrfjprog library. This enables you to read and write RTT channels from a python script.

    Best regards,
    Jørgen

    1. RTT supports mulitple channels. If you want to keep logging, use another channel than 0 for the test communications.
    2. Yes, this makes sense to me.
  • Okay, so I tried using Channel 1 (both in my python script and firmware), Everytime I run the script, I hit a breakpoint in the code. Specifically, this breakpoint (in cmsis_gcc.h) is hit everytime I send a string from the script:

    __attribute__((always_inline)) __STATIC_INLINE void __SEV(void)
    {
      __ASM volatile ("sev");
    }

    And the program halts. Is this expected?

  • I have not experienced this. I did a test with a modified peripheral example, and a custom pynrfjprog sample. This seems to work as expected.

    rtt_writer_sdk_16.0.0.zip

    from __future__ import print_function
    
    # Import pynrfjprog API module
    from pynrfjprog import LowLevel
    from time import sleep
    
    
    def run(snr=None):
        """
        Run example script.
    
        @param (optional) int snr: Specify serial number of DK to run example on.
        """
        print('# RTT read example using pynrfjprog started...')
        
        # Detect the device family of your device. Initialize an API object with UNKNOWN family and read the device's family. This step is performed so this example can be run in all devices without customer input.
        print('# Opening API with device family UNKNOWN, reading the device family.')
        with LowLevel.API(LowLevel.DeviceFamily.UNKNOWN) as api:            # Using with construction so there is no need to open or close the API class.
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
            device_family = api.read_device_family()
        
        # Initialize an API object with the target family. This will load nrfjprog.dll with the proper target family.
        api = LowLevel.API(device_family)
        
        # Open the loaded DLL and connect to an emulator probe. If several are connected a pop up will appear.
        api.open()
        try:
    
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
    
            # Erase all the flash of the device.
            print('Starting RTT.')
            api.rtt_start()
    		
    		# rtt_start() API is non-blocking, need to wait for the control block to be found
            while(api.rtt_is_control_block_found() != True): 
    			print("waiting for control block")
    			sleep(0.1)
    
            channel_count_down, channel_count_up = api.rtt_read_channel_count()
            print("Found {} down channels and {} up channels".format(channel_count_down, channel_count_up))
    		
            rtt_string = {}
            for i in range(channel_count_down):
    			rtt_string[str(i)] = b''
    		
            while(True):
    			for i in range(channel_count_down):
    				r = api.rtt_read(i, 1)
    				if(len(r) != 0):
    					if(r == b'\n'):
    						print(rtt_string[str(i)])
    						rtt_string[str(i)] = b''
    					else:
    						rtt_string[str(i)] = rtt_string[str(i)] + r
            
            api.close()
    
            print('# Example done...')
    
        except LowLevel.APIError:
            api.close()
            raise
        
     
    if __name__ == '__main__':
        run()
    
    
    

    Did you SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS/SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS in your sdk_config.h file?

  • Thanks, I'll give this a try.

    In the meantime I noticed that the script you sent primarily does RTT reading, and the firmware does RTT write. Is the reverse possible (writing using the script, and reading using the firmware)?

  • Yes, that should work similarly. I updated the examples with read in application and write in Python script:

    rtt_reader_writer_sdk_16.0.0.zip

    from __future__ import print_function
    
    # Import pynrfjprog API module
    from pynrfjprog import LowLevel
    from time import sleep
    
    TEST_STRING = b'RTT Channel 1 write test #'
    
    
    def run(snr=None):
        """
        Run example script.
    
        @param (optional) int snr: Specify serial number of DK to run example on.
        """
        print('# RTT read example using pynrfjprog started...')
        
        # Detect the device family of your device. Initialize an API object with UNKNOWN family and read the device's family. This step is performed so this example can be run in all devices without customer input.
        print('# Opening API with device family UNKNOWN, reading the device family.')
        with LowLevel.API(LowLevel.DeviceFamily.UNKNOWN) as api:            # Using with construction so there is no need to open or close the API class.
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
            device_family = api.read_device_family()
        
        # Initialize an API object with the target family. This will load nrfjprog.dll with the proper target family.
        api = LowLevel.API(device_family)
        
        # Open the loaded DLL and connect to an emulator probe. If several are connected a pop up will appear.
        api.open()
        try:
    
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
    
            # Erase all the flash of the device.
            print('Starting RTT.')
            api.rtt_start()
    		
    		# rtt_start() API is non-blocking, need to wait for the control block to be found
            while(api.rtt_is_control_block_found() != True): 
    			print("waiting for control block")
    			sleep(0.1)
    
            channel_count_down, channel_count_up = api.rtt_read_channel_count()
            print("Found {} down channels and {} up channels".format(channel_count_down, channel_count_up))
            cnt = 0
            while(True):
    			api.rtt_write(1, TEST_STRING + str(cnt) + '\0')
    			cnt = cnt + 1
    			sleep(2);
            
            api.close()
    
            print('# Example done...')
    
        except LowLevel.APIError:
            api.close()
            raise
        
     
    if __name__ == '__main__':
        run()
    
    
    

Reply
  • Yes, that should work similarly. I updated the examples with read in application and write in Python script:

    rtt_reader_writer_sdk_16.0.0.zip

    from __future__ import print_function
    
    # Import pynrfjprog API module
    from pynrfjprog import LowLevel
    from time import sleep
    
    TEST_STRING = b'RTT Channel 1 write test #'
    
    
    def run(snr=None):
        """
        Run example script.
    
        @param (optional) int snr: Specify serial number of DK to run example on.
        """
        print('# RTT read example using pynrfjprog started...')
        
        # Detect the device family of your device. Initialize an API object with UNKNOWN family and read the device's family. This step is performed so this example can be run in all devices without customer input.
        print('# Opening API with device family UNKNOWN, reading the device family.')
        with LowLevel.API(LowLevel.DeviceFamily.UNKNOWN) as api:            # Using with construction so there is no need to open or close the API class.
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
            device_family = api.read_device_family()
        
        # Initialize an API object with the target family. This will load nrfjprog.dll with the proper target family.
        api = LowLevel.API(device_family)
        
        # Open the loaded DLL and connect to an emulator probe. If several are connected a pop up will appear.
        api.open()
        try:
    
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
    
            # Erase all the flash of the device.
            print('Starting RTT.')
            api.rtt_start()
    		
    		# rtt_start() API is non-blocking, need to wait for the control block to be found
            while(api.rtt_is_control_block_found() != True): 
    			print("waiting for control block")
    			sleep(0.1)
    
            channel_count_down, channel_count_up = api.rtt_read_channel_count()
            print("Found {} down channels and {} up channels".format(channel_count_down, channel_count_up))
            cnt = 0
            while(True):
    			api.rtt_write(1, TEST_STRING + str(cnt) + '\0')
    			cnt = cnt + 1
    			sleep(2);
            
            api.close()
    
            print('# Example done...')
    
        except LowLevel.APIError:
            api.close()
            raise
        
     
    if __name__ == '__main__':
        run()
    
    
    

Children
Related