Platform: USART driver enhancement for secure
USART driver in TF-M is not compliant with CMSIS USART driver
specification. Add following changes to conform CMSIS compliance.
- Add busy wait and block send after sending.
- Add power control and work mode control support. Ignore error
check currently since ARM_USART_CONTROL_TX and POWEROFF is not
implemented in platform driver.
Change-Id: I5c9c71f7448469803c6fed4bb13bf531496f626f
Signed-off-by: Mingyang Sun <mingyang.sun@arm.com>
diff --git a/platform/ext/common/uart_stdout.c b/platform/ext/common/uart_stdout.c
index 48ebe81..5a68697 100644
--- a/platform/ext/common/uart_stdout.c
+++ b/platform/ext/common/uart_stdout.c
@@ -18,7 +18,7 @@
#include <assert.h>
#include <stdio.h>
-#include <string.h>
+#include <stdint.h>
#include "Driver_USART.h"
#include "target_cfg.h"
#include "device_cfg.h"
@@ -28,12 +28,18 @@
/* Imports USART driver */
extern ARM_DRIVER_USART TFM_DRIVER_STDIO;
-static void uart_putc(unsigned char c)
+static int uart_send_string(const unsigned char *str, uint32_t len)
{
- int32_t ret = ARM_DRIVER_OK;
+ int32_t ret;
- ret = TFM_DRIVER_STDIO.Send(&c, 1);
- ASSERT_HIGH(ret);
+ ret = TFM_DRIVER_STDIO.Send(str, len);
+ if (ret != ARM_DRIVER_OK) {
+ return 0;
+ }
+ /* Add a busy wait after sending. */
+ while (TFM_DRIVER_STDIO.GetStatus().tx_busy);
+
+ return TFM_DRIVER_STDIO.GetTxCount();
}
/* Redirects printf to TFM_DRIVER_STDIO in case of ARMCLANG*/
@@ -42,12 +48,13 @@
* TFM_DRIVER_STDIO
*/
FILE __stdout;
-
/* __ARMCC_VERSION is only defined starting from Arm compiler version 6 */
int fputc(int ch, FILE *f)
{
+ (void)f;
+
/* Send byte to USART */
- uart_putc(ch);
+ (void)uart_send_string((const unsigned char *)&ch, 1);
/* Return character written */
return ch;
@@ -56,21 +63,16 @@
/* Redirects printf to TFM_DRIVER_STDIO in case of GNUARM */
int _write(int fd, char *str, int len)
{
- int i;
+ (void)fd;
- for (i = 0; i < len; i++) {
- /* Send byte to USART */
- uart_putc(str[i]);
- }
-
- /* Return the number of characters written */
- return len;
+ /* Send string and return the number of characters written */
+ return uart_send_string((const unsigned char *)str, (uint32_t)len);
}
#elif defined(__ICCARM__)
int putchar(int ch)
{
/* Send byte to USART */
- uart_putc(ch);
+ (void)uart_send_string((const unsigned char *)&ch, 1);
/* Return character written */
return ch;
@@ -79,18 +81,26 @@
void stdio_init(void)
{
- int32_t ret = ARM_DRIVER_OK;
+ int32_t ret;
ret = TFM_DRIVER_STDIO.Initialize(NULL);
ASSERT_HIGH(ret);
+ ret = TFM_DRIVER_STDIO.PowerControl(ARM_POWER_FULL);
+ ASSERT_HIGH(ret);
+
ret = TFM_DRIVER_STDIO.Control(ARM_USART_MODE_ASYNCHRONOUS,
DEFAULT_UART_BAUDRATE);
ASSERT_HIGH(ret);
+
+ (void)TFM_DRIVER_STDIO.Control(ARM_USART_CONTROL_TX, 1);
}
void stdio_uninit(void)
{
- int32_t ret = ARM_DRIVER_OK;
+ int32_t ret;
+
+ (void)TFM_DRIVER_STDIO.PowerControl(ARM_POWER_OFF);
+
ret = TFM_DRIVER_STDIO.Uninitialize();
ASSERT_HIGH(ret);
}