summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-04-20 13:07:42 -0700
committerRandall Spangler <rspangler@chromium.org>2012-04-20 14:01:11 -0700
commit9f552ff5aa043eddc5b6d59db09728d83faf97dd (patch)
treee7f39070eac9b14a9afa6363703eab0950e856cc
parenta05deade13c696643ca6f8cc216f78db015a7ddb (diff)
downloadchrome-ec-9f552ff5aa043eddc5b6d59db09728d83faf97dd.tar.gz
Implement 64-bit integer printing in uart_printf()
Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:7490 TEST=timerinfo; numbers should look reasonable Change-Id: I698be99c87bf311013427ac0ed9e93e5687f40c0
-rw-r--r--common/charge_state.h2
-rw-r--r--common/uart_buffering.c41
-rw-r--r--common/util.c46
-rw-r--r--core/cortex-m/timer.c28
-rw-r--r--include/uart.h11
-rw-r--r--include/util.h22
6 files changed, 109 insertions, 41 deletions
diff --git a/common/charge_state.h b/common/charge_state.h
index 0fe93b92a0..672dab3e8b 100644
--- a/common/charge_state.h
+++ b/common/charge_state.h
@@ -10,7 +10,7 @@
#define __CROS_EC_CHARGE_STATE_H
/* Time constants */
-#define MSEC ((uint64_t)1000)
+#define MSEC (1000ULL)
#define SECOND (MSEC * 1000)
#define MINUTE (SECOND * 60)
#define HOUR (MINUTE * 60)
diff --git a/common/uart_buffering.c b/common/uart_buffering.c
index 6393ff47be..6d08dbb9af 100644
--- a/common/uart_buffering.c
+++ b/common/uart_buffering.c
@@ -452,24 +452,40 @@ int uart_printf(const char *format, ...)
if (vstr == NULL)
vstr = "(NULL)";
} else {
- uint32_t v;
+ uint64_t v;
int is_negative = 0;
+ int is_64bit = 0;
int base = 10;
- /* TODO: (crosbug.com/p/7490) handle "%l" prefix for
- * uint64_t */
+ if (c == 'l') {
+ is_64bit = 1;
+ c = *format++;
+ }
/* Special-case: %T = current time */
- if (c == 'T')
- v = get_time().le.lo;
- else
+ if (c == 'T') {
+ v = get_time().val;
+ is_64bit = 1;
+ } else if (is_64bit) {
+ v = va_arg(args, uint64_t);
+ } else {
v = va_arg(args, uint32_t);
+ }
switch (c) {
case 'd':
- if ((int)v < 0) {
- is_negative = 1;
- v = -v;
+ if (is_64bit) {
+ if ((int64_t)v < 0) {
+ is_negative = 1;
+ if (v != (1ULL << 63))
+ v = -v;
+ }
+ } else {
+ if ((int)v < 0) {
+ is_negative = 1;
+ if (v != (1ULL << 31))
+ v = -(int)v;
+ }
}
break;
case 'u':
@@ -496,10 +512,9 @@ int uart_printf(const char *format, ...)
if (!v)
*(--vstr) = '0';
- while (v) {
- *(--vstr) = int_chars[v % base];
- v /= base;
- }
+ while (v)
+ *(--vstr) = int_chars[uint64divmod(&v, base)];
+
if (is_negative)
*(--vstr) = '-';
}
diff --git a/common/util.c b/common/util.c
index 40908cc5ce..fe30ffa518 100644
--- a/common/util.c
+++ b/common/util.c
@@ -144,7 +144,6 @@ void *memset(void *dest, int c, int len)
}
-/* Like strncpy(), but guarantees null termination */
char *strzcpy(char *dest, const char *src, int len)
{
char *d = dest;
@@ -155,3 +154,48 @@ char *strzcpy(char *dest, const char *src, int len)
*d = '\0';
return dest;
}
+
+
+int uint64divmod(uint64_t *n, int d)
+{
+ uint64_t q = 0, mask;
+ int r = 0;
+
+ /* Divide-by-zero returns zero */
+ if (!d) {
+ *n = 0;
+ return 0;
+ }
+
+ /* Common powers of 2 = simple shifts */
+ if (d == 2) {
+ r = *n & 1;
+ *n >>= 1;
+ return r;
+ } else if (d == 16) {
+ r = *n & 0xf;
+ *n >>= 4;
+ return r;
+ }
+
+ /* If v fits in 32-bit, we're done. */
+ if (*n <= 0xffffffff) {
+ uint32_t v32 = *n;
+ r = v32 % d;
+ *n = v32 / d;
+ return r;
+ }
+
+ /* Otherwise do integer division the slow way. */
+ for (mask = (1ULL << 63); mask; mask >>= 1) {
+ r <<= 1;
+ if (*n & mask)
+ r |= 1;
+ if (r >= d) {
+ r -= d;
+ q |= mask;
+ }
+ }
+ *n = q;
+ return r;
+}
diff --git a/core/cortex-m/timer.c b/core/cortex-m/timer.c
index 8d98287c46..e4915e76ad 100644
--- a/core/cortex-m/timer.c
+++ b/core/cortex-m/timer.c
@@ -167,29 +167,31 @@ DECLARE_CONSOLE_COMMAND(waitms, command_wait);
static int command_get_time(int argc, char **argv)
{
timestamp_t ts = get_time();
- uart_printf("Time: 0x%08x%08x us (%u %u)\n", ts.le.hi, ts.le.lo,
- ts.le.hi, ts.le.lo);
- return EC_SUCCESS;
+ uart_printf("Time: 0x%016lx = %ld us\n", ts.val, ts.val);
+ return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(gettime, command_get_time);
int command_timer_info(int argc, char **argv)
{
- timestamp_t ts = get_time();
+ uint64_t t = get_time().val;
+ uint64_t deadline = (uint64_t)clksrc_high << 32 |
+ __hw_clock_event_get();
int tskid;
- uart_printf("Time: 0x%08x%08x us\n"
- "Deadline: 0x%08x%08x us\n"
- "Active timers:\n",
- ts.le.hi, ts.le.lo, clksrc_high,
- __hw_clock_event_get());
+ uart_printf("Time: 0x%016lx us\n"
+ "Deadline: 0x%016lx -> %10ld us from now\n"
+ "Active timers:\n",
+ t, deadline, deadline - t);
for (tskid = 0; tskid < TASK_ID_COUNT; tskid++) {
- if (timer_running & (1<<tskid))
- uart_printf("Tsk %d tmr 0x%08x%08x\n", tskid,
- timer_deadline[tskid].le.hi,
- timer_deadline[tskid].le.lo);
+ if (timer_running & (1<<tskid)) {
+ uart_printf(" Tsk %2d 0x%016lx -> %10ld\n", tskid,
+ timer_deadline[tskid].val,
+ timer_deadline[tskid].val - t);
+ uart_flush_output();
+ }
}
return EC_SUCCESS;
}
diff --git a/include/uart.h b/include/uart.h
index 3ca34c67f1..67a2968d6c 100644
--- a/include/uart.h
+++ b/include/uart.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -46,16 +46,13 @@ int uart_puts(const char *outstr);
* string (%s)
* native int (signed/unsigned) (%d / %u / %x)
* int32_t / uint32_t (%d / %x)
+ * int64_t / uint64_t (%ld / %lu / %lx)
* pointer (%p)
* And the following special format codes:
* current time in us (%T)
- * including padding (%-5s, %8d, %08x)
- *
- * Support planned for:
- * int64_t / uint64_t (%ld / %lu / %lx)
+ * including padding (%-5s, %8d, %08x, %016lx)
*
- * Note: Floating point output (%f / %g) is not supported.
- */
+ * Floating point output (%f / %g) is not supported. */
int uart_printf(const char *format, ...);
/* Flushes output. Blocks until UART has transmitted all output. */
diff --git a/include/util.h b/include/util.h
index d11b3a587f..5b9dd364db 100644
--- a/include/util.h
+++ b/include/util.h
@@ -1,15 +1,14 @@
-/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Various utility functions and macros */
-#ifndef __UTIL_H
-#define __UTIL_H
-
-#include <stdint.h>
+#ifndef __CROS_EC_UTIL_H
+#define __CROS_EC_UTIL_H
+#include "common.h"
#include "config.h"
/**
@@ -60,7 +59,18 @@ void *memset(void *dest, int c, int len);
int strcasecmp(const char *s1, const char *s2);
int strlen(const char *s);
int strtoi(const char *nptr, char **endptr, int base);
+
+/* Like strncpy(), but guarantees null termination. */
char *strzcpy(char *dest, const char *src, int len);
+
int tolower(int c);
-#endif /* __UTIL_H */
+/* 64-bit divide-and-modulo. Does the equivalent of:
+ *
+ * r = *n % d;
+ * *n /= d;
+ * return r;
+ */
+int uint64divmod(uint64_t *v, int by);
+
+#endif /* __CROS_EC_UTIL_H */