This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2640 SWO output data from multiple STIM ports get corrupted when debugger is not used

Mastermind 8455 points

Replies: 8

Views: 932

Hi,

I encounter a very strange problem.

** In the following problem description, I don't use TI provided code. I have designed my own RTOS and framework. **

With CC2640, I would like to output data through SWO by different STIM ports. For example, task 1 is using STIM port 0 while task 2 is using port 1. OK, everything works fine when I download program and start to run the target by CCS. I have also designed a PC (Linux) viewer to view the SWO output data. Messages from two tasks can be separated easily by parsing SWO SWIT packets in the PC viewer.

Now, I want to disconnect target from debugger. In CCS, I can do it by menu command "disconnect target". This will keep the target firmware "free" running. Everything still works fine. With XDS100v3 cable still inserted in PC USB port, the PC viewer can continuously get messages from SWO. Then, I unplug the XDS100v3 cable from PC. The viewer stop showing message. After that, I plug XDS100v3 cable to PC again, the viewer continues to show message. Good, everything is as expected.

Then, I power-cycle the target. Now, the firmware in CC2640 is re-launched by boot loader after power-on. I can see some messages output from SWO. But the data are corrupted. Some text are correct, but some are just garbage.

I guess there might be some registers pre-set by the debugger before "run" the target. So, I remove the default GEL file within the .ccxml file. Repeat the above experiment, but the result is the same.

Then I disable task 2. So, only STIM port 0 is used by task 1. Now, the data is correct no matter it is launched by debugger or by power-on.

I have repeated the experiment again and again. It is confirmed that the SWO output from multiple STIM ports are corrupted when the target is executed from power-on (by boot loader?). If the program is executed by debugger (CCS) then everything is fine.

I re-read ARM TRM and CC2640 TRM again and again to ensure TPIU/ITM... registers are well configured. They should be, otherwise, I should not be able to get SWO output  at all.

Finally, I have to call for help...

Robert Chen
simple is beautiful.

