As part of the production programming process, Cyclone FX programmers have the ability to program and run a series of custom test applications in the target processor before final programming is allowed to occur. These custom test applications are written by the end user and include any functionality desired including test and calibration of the target system. The custom test applications indicate to the Cyclone through the debug interface whether they were successful or not and also optionally return generated data to the Cyclone for use later in the programming process. If all of the custom test applications pass, the final application is programmed into the target. This advanced control/automation feature is exclusive to the Cyclone FX programmer model. This “Run Test” process is shown here: Use cases of the Run Test feature during programming include: Run Test applications are written by the user in any development environment which can generate a valid application for the processor being programmed. The test application could be a special version of the final application which conditionally has included test code, or the test application could as easily be a totally different code base. The test application links in the Run Test API code which allows the run test application to communicate to the Cyclone via the debug connection during the test process. While each test application must in the end report back a success/fail result to the Cyclone FX, it can also query the Cyclone for information and interact with the user through the Cyclone hardware. As part of each test application that is programmed and run, the test application can optionally return "named" blocks of run test data (rtData) which are saved in the Cyclone until the entire programming process is complete. These rtData blocks may be programmed with any subsequent test application or during final application programming. The Image Creation utility, which generates stand-alone programming images, has a script creation wizard which specifies the steps to be executed during target programming. Here is what a simple, and yet common, programming script without Run Test looks like: Here is what a simple programming script with Run Test looks like: NOTE: The "SS" command has been replaced by the "QO"and "QB" commands, please refer to this article. This will be reflected in the exmples below. The RT command (Run Test) executes the application currently programmed into the flash. The application establishes a connection to the Cyclone through the debug bus, optionally interacts with the Cyclone, optionally saves named blocks of data (rtData) to the Cyclone, and will report success/failure to the Cyclone. A failure immediately terminates the programming script. The PF command (program feature) can be used to program any named rtData blocks back into the device at any time. rtData blocks are discarded once the programming script/image completes. In order to implement the test applications as part of the programming process, PEmicro provides a Run Test API C and header file. These are linked into the test application and allow the application to communicate to the Cyclone through the debug bus. The API calls let the user display, retrieve, and save a variety of information on the cyclone. A selection of the Run Test API Calls: void runtest_initialize_programmer_connection(void); Initiate the connection to the cyclone programmer across the debug connection. This is expected to be called somewhere near the start of the main() function in the test application. If the Cyclone doesn’t receive a connection request from the Run Test application, then it will error after a timeout. Once this routine returns, all other calls may be used until the test application is stopped by the runtest_stop_test_and_return_result() call. void runtest_stop_test_and_return_result (unsigned long result_temp); Stops the test application from running and sends back the test application result to the Cyclone as pass/fail with error codes. The Cyclone will move on to the next programming step if the result was successful. A zero result denotes success and non-zero means failure. unsigned char runtest_send_rtdata_block_to_programmer(void *dataptr, unsigned long number_of_bytes, char *data_feature_description); Sends a block of data (“rtData”) to the Cyclone, with a specific name to reference it, for later use by the Cyclone. This data can be reprogrammed by the Cyclone into the device using the PF Program Feature command when programming in the final application (or other test applications). void runtest_get_date_time(runtest_date_struct *runtest_date_ptr); void runtest_get_UTC_date_time(runtest_date_struct *runtest_date_ptr); Allows the test application to retrieve either the local or the UTC date and time from the Cyclone. The Cyclone will fill out the data structure pointed to by the pe_data_ptr. unsigned char runtest_display_dialog(char* dialog_text, char* button_one_text, char* button_two_text, char* button_three_text); Allows the test application to pop up a message box with three buttons on the display of the Cyclone (or on the PC if using the PROG software). All strings are null terminated. If the button text for each button is not blank, then the button will be visible. This is a way to either notify the operator to do something at some point in the test or to ask them a question. Once a button is selected, it will send back the button number from the Cyclone to the running test application in the target. If no button is selected, it will send back a 0 for no data. unsigned char runtest_input_query(const char* message_string, char *string_input_by_user, unsigned char max_string_length); Pops up a message box on the Cyclone screen prompting the user for a response. This default response on the Cyclone screen for editing is specified by the string_input_by_user string. If the user enters a new string, the data in the string_input_by_user string will be overwritten. The image below is an example of what is shown on the Cyclone touch screen. unsigned char runtest_write_string_to_log_file(char* string_to_append_to_logfile); Send a text string back to the Cyclone for display/logging. void runtest_request_power_measurement(unsigned long *V_measured, unsigned long *I_measured); Reads the target voltage and current usage as measured from the Cyclone. The voltage is in mV and the current is in uA. This example runs a hardware test before final programming. // Initialization runtest_initialize_programmer_connection(); runtest_write_string_to_log_file("Running HARDWARE TEST…"); if (testHardware()) { runtest_write_string_to_log_file("Success."); runtest_stop_test_and_return_result (0); // Success } else { runtest_write_string_to_log_file("Error – Hardware Test Reported Failure!!!!!!!!!!!!!"); runtest_stop_test_and_return_result (0x01); // failure! } CM C:\PEMicro\cyclone\supportfiles\supportFiles_ARM\NXP\iMX\nxp_imxrt1064_1x32x1meg.arp EM ;Erase Module QO C:\MyWorkspace\Test\Widget\Hardware\widgettestapp.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Application\Widget\finalapplication.elf PM ;Program Module VM ;Verify Module This example calculates a unique block of data, the “device fingerprint”, based upon the device’s unique id (UUID) and an unspecified algorithm. This could actually be a series of individual algorithms generating a number of fingerprint components including : CRCs, asymmetric keys, lookup tables, etc. Anything which would be hard to reverse and gives unique pieces of data which can be verified later in the final application, firmware updates, or if the device interacts with other components of the manufacturer. The algorithm for generating the device fingerprint only resides in the test application (which gets erased during the programming process) and not in the final application. The final application can optionally confirm the signature or one component of the signature. // Initialization runtest_initialize_programmer_connection(); runtest_write_string_to_log_file("Running Fingerprinting operation …"); // Calculate “fingerprint” based on the UUID and some algorithm. Potentially multiple fingerprints. readDeviceUniqueId(&uniqueIdBuffer); createFingerprintBasedOnUniqueId(&fingerprintBuffer, &uniqueIdBuffer); //Return Device fingerprint to the Cyclone for later programming with final application runtest_add_rtData_to_programmer(&fingerprintBuffer, FINGERPRINT_BUFFER_SIZE, "DEVICE_FINGERPRINT"); runtest_write_string_to_log_file("Done."); runtest_stop_test_and_return_result (0); // Success CM C:\PEMicro\cyclone\supportfiles\supportFiles_ARM\NXP\iMX\nxp_imxrt1064_1x32x1meg.arp EM ;Erase Module QO C:\MyWorkspace\Test\Widget\Fingerprint\devicefingerprintapp.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Application\Widget\finalapplication.elf PM ;Program Module PF DEVICE_FINGERPRINT 1F000 ;The RTC_DATA was generated by the devicefingerprintapp.elf test application VM ;Verify Module This example was derived from a test used in PEmicro’s manufacturing process. Since 32.768Khz crystals have some small inaccuracy which accumulates over time in an RTC, we wished to measure the crystal frequency on each device manufactured very precisely and record it in that device. Since the frequency can be affected by temperature, we also record the temperature of the device at the time of measurement/programming. The goal was to have this information in case we needed it in the future for calibration. The test uses a benchtop external high performance counter unit to measure a 1hz signal generated by the MCU based on the crystal frequency. The operator of the Cyclone FX is prompted to enter the displayed frequency value in the middle of the test/programming process (this was easier than integrating the performance counter in an automated way). CM C:\PEMicro\cyclone\supportfiles\supportFiles_ARM\NXP\iMX\nxp_imxrt1064_1x32x1meg.arp EM ;Erase Module QO C:\MyWorkspace\Test\Widget\Hardware\widgettestapp.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Test\Widget\Fingerprint\devicefingerprintapp.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Test\Widget\RTC_Cal\rtccal.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Application\Widget\finalapplication.elf PM ;Program Module PF DEVICE_FINGERPRINT 1F000 ;The RTC_DATA was generated by the devicefingerprintapp.elf test application PF RTC_DATA 1FF00 ;The RTC_DATA was generated by the rtccal.elf test application VM ;Verify Module This programming script/image runs all three test/calibration applications detailed above before final programming. It programs both the calibration data and device fingerprint with the final application. Cyclone Programming Image (and Test Application) Overview: Cyclone Programming Script : CM C:\PEMicro\cyclone\supportfiles\supportFiles_ARM\NXP\iMX\nxp_imxrt1064_1x32x1meg.arp EM ;Erase Module QO C:\MyWorkspace\Test\Widget\Hardware\widgettestapp.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Test\Widget\Fingerprint\devicefingerprintapp.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Test\Widget\RTC_Cal\rtccal.elf PM ;Program Module RT ;Run Test/Calibration Code EM ;Erase Module QO C:\MyWorkspace\Application\Widget\finalapplication.elf PM ;Program Module PF DEVICE_FINGERPRINT 1F000 ;The RTC_DATA was generated by the devicefingerprintapp.elf test application PF RTC_DATA 1FF00 ;The RTC_DATA was generated by the rtccal.elf test application VM ;Verify Module The Run Test advanced control/automation feature is exclusive to the Cyclone FX model programmer. The latest Cyclone installation software and firmware includes the Run Test Feature as well as the Run Test API files PEtest.c and PEtest.h for including into test applications. The PROG programming software, which is a PC based programming software, also contains the same Run Test feature (independent of the Cyclone). PEmicro’s Cyclone programmers provide an easy way to automate running test code as part of the fully automated programming process. The user can use this feature to ensure that a target has passed test before final programming can occur. It also gives the user the capability to program dynamic data retrieved/generated by the test code along with the final application. “Run Test” Applications
Adding Run Tests to the Cyclone Programming Script
Run Test API Calls
Example Programming Images with Run Test
Image with Hardware Test (Pass/Fail)
Cyclone Programming Image (and Test Application) Overview:
Test Application Code (widgettestapp.elf):
Cyclone Programming Script:
Image That Fingerprints MCU Device (Pass/Fail, programs generated Data)
Cyclone Programming Image (and Test Application) Overview:
Test Application Code (widgettestapp.elf):
Cyclone Programming Script:
Image with 32.768Khz Crystal Calibration
(Pass/Fail, Interacts with Cyclone Operator, Programs Generated Data)Cyclone Programming Image (and Test Application) Overview:
Cyclone Programming Script:
Image With All Three Test Applications
(Hardware Test, Device Fingerprinting, 32.768Khz Crystal Calibration)Run Test Availability
Conclusion