mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Improve efficiency and formatting of ITM output
SerialWireOutput was outputting 1 character per 32-bit write to the ITM stimulus port. This is inefficient, and causes processing problems with some viewers due to them receiving 3 NUL bytes between each desired character. Rework to allow us to be more efficient, and eliminate those NUL bytes: * Retain existing mbed_itm_send() and clarify it's a single 32-bit write. * Add new mbed_itm_send_block() that is appropriate for sending character data, and modify SerialWireOutput to use it. * Move "wait for FIFO ready" check to before the write, rather than after. One minor correction - FIFOREADY is a single bit of the register read. Don't interpret reserved bits.pull/7371/head
							parent
							
								
									f12afde757
								
							
						
					
					
						commit
						0f98338153
					
				| 
						 | 
					@ -33,12 +33,8 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual ssize_t write(const void *buffer, size_t size)
 | 
					    virtual ssize_t write(const void *buffer, size_t size)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const unsigned char *buf = static_cast<const unsigned char *>(buffer);
 | 
					        mbed_itm_send_block(ITM_PORT_SWO, buffer, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Send buffer one character at a time over the ITM SWO port */
 | 
					 | 
				
			||||||
        for (size_t i = 0; i < size; i++) {
 | 
					 | 
				
			||||||
            mbed_itm_send(ITM_PORT_SWO, buf[i]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return size;
 | 
					        return size;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@
 | 
				
			||||||
#if defined(DEVICE_ITM)
 | 
					#if defined(DEVICE_ITM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
| 
						 | 
					@ -68,12 +69,26 @@ void mbed_itm_init(void);
 | 
				
			||||||
 * @brief      Send data over ITM stimulus port.
 | 
					 * @brief      Send data over ITM stimulus port.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param[in]  port  The stimulus port to send data over.
 | 
					 * @param[in]  port  The stimulus port to send data over.
 | 
				
			||||||
 * @param[in]  data  The data to send.
 | 
					 * @param[in]  data  The 32-bit data to send.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The data is written as a single 32-bit write to the port.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return     value of data sent.
 | 
					 * @return     value of data sent.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
uint32_t mbed_itm_send(uint32_t port, uint32_t data);
 | 
					uint32_t mbed_itm_send(uint32_t port, uint32_t data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief      Send a block of data over ITM stimulus port.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in]  port  The stimulus port to send data over.
 | 
				
			||||||
 | 
					 * @param[in]  data  The block of data to send.
 | 
				
			||||||
 | 
					 * @param[in]  len   The number of bytes of data to send.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The data is written using multiple appropriately-sized port accesses for
 | 
				
			||||||
 | 
					 * efficient transfer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void mbed_itm_send_block(uint32_t port, const void *data, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**@}*/
 | 
					/**@}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ITM_STIM_FIFOREADY_Msk
 | 
				
			||||||
 | 
					#define ITM_STIM_FIFOREADY_Msk 1
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ITM_ENABLE_WRITE 0xC5ACCE55
 | 
					#define ITM_ENABLE_WRITE 0xC5ACCE55
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SWO_NRZ 0x02
 | 
					#define SWO_NRZ 0x02
 | 
				
			||||||
| 
						 | 
					@ -66,21 +70,64 @@ void mbed_itm_init(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void itm_out8(uint32_t port, uint8_t data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Wait until port is available */
 | 
				
			||||||
 | 
					    while ((ITM->PORT[port].u32 & ITM_STIM_FIFOREADY_Msk) == 0) {
 | 
				
			||||||
 | 
					        __NOP();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* write data to port */
 | 
				
			||||||
 | 
					    ITM->PORT[port].u8 = data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void itm_out32(uint32_t port, uint32_t data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Wait until port is available */
 | 
				
			||||||
 | 
					    while ((ITM->PORT[port].u32 & ITM_STIM_FIFOREADY_Msk) == 0) {
 | 
				
			||||||
 | 
					        __NOP();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* write data to port */
 | 
				
			||||||
 | 
					    ITM->PORT[port].u32 = data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t mbed_itm_send(uint32_t port, uint32_t data)
 | 
					uint32_t mbed_itm_send(uint32_t port, uint32_t data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Check if ITM and port is enabled */
 | 
					    /* Check if ITM and port is enabled */
 | 
				
			||||||
    if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) &&      /* ITM enabled */
 | 
					    if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) &&      /* ITM enabled */
 | 
				
			||||||
            ((ITM->TER & (1UL << port)) != 0UL)) {           /* ITM Port enabled */
 | 
					            ((ITM->TER & (1UL << port)) != 0UL)) {       /* ITM Port enabled */
 | 
				
			||||||
        /* write data to port */
 | 
					        itm_out32(port, data);
 | 
				
			||||||
        ITM->PORT[port].u32 = data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Wait until data has been clocked out */
 | 
					 | 
				
			||||||
        while (ITM->PORT[port].u32 == 0UL) {
 | 
					 | 
				
			||||||
            __NOP();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return data;
 | 
					    return data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mbed_itm_send_block(uint32_t port, const void *data, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const char *ptr = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check if ITM and port is enabled */
 | 
				
			||||||
 | 
					    if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) &&      /* ITM enabled */
 | 
				
			||||||
 | 
					            ((ITM->TER & (1UL << port)) != 0UL)) {       /* ITM Port enabled */
 | 
				
			||||||
 | 
					        /* Output single byte at a time until data is aligned */
 | 
				
			||||||
 | 
					        while ((((uintptr_t) ptr) & 3) && len != 0) {
 | 
				
			||||||
 | 
					            itm_out8(port, *ptr++);
 | 
				
			||||||
 | 
					            len--;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Output bulk of data one word at a time */
 | 
				
			||||||
 | 
					        while (len >= 4) {
 | 
				
			||||||
 | 
					            itm_out32(port, *(const uint32_t *) ptr);
 | 
				
			||||||
 | 
					            ptr += 4;
 | 
				
			||||||
 | 
					            len -= 4;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Output any trailing bytes */
 | 
				
			||||||
 | 
					        while (len != 0) {
 | 
				
			||||||
 | 
					            itm_out8(port, *ptr++);
 | 
				
			||||||
 | 
					            len--;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif // defined(DEVICE_ITM)
 | 
					#endif // defined(DEVICE_ITM)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue