/** * \file * \brief ATXMEGA's ATCA Hardware abstraction layer for SWI interface over UART drivers. * * Prerequisite: add UART Polled support to application in Atmel Studio * * \copyright (c) 2015-2020 Microchip Technology Inc. and its subsidiaries. * * \page License * * Subject to your compliance with these terms, you may use Microchip software * and any derivatives exclusively with Microchip products. It is your * responsibility to comply with third party license terms applicable to your * use of third party software (including open source software) that may * accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, * SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE * OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF * MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE * FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL * LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED * THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR * THIS SOFTWARE. */ #include #include #include "swi_uart_samd21_asf.h" #include "basic/atca_helpers.h" /** \defgroup hal_ Hardware abstraction layer (hal_) * * \brief * These methods define the hardware abstraction layer for communicating with a CryptoAuth device * @{ */ /** \brief usart configuration struct */ static struct usart_config config_usart; struct port_config pin_conf; //for DEBUG purpose /** \brief - this HAL implementation assumes you've included the ASF SERCOM UART libraries in your project, otherwise, the HAL layer will not compile because the ASF UART drivers are a dependency * */ /** \brief Implementation of SWI UART init. * \param[in] instance instance * \return ATCA_SUCCESS on success, otherwise an error code. */ ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance) { #ifdef DEBUG_PIN port_get_config_defaults(&pin_conf); pin_conf.direction = PORT_PIN_DIR_OUTPUT; port_pin_set_config(DEBUG_PIN_1, &pin_conf); port_pin_set_config(DEBUG_PIN_2, &pin_conf); port_pin_set_output_level(DEBUG_PIN_1, HIGH); port_pin_set_output_level(DEBUG_PIN_2, HIGH); #endif ATCA_STATUS status = ATCA_SUCCESS; usart_get_config_defaults(&config_usart); // Set data size to 7 config_usart.character_size = USART_CHARACTER_SIZE_7BIT; // Set parity to no parity config_usart.parity = USART_PARITY_NONE; // Set data byte to one stopbit config_usart.stopbits = USART_STOPBITS_1; // Set baudrate to 230400 config_usart.baudrate = 230400; #ifdef __SAMD21J18A__ config_usart.mux_setting = EXT3_UART_SERCOM_MUX_SETTING; config_usart.pinmux_pad0 = EXT3_UART_SERCOM_PINMUX_PAD0; config_usart.pinmux_pad1 = EXT3_UART_SERCOM_PINMUX_PAD1; config_usart.pinmux_pad2 = EXT3_UART_SERCOM_PINMUX_PAD2; config_usart.pinmux_pad3 = EXT3_UART_SERCOM_PINMUX_PAD3; #endif #ifdef __SAMR21G18A__ config_usart.mux_setting = EXT1_UART_SERCOM_MUX_SETTING; config_usart.pinmux_pad0 = EXT1_UART_SERCOM_PINMUX_PAD0; config_usart.pinmux_pad1 = EXT1_UART_SERCOM_PINMUX_PAD1; config_usart.pinmux_pad2 = EXT1_UART_SERCOM_PINMUX_PAD2; config_usart.pinmux_pad3 = EXT1_UART_SERCOM_PINMUX_PAD3; #endif switch (instance->bus_index) { case 0: status = usart_init(&(instance->usart_instance), SERCOM0, &config_usart); break; case 1: status = usart_init(&(instance->usart_instance), SERCOM1, &config_usart); break; case 2: status = usart_init(&(instance->usart_instance), SERCOM2, &config_usart); break; case 3: status = usart_init(&(instance->usart_instance), SERCOM3, &config_usart); break; case 4: status = usart_init(&(instance->usart_instance), SERCOM4, &config_usart); break; case 5: status = usart_init(&(instance->usart_instance), SERCOM5, &config_usart); break; } usart_enable(&(instance->usart_instance)); return status; } /** \brief Implementation of SWI UART deinit. * \param[in] instance instance * \return ATCA_SUCCESS on success, otherwise an error code. */ ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance) { ATCA_STATUS status = ATCA_SUCCESS; usart_reset(&(instance->usart_instance)); return status; } /** \brief implementation of SWI UART change baudrate. * \param[in] instance instance * \param[in] baudrate (typically 230400 , 160000 or 115200) */ void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate) { // Disable UART module usart_disable(&(instance->usart_instance)); // Set baudrate for UART module config_usart.baudrate = baudrate; switch (instance->bus_index) { case 0: usart_init(&(instance->usart_instance), SERCOM0, &config_usart); break; case 1: usart_init(&(instance->usart_instance), SERCOM1, &config_usart); break; case 2: usart_init(&(instance->usart_instance), SERCOM2, &config_usart); break; case 3: usart_init(&(instance->usart_instance), SERCOM3, &config_usart); break; case 4: usart_init(&(instance->usart_instance), SERCOM4, &config_usart); break; case 5: usart_init(&(instance->usart_instance), SERCOM5, &config_usart); break; } usart_enable(&(instance->usart_instance)); } /** \brief implementation of SWI UART change mode. * \param[in] instance instance * \param[in] mode (TRANSMIT_MODE or RECEIVE_MODE) */ void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode) { usart_disable(&(instance->usart_instance)); // Do nothing as the available time is not enough for setting the baudrate in ASF usart_enable(&(instance->usart_instance)); } /** \brief discover UART buses available for this hardware * this maintains a list of logical to physical bus mappings freeing the application * of the a-priori knowledge * \param[in] swi_uart_buses - an array of logical bus numbers * \param[in] max_buses - maximum number of buses the app wants to attempt to discover */ void swi_uart_discover_buses(int swi_uart_buses[], int max_buses) { /* if every SERCOM was a likely candidate bus, then would need to initialize the entire array to all SERCOM n numbers. * As an optimization and making discovery safer, make assumptions about bus-num / SERCOM map based on SAMD21 Xplained Pro board * If you were using a raw SAMD21 on your own board, you would supply your own bus numbers based on your particular hardware configuration. */ swi_uart_buses[0] = 4; // default samd21 for xplained dev board } /** \brief HAL implementation of SWI UART send byte over ASF. This function send one byte over UART * \param[in] instance instance * \param[in] data number of byte to send * \return ATCA_SUCCESS on success, otherwise an error code. */ ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data) { int8_t retries = 90; uint16_t bitdata = (uint16_t)data; // Send one byte over UART module #ifdef DEBUG_PIN port_pin_toggle_output_level(DEBUG_PIN_1); #endif while ((retries > 0) && (usart_write_wait(&(instance->usart_instance), bitdata) != STATUS_OK)) { retries--; } #ifdef DEBUG_PIN port_pin_toggle_output_level(DEBUG_PIN_1); #endif if (retries <= 0x00) { return ATCA_TIMEOUT; } else { return ATCA_SUCCESS; } } /** \brief HAL implementation of SWI UART receive bytes over ASF. This function receive one byte over UART * \param[in] instance instance * \param[out] data pointer to space to receive the data * \return ATCA_SUCCESS on success, otherwise an error code. */ ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data) { uint8_t retries = 100; // This retry is used to compensate the baudrate that do not match when receiving response uint16_t bitdata = 0x00; #ifdef DEBUG_PIN port_pin_toggle_output_level(DEBUG_PIN_2); #endif // Receive one byte over UART module while ((retries > 0) && (usart_read_wait(&(instance->usart_instance), &bitdata) != STATUS_OK)) { retries--; } #ifdef DEBUG_PIN port_pin_toggle_output_level(DEBUG_PIN_2); #endif *data = bitdata; if (retries <= 0x00) { return ATCA_TIMEOUT; } else { return ATCA_SUCCESS; } } /** @} */