stlink: fix computation of trace prescaler
authorAntonio Borneo <borneo.antonio@gmail.com>
Sat, 31 Oct 2020 13:55:10 +0000 (14:55 +0100)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 7 Nov 2020 20:54:08 +0000 (20:54 +0000)
Use integer rounding for the computation of prescaler.
Improve the test of prescaler range, knowing its value would be
decremented before being written in TPIU ACPR.

Change-Id: I041dde1dca41323904e36a6b6975028a6de902b3
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/5909
Tested-by: jenkins
src/jtag/drivers/stlink_usb.c

index 8ab73cd12752d677dfda640ec2416dcc60cdb32f..c54e2cc192e0900eef4392fc0581b2b82eb5b57e 100644 (file)
@@ -2989,7 +2989,6 @@ static int stlink_config_trace(void *handle, bool enabled,
                uint16_t *prescaler)
 {
        struct stlink_usb_handle_s *h = handle;
-       uint16_t presc;
 
        if (enabled && (!(h->version.flags & STLINK_F_HAS_TRACE) ||
                        pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART)) {
@@ -3012,12 +3011,17 @@ static int stlink_config_trace(void *handle, bool enabled,
        if (!*trace_freq)
                *trace_freq = max_trace_freq;
 
-       presc = traceclkin_freq / *trace_freq;
-
-       if (traceclkin_freq % *trace_freq > 0)
-               presc++;
+       unsigned int presc = (traceclkin_freq + *trace_freq / 2) / *trace_freq;
+       if (presc == 0 || presc > TPIU_ACPR_MAX_SWOSCALER + 1) {
+               LOG_ERROR("SWO frequency is not suitable. Please choose a different "
+                       "frequency.");
+               return ERROR_FAIL;
+       }
 
-       if (presc > TPIU_ACPR_MAX_SWOSCALER) {
+       /* Probe's UART speed must be within 3% of the TPIU's SWO baud rate. */
+       unsigned int max_deviation = (traceclkin_freq * 3) / 100;
+       if (presc * *trace_freq < traceclkin_freq - max_deviation ||
+                       presc * *trace_freq > traceclkin_freq + max_deviation) {
                LOG_ERROR("SWO frequency is not suitable. Please choose a different "
                        "frequency.");
                return ERROR_FAIL;