summaryrefslogtreecommitdiff
path: root/chip/stm32/usart_host_command.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/stm32/usart_host_command.c')
-rw-r--r--chip/stm32/usart_host_command.c616
1 files changed, 0 insertions, 616 deletions
diff --git a/chip/stm32/usart_host_command.c b/chip/stm32/usart_host_command.c
deleted file mode 100644
index f4d6a65fc4..0000000000
--- a/chip/stm32/usart_host_command.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* Copyright 2020 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.
- */
-
-#include "common.h"
-#include "clock.h"
-#include "dma.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "queue_policies.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "usart_rx_dma.h"
-#include "usart_host_command.h"
-#include "usart-stm32f4.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args)
-
-/*
- * Timeout to wait for complete request packet
- *
- * This value determines how long we should wait for entire packet to arrive.
- * USART host command handler should wait for at least 75% of
- * EC_MSG_DEADLINE_MS, before declaring timeout and dropping the packet.
- *
- * This timeout should be less than host's driver timeout to make sure that
- * last packet can be successfully discarded before AP attempts to resend
- * request. AP driver waits for EC_MSG_DEADLINE_MS = 200 before attempting a
- * retry.
- */
-#define USART_REQ_RX_TIMEOUT (150 * MSEC)
-
-/*
- * Timeout to wait for overrun bytes on USART
- *
- * This values determines how long call to process_request should be deferred
- * in case host is sending extra bytes. This value is based on DMA buffer size.
- *
- * There is no guarantee that AP will send continuous bytes on usart. Wait
- * for USART_DEFERRED_PROCESS_REQ_TIMEOUT_US to check if host is sending
- * extra bytes.
- * Note: This value affects the response latency.
- */
-#define USART_DEFERRED_PROCESS_REQ_TIMEOUT 300
-
-/*
- * Max data size for a version 3 request/response packet. This is big enough
- * to handle a request/response header, flash write offset/size and 512 bytes
- * of request payload or 224 bytes of response payload.
- */
-#define USART_MAX_REQUEST_SIZE 0x220
-#define USART_MAX_RESPONSE_SIZE 0x100
-
-/*
- * FIFO size for USART DMA. Should be big enough to handle worst case
- * data processing
- */
-#define USART_DMA_FIFO_SIZE 0x110
-
-/* Local definitions */
-
-/*
- * Raw USART RX/TX byte buffers.
- */
-static uint8_t usart_in_buffer[USART_MAX_REQUEST_SIZE] __aligned(4);
-static uint8_t usart_out_buffer[USART_MAX_RESPONSE_SIZE] __aligned(4);
-
-/*
- * Maintain head position of in buffer
- * Head always starts with zero and goes up to max bytes.
- * Once the buffer contents are read, it should go back to zero.
- */
-static uint16_t usart_in_head;
-
-/*
- * Maintain head position of out buffer
- * Head always starts from zero and goes up to max bytes.
- * Head is moved by tx interrupt handler to response size sent by host command
- * task. Once all the bytes are sent (head == tail) both should go back to 0.
- */
-static uint16_t usart_out_head;
-
-/*
- * Once the response is ready, get the datalen
- */
-static uint16_t usart_out_datalen;
-
-/*
- * Enumeration to maintain different states of incoming request from
- * host
- */
-static enum uart_host_command_state {
- /*
- * USART host command handler not enabled.
- */
- USART_HOST_CMD_STATE_DISABLED,
-
- /*
- * Ready to receive next request
- * This state represents USART layer is initialized and ready to
- * receive host request. Once the response is sent, current_state is
- * reset to this state to accept next packet.
- */
- USART_HOST_CMD_READY_TO_RX,
-
- /*
- * Receiving request
- * After first byte is received current_state is moved to receiving
- * state until all the header bytes + datalen bytes are received.
- * If host_request_timeout was called in this state, it would be
- * because of an underrun situation.
- */
- USART_HOST_CMD_RECEIVING,
-
- /*
- * Receiving complete
- * Once all the header bytes + datalen bytes are received, current_state
- * is moved to complete. Ideally, host should wait for response or retry
- * timeout before sending anymore bytes, otherwise current_state will
- * be moved to overrun to represent extra bytes sent by host.
- */
- USART_HOST_CMD_COMPLETE,
-
- /*
- * Processing request
- * Once the process_request starts processing usart_in_buffer,
- * current_state is moved to processing state. Host should not send
- * any bytes in this state as it would be considered contiguous
- * request.
- */
- USART_HOST_CMD_PROCESSING,
-
- /*
- * Sending response
- * Once host task is ready with the response bytes, current_state is
- * moved to sending state.
- */
- USART_HOST_CMD_SENDING,
-
- /*
- * Received bad data
- * If bad packet header is received, current_state is moved to rx_bad
- * state and after rx_timeout all the bytes are dropped.
- */
- USART_HOST_CMD_RX_BAD,
-
- /*
- * Receiving data overrun bytes
- * If extra bytes are received after current_state is in complete,
- * host is sending extra bytes which indicates data overrun.
- */
- USART_HOST_CMD_RX_OVERRUN,
-
-} current_state __aligned(4);
-
-/*
- * This diagram is the state machine representation of USART host
- * command layer.
- *
- * This layer is responsible for checking packet integrity of incoming bytes
- * on usart transceiver. It will only process packet header to check version,
- * data_len. This layer will not process payload bytes.
- *
- * STATE = USART_HOST_CMD_STATE_DISABLED
- *
- * Initialize USART and local variables
- *
- * STATE = USART_HOST_CMD_READY_TO_RX
- *
- * |<---------- HOST RETRY TIMEOUT = 200 ms ---------->|
- * |
- * |--------------USART_REQ_RX_TIMEOUT------>|
- * | Underrun if request not complete -->|
- * | |<-- USART ready to rx
- * |____REQUEST____ ____REQUEST____
- * | | | | | |
- * | HDR | DATA | | HDR | DATA |
- * |_____|_________| |_____|_________|
- * |
- * |<-- Request packet start
- * |
- * STATE = USART_HOST_CMD_RECEIVING
- * |
- * |<-- HDR received, now we will wait for data len bytes
- * |
- * If bad packet is received, move state to rx_bad
- * STATE = USART_HOST_CMD_RX_BAD
- * Ignore data processing, print status on console and reset layer -----------
- * | |
- * |<-- Request packet end (data rx complete) |
- * | |
- * If request_timeout is called, it represents packet underrun |
- * Ignore data processing, print status on console and reset layer -----------
- * | |
- * STATE = USART_HOST_CMD_COMPLETE |
- * | |
- * |<-- Deferred call to process request |
- * | |
- * If extra byte is received, move state to overrun |
- * STATE = USART_HOST_CMD_RX_OVERRUN |
- * Ignore data processing, print status on console and reset layer -----------
- * | |
- * -->| |<-- USART_DEFERRED_PROCESS_REQ_TIMEOUT |
- * | Start process request |
- * | |
- * STATE = USART_HOST_CMD_PROCESSING |
- * | |
- * Send ec_host_request to host command task |
- * |<-- Packet sent to host command task |
- * >| |<-- host command task process time |
- * |<-- host command task ready for response |
- * | |
- * STATE = USART_HOST_CMD_SENDING |
- * | |
- * |____RESPONSE____ |
- * | | | |
- * | HDR | DATA | |
- * |_____|__________| |
- * | |
- * |<-- Response send complete |
- * |
- * STATE = USART_HOST_CMD_READY_TO_RX <------------------------------
- */
-
-/*
- * Local function definition
- */
-static void usart_host_command_reset(void);
-static void usart_host_command_request_timeout(void);
-static void usart_host_command_process_request(void);
-static void usart_host_command_process_response(struct host_packet *pkt);
-/*
- * Local variable declaration
- */
-
-/*
- * Configure dma instance for rx
- *
- * STM32_DMAS_USART1_RX is the DMA channel to be used for reception. This DMA
- * channel is for the USART peripheral.
- *
- * A unnamed, valid, empty usart_rx_dma_state structure is required to manage
- * DMA based transmission.
- *
- * USART_DMA_FIFO_SIZE is size of the valid, unnamed DMA circular buffer.
- * This buffer is large enough to process worst case interrupt latency this
- * layer can encounter.
- */
-static struct usart_rx_dma const usart_host_command_rx_dma = {
- .usart_rx = {
- .producer_ops = {
- .read = NULL,
- },
- .init = usart_rx_dma_init,
- .interrupt = usart_host_command_rx_dma_interrupt,
- .info = USART_RX_DMA_INFO,
- },
- .state = &((struct usart_rx_dma_state) {}),
- .fifo_buffer = ((uint8_t[USART_DMA_FIFO_SIZE]) {}),
- .fifo_size = USART_DMA_FIFO_SIZE,
- .channel = STM32_DMAS_USART1_RX,
-};
-
-/*
- * Configure USART structure with hardware, interrupt handlers, baudrate.
- */
-static struct usart_config const tl_usart = {
- .hw = &CONFIG_UART_HOST_COMMAND_HW,
- .rx = &usart_host_command_rx_dma.usart_rx,
- .tx = &usart_host_command_tx_interrupt,
- .state = &((struct usart_state){}),
- .baud = CONFIG_UART_HOST_COMMAND_BAUD_RATE,
- .flags = 0,
-};
-
-/*
- * Local function declaration
- */
-
-/*
- * This function will be called only if request rx timed out.
- * Drop the packet and put tl state into RX_READY
- */
-static void usart_host_command_request_timeout(void)
-{
- switch (current_state) {
- case USART_HOST_CMD_RECEIVING:
- /* If state is receiving then timeout was hit due to underrun */
- CPRINTS("USART HOST CMD ERROR: Request underrun detected.");
- break;
-
- case USART_HOST_CMD_RX_OVERRUN:
- /* If state is rx_overrun then timeout was hit because
- * process request was cancelled and extra rx bytes were
- * dropped
- */
- CPRINTS("USART HOST CMD ERROR: Request overrun detected.");
- break;
-
- case USART_HOST_CMD_RX_BAD:
- /* If state is rx_bad then packet header was bad and process
- * request was cancelled to drop all incoming bytes.
- */
- CPRINTS("USART HOST CMD ERROR: Bad packet header detected.");
- break;
-
- default:
- CPRINTS("USART HOST CMD ERROR: Request timeout mishandled");
- }
-
- /* Reset host command layer to accept new request */
- usart_host_command_reset();
-}
-DECLARE_DEFERRED(usart_host_command_request_timeout);
-
-/*
- * This function is called from interrupt handler after entire packet is
- * received.
- */
-static void usart_host_command_process_request(void)
-{
- /* Handle usart_in_buffer as ec_host_request */
- struct ec_host_request *ec_request =
- (struct ec_host_request *)usart_in_buffer;
-
- /* Prepare host_packet for host command task */
- static struct host_packet uart_packet;
-
- /*
- * Disable interrupts before processing request to be sent
- * to host command task.
- */
- interrupt_disable();
-
- /*
- * In case rx interrupt handler was called in this function's prologue,
- * host was trying to send extra byte(s) exactly when
- * USART_DEFERRED_PROCESS_REQ_TIMEOUT expired. If state is
- * not USART_HOST_CMD_COMPLETE, overrun condition is already
- * handled.
- */
- if (current_state != USART_HOST_CMD_COMPLETE) {
- /* Enable interrupts before exiting this function. */
- interrupt_enable();
-
- return;
- }
-
- /* Move current_state to USART_HOST_CMD_PROCESSING */
- current_state = USART_HOST_CMD_PROCESSING;
-
- /* Enable interrupts as current_state is safely handled. */
- interrupt_enable();
-
- /*
- * Cancel deferred call to timeout handler as request
- * received was good.
- */
- hook_call_deferred(
- &usart_host_command_request_timeout_data,
- -1);
-
- uart_packet.send_response = usart_host_command_process_response;
- uart_packet.request = usart_in_buffer;
- uart_packet.request_temp = NULL;
- uart_packet.request_max = sizeof(usart_in_buffer);
- uart_packet.request_size =
- host_request_expected_size(ec_request);
- uart_packet.response = usart_out_buffer;
- uart_packet.response_max = sizeof(usart_out_buffer);
- uart_packet.response_size = 0;
- uart_packet.driver_result = EC_RES_SUCCESS;
-
- /* Process usart_packet */
- host_packet_receive(&uart_packet);
-}
-DECLARE_DEFERRED(usart_host_command_process_request);
-
-/*
- * This function is called from host command task after it is ready with a
- * response.
- */
-static void usart_host_command_process_response(struct host_packet *pkt)
-{
- /* Disable interrupts before entering critical section. */
- interrupt_disable();
-
- /*
- * Send host command response in usart_out_buffer via
- * tx_interrupt_handler.
- *
- * Send response if current state is USART_HOST_CMD_PROCESSING
- * state. If this layer is in any other state drop response and
- * let request timeout handler handle state transitions.
- */
- if (current_state != USART_HOST_CMD_PROCESSING) {
- /* Enable interrupts before exiting critical section. */
- interrupt_enable();
-
- return;
- }
-
- /* Move to sending state. */
- current_state = USART_HOST_CMD_SENDING;
-
- /* Enable interrupts before exiting critical section. */
- interrupt_enable();
-
- usart_out_datalen = pkt->response_size;
- usart_out_head = 0;
-
- /* Start sending response to host via usart tx by
- * triggering tx interrupt.
- */
- usart_tx_start(&tl_usart);
-}
-
-/*
- * This function will drop current request, clear buffers.
- */
-static void usart_host_command_reset(void)
-{
- /* Cancel deferred call to process_request. */
- hook_call_deferred(
- &usart_host_command_process_request_data,
- -1);
-
- /* Cancel deferred call to timeout handler. */
- hook_call_deferred(
- &usart_host_command_request_timeout_data,
- -1);
-
- /*
- * Disable interrupts before entering critical region
- * Operations in this section should be minimum to avoid
- * harming the real-time characteristics of the runtime.
- */
- interrupt_disable();
-
- /* Clear in buffer, head and datalen */
- usart_in_head = 0;
-
- /* Clear out buffer, head and datalen */
- usart_out_datalen = 0;
- usart_out_head = 0;
-
- /* Move to ready state*/
- current_state = USART_HOST_CMD_READY_TO_RX;
-
- /* Enable interrupts before exiting critical region
- */
- interrupt_enable();
-}
-
-/*
- * Exported functions
- */
-
-/*
- * Initialize USART host command layer.
- */
-void usart_host_command_init(void)
-{
- /* USART host command layer starts in DISABLED state */
- current_state = USART_HOST_CMD_STATE_DISABLED;
-
- /* Initialize transport uart */
- usart_init(&tl_usart);
-
- /* Initialize local variables */
- usart_in_head = 0;
- usart_out_head = 0;
- usart_out_datalen = 0;
-
- /* Move to ready state */
- current_state = USART_HOST_CMD_READY_TO_RX;
-}
-
-/*
- * Function to handle incoming bytes from DMA interrupt handler
- *
- */
-size_t usart_host_command_rx_append_data(struct usart_config const *config,
- const uint8_t *src, size_t count)
-{
- /* Define ec_host_request pointer to process in bytes later*/
- struct ec_host_request *ec_request =
- (struct ec_host_request *) usart_in_buffer;
-
- /* Once the header is received, store the datalen */
- static int usart_in_datalen;
-
- /*
- * Host can send extra bytes than in header data_len
- * Only copy valid bytes in buffer
- */
- if (current_state == USART_HOST_CMD_READY_TO_RX ||
- current_state == USART_HOST_CMD_RECEIVING ||
- (usart_in_head + count) < USART_MAX_REQUEST_SIZE) {
- /* Copy all the bytes from DMA FIFO */
- memcpy(usart_in_buffer + usart_in_head,
- src, count);
- }
-
- /*
- * Add incoming byte count to usart_in_head.
- * Even if overflow bytes are not copied in buffer, maintain
- * the overflow count so that packet can be dropped later in this
- * function.
- */
- usart_in_head += count;
-
- if (current_state == USART_HOST_CMD_READY_TO_RX) {
- /* Kick deferred call to request timeout handler */
- hook_call_deferred(&usart_host_command_request_timeout_data,
- USART_REQ_RX_TIMEOUT);
-
- /* Move current state to receiving */
- current_state = USART_HOST_CMD_RECEIVING;
- }
-
- if (usart_in_head >= sizeof(struct ec_host_request)) {
- /* Buffer has request header. Check header and get data_len */
- usart_in_datalen = host_request_expected_size(ec_request);
-
- if (usart_in_datalen == 0 ||
- usart_in_datalen > USART_MAX_REQUEST_SIZE) {
- /* EC host request version not compatible or
- * reserved byte is not zero.
- */
- current_state = USART_HOST_CMD_RX_BAD;
- } else if (usart_in_head == usart_in_datalen) {
- /*
- * Once all the datalen bytes are received, wait for
- * USART_DEFERRED_PROCESS_REQ_TIMEOUT to call
- * process_request function. This is to catch overrun
- * bytes before processing the packet.
- */
- hook_call_deferred(
- &usart_host_command_process_request_data,
- USART_DEFERRED_PROCESS_REQ_TIMEOUT);
-
- /* If no data in request, packet is complete */
- current_state = USART_HOST_CMD_COMPLETE;
- } else if (usart_in_head > usart_in_datalen) {
- /* Cancel deferred call to process_request */
- hook_call_deferred(
- &usart_host_command_process_request_data,
- -1);
-
- /* Move state to overrun*/
- current_state = USART_HOST_CMD_RX_OVERRUN;
- }
- }
-
- if (current_state == USART_HOST_CMD_PROCESSING)
- /* Host should not send data before receiving a response.
- * Since the request was already sent to host command task,
- * just notify console about this. After response is sent
- * dma will be cleared to handle next packet
- */
- CPRINTS("USART HOST CMD ERROR: Contiguous packets detected.");
-
- /* Return count to show all incoming bytes were processed */
- return count;
-}
-
-/*
- * This function processes the outgoing bytes from tl usart.
- */
-size_t usart_host_command_tx_remove_data(struct usart_config const *config,
- uint8_t *dest)
-{
- size_t bytes_remaining = 0;
-
- if (current_state == USART_HOST_CMD_SENDING &&
- usart_out_datalen != 0) {
- /* Calculate byte_remaining in out_buffer */
- bytes_remaining = usart_out_datalen - usart_out_head;
-
- /* Get char on the head */
- *((uint8_t *) dest) = usart_out_buffer[usart_out_head++];
-
- /* If no bytes remaining, reset layer to accept next
- * request.
- */
- if (bytes_remaining == 0)
- usart_host_command_reset();
- }
-
- /* Return count of bytes remaining in out buffer */
- return bytes_remaining;
-}
-
-/*
- * Get protocol information
- */
-enum ec_status usart_get_protocol_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_get_protocol_info *r = args->response;
-
- memset(r, 0, sizeof(*r));
- r->protocol_versions |= BIT(3);
- r->max_request_packet_size = USART_MAX_REQUEST_SIZE;
- r->max_response_packet_size = USART_MAX_RESPONSE_SIZE;
- r->flags = EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED;
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}