| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 1 | Attaching External Custom Decoders {#custom_decoders} |
| 2 | ================================== |
| 3 | |
| 4 | @brief A description of the C API external decoder interface. |
| 5 | |
| 6 | Introduction |
| 7 | ------------ |
| 8 | |
| 9 | An external custom decoder is one which decodes a CoreSight trace byte stream from a source other |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 10 | than an ARM core which cannot be decoded by the standard built-in decoders within the library. |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 11 | |
| 12 | An example of this may be a trace stream from a DSP device. |
| 13 | |
| 14 | The external decoder API allows a suitable decoder to be attached to the library and used in the |
| 15 | same way as the built-in decoders. This means that the external decoder can be created and destroyed |
| 16 | using the decode tree API, and will integrate seamlessly with any ARM processor decoders that are part |
| 17 | of the same tree. |
| 18 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 19 | An external decoder will be required to use three standard structures:- |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 20 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 21 | - `ocsd_extern_dcd_fact_t` : This is a decoder "factory" that allows the creation of the custom decoders. |
| 22 | - `ocsd_extern_dcd_inst_t` : This structure provides decoder data to the library for a single decoder instance. |
| 23 | - `ocsd_extern_dcd_cb_fns` : This structure provides a set of callback functions allowing the decoder to use library functionality in the same way as built-in decoders. |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 24 | |
| 25 | These structures consist of data and function pointers to allow integration with the library infrastructure. |
| 26 | |
| 27 | Registering A Decoder |
| 28 | --------------------- |
| 29 | |
| 30 | A single API function is provided to allow a decoder to be registered with the library by name. |
| 31 | |
| 32 | ocsd_err_t ocsd_register_custom_decoder(const char *name, ocsd_extern_dcd_fact_t *p_dcd_fact); |
| 33 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 34 | This registers the custom decoder with the library using the supplied name and factory structure. |
| 35 | As part of the registration function the custom decoder will be assigned a protocol ID which may be used in |
| 36 | API functions requiring this parameter. |
| 37 | |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 38 | Once registered, the standard API functions used with the built-in decoders will work with the custom decoder. |
| 39 | |
| 40 | The Factory Structure |
| 41 | --------------------- |
| 42 | This structure contains the interface that is registered with the library to allow the creation of custom decoder instances. |
| 43 | |
| 44 | The mandatory functions that must be provided include: |
| 45 | - `fnCreateCustomDecoder` : Creates a decoder. This function will fill in a `ocsd_extern_dcd_inst_t` structure for the decoder instance. |
| 46 | - `fnDestroyCustomDecoder` : Destroys the decoder. Takes the `decoder_handle` attribute of the instance structure. |
| 47 | - `fnGetCSIDFromConfig` : Extracts the CoreSight Trace ID from the decoder configuration structure. |
| 48 | May be called before the create function. The CSID is used as part of the creation process to |
| 49 | attach the decoder to the correct trace byte stream. |
| 50 | |
| 51 | `fnPacketToString` : This optional function will provide a human readable string from a protocol specific packet structure. |
| 52 | |
| 53 | `protocol_id` : This is filled in when the decoder type is registered with the library. Used in some API |
| 54 | calls to specify the decoder protocol type. |
| 55 | |
| 56 | |
| 57 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 58 | Creating a Custom Decoder Instance |
| 59 | ---------------------------------- |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 60 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 61 | Once the custom decoder factory has been registered with the library then using the decoder uses the standard creation API:- |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 62 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 63 | `ocsd_dt_create_decoder(const dcd_tree_handle_t handle, const char *decoder_name, const int create_flags, |
| 64 | const void *decoder_cfg, unsigned char *pCSID)` |
| 65 | |
| 66 | |
| 67 | This creates a decoder by type name in the current decode tree and attaches it to the trace data stream associated with a CoreSight trace ID extracted from |
| 68 | the trace configuration. |
| 69 | |
| 70 | To create a custom decoder instance simply use the custom name and a pointer to the custom configuration structure. |
| 71 | |
| 72 | Calling this on a custom decoder name will result in a call to the factor function `fnCreateCustomDecoder` function:- |
| 73 | `ocsd_err_t CreateCustomDecoder(const int create_flags, const void *decoder_cfg, const ocsd_extern_dcd_cb_fns *p_lib_callbacks, ocsd_extern_dcd_inst_t *p_decoder_inst)` |
| 74 | |
| 75 | This will first require that the `ocsd_extern_dcd_inst_t` structure is populated. |
| 76 | |
| 77 | There is are two mandatory function calls in this structure that may be called by the library |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 78 | |
| 79 | `fnTraceDataIn` : the decoder must provide this as this is called by the library to provide the |
| 80 | raw trace data to the decoder. |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 81 | |
| 82 | `fn_update_pkt_mon` : Allows the library to communicate when packet sink / packet monitor interfaces are attached to the decoder and in use. |
| 83 | |
| 84 | The decoder creation process will also fill in the additional information to allow the library to correctly call back into the custom decoder using the `decoder_handle` parameter. |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 85 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 86 | Secondly the library will provide a structure of callback functions - `ocsd_extern_dcd_cb_fns` - that the decoder can use to access standard library functionality. |
| 87 | This includes the standard error and message logging functions, the memory access and ARM instruction decode functions, plus the current output sink for generic |
| 88 | trace elements generated by the decoder. The decoder is not required to use these functions - indeed the ARM instruction decode will not be useful to none ARM |
| 89 | architecture decoders, but should where possible use these functions if being used as part of a combined ARM / custom decoder tree. This will simplify client |
| 90 | use of the external decoders. |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 91 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 92 | The `create_flags` parameter will describe the expected operational mode for the decoder. The flags are:- |
| 93 | - `OCSD_CREATE_FLG_PACKET_PROC` : Packet processing only - the decoder will split the incoming stream into protocol trace packets and output these. |
| 94 | - `OCSD_CREATE_FLG_FULL_DECODER` : Full decode - the decoder will split the incoming stream into protocol trace packets and further decode and analyse these to produce generic trace output which may describe the program flow. |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 95 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 96 | Finally the decoder creation function will interpret the custom configuration (`decoder_cfg`) and fill in the CoreSight Trace ID parameter `pCSID` |
| 97 | for this decoder instance. Decoder configuration structures describe registers and parameters used in programming up the trace source. The only |
| 98 | minimum requirement is that it is possible to extract a CoreSight trace ID from the configuration to allow the library to attach the correct byte |
| 99 | stream to the decoder. |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 100 | |
| 101 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 102 | Example : The echo_test decoder |
| 103 | -------------------------------- |
| 104 | |
| 105 | The echo_test decoder is provided to both test the C-API interfaces provided for using custom decoders and as a worked example for using these interfaces. |
| 106 | |
| 107 | This decoder is initialised and created by the `c_api_pkt_print_test` program when the `-extern` command line option is used. |
| 108 | |
| 109 | In order to use a custom decoder, the header files for that decoder must be included by the client as they are not part of the built-in provided by the standard library includes. |
| 110 | |
| 111 | #include "ext_dcd_echo_test_fact.h" // provides the ext_echo_get_dcd_fact() fn |
| 112 | #include "ext_dcd_echo_test.h" // provides the echo_dcd_cfg_t config structure. |
| 113 | |
| 114 | The `register_extern_decoder()` function in the test shows how simple the API is to use. |
| 115 | |
| 116 | The implementation of the decoder provides an external function to get a factory structure. |
| 117 | |
| 118 | p_ext_fact = ext_echo_get_dcd_fact(); |
| 119 | |
| 120 | Assuming this returns a structure then the decoder is registered by name. |
| 121 | |
| 122 | if (p_ext_fact) |
| 123 | { |
| 124 | err = ocsd_register_custom_decoder(EXT_DCD_NAME, p_ext_fact); |
| 125 | } |
| 126 | |
| 127 | After this the test uses the same code path as the built in decoders when testing the custom decoder. |
| 128 | The test function `ocsd_err_t create_decoder_extern(dcd_tree_handle_t dcd_tree_h)` is called if the test parameters indicate a custom decoder is needed. |
| 129 | This populates the custom configuration structure specific to the echo_test decoder (`echo_dcd_cfg_t`), then passes this plus the decoder name to the same `create_generic_decoder()` function used when testing the built in decoders. |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 130 | |
| 131 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 132 | static ocsd_err_t create_decoder_extern(dcd_tree_handle_t dcd_tree_h) |
| 133 | { |
| 134 | echo_dcd_cfg_t trace_cfg_ext; |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 135 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 136 | /* setup the custom configuration */ |
| 137 | trace_cfg_ext.cs_id = 0x010; |
| 138 | if (test_trc_id_override != 0) |
| 139 | { |
| 140 | trace_cfg_ext.cs_id = (uint32_t)test_trc_id_override; |
| 141 | } |
| Mike Leach | 17610e5 | 2016-09-16 15:55:11 +0100 | [diff] [blame] | 142 | |
| Mike Leach | 998059f | 2016-11-18 17:24:57 +0000 | [diff] [blame^] | 143 | /* create an external decoder - no context needed as we have a single stream to a single handler. */ |
| 144 | return create_generic_decoder(dcd_tree_h, EXT_DCD_NAME, (void *)&trace_cfg_ext, 0); |
| 145 | } |
| 146 | |
| 147 | From the test program perspective, these are the only changes made to the test program to test this decoder. |
| 148 | The `create_generic_decoder()` then uses the normal C-API calls such as `ocsd_dt_create_decoder()` and `ocsd_dt_attach_packet_callback()` to hook the decoder into the decode tree infrastructure. |