8 Replies

  • Hi.

    I am not sure why this would be. Some information might help.


    1. I assume your application is setting up the TPIU/ITM. What baud rate and what timestamp prescalar are you setting it up for?

    2. You mentioned garbage messages. Does it look like messages have been intermixed or characters have been dropped or does it look like messages that are not SWIT packets?


    3. What happens if you disable task 1 and instead have task 2 output messages to STM port 1?


    Thanks

    Ashwini

  • In reply to Ashwini Athalye:

    Hi Ashwini:

    The baud rate is 6Mbps. I have used oscilloscope to confirm the waveform.

    The message is not "intermixed", some messages are correct and some are garbage. These garbage doesn't look like any SWIT packet. When only one task outputs, the data is correct.

    As in my previous post, the output data is correct when:

    (1) the program is launched  by boot loader but only one STIM port is enabled to output.

    (2) the program is launched by CCS debugger and two STIM ports are enabled to output.

    I also understand that all STIM ports share the same FIFO. So I already use LDREX/STREX to protect it as in following code:

    void swv_write(int port, uint8_t* data, int size)
    {
    	while(size){
    		if(size >= 4){
    			while(1){
    				if(__ldrex(port_addr))
    					if(__strex(*(uint32_t*)p, port_addr) == 0)
    						break;
    			}
    			p += 4;
    			size -= 4;
    		}else if(size >= 2){
    			while(1){
    				if(__ldrexh(port_addr))
    					if(__strexh(*(uint16_t*)p, port_addr) == 0)
    						break;
    			}
    			p += 2;
    			size -= 2;
    		}else{
    			while(1){
    				if(__ldrexb(port_addr))
    					if(__strexb(*(uint8_t*)p, port_addr) == 0)
    						break;
    			}
    			p += 1;
    			size -= 1;
    		}
    	}
    }
    

    I also try to disable/enable interrupt to replace LDREX/STREX and the output result is the same. So, the above LDREX/STREX usage should be correct.

    So, I guess CCS must modify some registers through JTAG interface before launching the program. And it cause multi STIM ports to work correctly.

    Robert Chen
    simple is beautiful.

  • In reply to Robert Chen:

    Hi

    The fact that a single STIM port works fine but 2 shows garbage leads me to think that the TPIU formatter might be enabled on power on reset that CCS disables.

    To be sure, we will need to read the TPIU configuration in the 2 cases. But while we are at it, better to grab the ITM configuration as well in case the formatter is not the cause. So to read the ITM and TPIU registers while the target is running use these instructions.

    a) After "free" running your core (for the working case) ...
    b) After power cycling target, launch debug session but don't auto connect to the Cortex M core. (for the non-working case) ....

    ... Right click on the Cortex M core and click on the "Show all cores" option. Now you should see a node for CS_DAP. Select the CS_DAP node and click on Connect (at this point your Cortex M is still disconnected). Now open memory browser and select the "System_View" option from the memory view drop down menu.

    Please take a snapshot of 4k block of memory starting at 0xE0000000 which is where ITM is located and 4k block of memory starting at 0xE0040000 which is where TPIU is located for both the cases a) and b) above. (There is a save memory option in the CCS Memory Browser window that you can use to do this).

    A diff of these files should indicate if something is different. Either you can send me the files or let me know what addresses and values are different in the 2 cases.
  • In reply to Ashwini Athalye:

    Hi Ashwini:

    I try to do what you suggested. Although I can not find "CS_DAP" when execute "Show all cores", the popup menu has a "Connect Target" command. After clicking on this command, the SWO output data becomes correct immediately.

    I have dumped memory by using command "Save memory" for both conditions with addresses 0xE0000000 and 0xE004000. Then, use Linux "diff" command to compare. The results are the same for both conditions. There should be no surprise since the output data becomes correct right after the target is connected.

    So, alternatively, I try to dump data memory by SWO output. To reduce data size, I only dump none-zero values:

    [00:00:00.359] start dump
    [00:00:00.359] e0000e00: ffffffff
    [00:00:00.359] e0000e40: f
    [00:00:00.359] e0000e80: 81000d
    [00:00:00.359] e0000fb4: 1
    [00:00:00.359] e0000fd0: 4
    [00:00:00.359] e0000fe0: 1
    [00:00:00.359] e0000fe4: b0
    [00:00:00.359] e0000fe8: 3b
    [00:00:00.359] e0000ff0: d
    [00:00:00.359] e0000ff4: e0
    [00:00:00.359] e0000ff8: 5
    [00:00:00.359] e0000ffc: b1
    [00:00:00.459]  
    [00:00:00.459] e0040000: b
    [00:00:00.459] e0040004: 1
    [00:00:00.459] e0040010: 7
    [00:00:00.459] e00400f0: 2
    [00:00:00.459] e0040300: 8
    [00:00:00.459] e0040304: 100
    [00:00:00.459] e0040fa0: f
    [00:00:00.459] e0040fc8: ca0
    [00:00:00.459] e0040fcc: 11
    [00:00:00.459] e0040fd0: 4
    [00:00:00.459] e0040fe0: 23
    [00:00:00.459] e0040fe4: b9
    [00:00:00.459] e0040fe8: 3b
    [00:00:00.459] e0040ff0: d
    [00:00:00.459] e0040ff4: 90
    [00:00:00.459] e0040ff8: 5
    [00:00:00.459] e0040ffc: b1
    [00:00:00.459] end dump
    

    The printed values are in hexadecimal without leading zeros. And the first 32 STIM ports are skipped since reading of the STIM ports return FIFO status.

    The printed values for both conditions are the same. So, there is nothing to do with the ITM and TPIU registers.

    Robert Chen
    simple is beautiful.

  • In reply to Robert Chen:

    The CS_DAP node is buried under the "Non debuggable devices" group node. If you use the dropdown arrow next to this group node you will see the CS_DAP node. Sorry I missed telling you this.

    At this point I have no idea why you are seeing the difference in behavior if the setup is identical. Can I get your application so I can try this at my end. It would also be useful to get a copy of your target configuration in CCS (ccxml). To read the SWO data, I plan to use a Terminal utility.

    Thanks

    Ashwini

  • In reply to Ashwini Athalye:

    Hi Ashwini,

    Sorry for late reply.

    The difference in CS_DAP node may because I updated CCS serval time. In fact, I usually feel the CCS interface is not well designed. It could be better.

    For my application, I am sorry that I can not release it to you due to some considerations. My RTOS is confidential. But you can try the SWO printf function in my previous posts. Call it within a while() loop in the main() function is enough to test the result. Sure, you have to configure SWO at first.

    Robert Chen
    simple is beautiful.

  • In reply to Robert Chen:

    Hi,

    Happy new year! Sorry for the delay in getting back over the holiday season. Few questions so I have the exact same setup as you do:

    1. How are you hooking up the SWO pin to the computer? Is it via a separate cable or is it routed via the XDS100v3?
    2. Is the SWO configured for being routed over TDO pin or some other GPIO?
    3. What debug protocol is configured for the target? If CJTAG then mode? Maybe its best if you send me your CCXML (target configuration).

    Thanks
    Ashwini
  • In reply to Ashwini Athalye:

    Hi Ashwini,

    Happy new year!

    1. SWO is routed to XDS100v3.EMU2. This seems the default SWO path in XDS100v3 FPGA.
    2. A separated GPIO (DIO0) pin is used for SWO.
    3. I use cJTAG since pins TDI & TDO are not connected to JTAG header. The CCXML file is created by CCS automatically without any modification. The selected device is CC2640F128.

    Btw, the reason I use DIO0 as SWO is because the boot loader uses DIO0/DIO1 as TX/RX. The boot loader is useful for mass production. And I want to preserve TDI/TDO pins for other usage.

    Robert Chen
    simple is beautiful.

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.