mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-18 16:03:22 +08:00
修改了Web后台的部分界面,增加了HAmqtt中的总电量传感器,后台新增mqtt上报频率设置
This commit is contained in:
420
mico-os/platform/MCU/ATSAMG55/peripherals/platform_uart.c
Normal file
420
mico-os/platform/MCU/ATSAMG55/peripherals/platform_uart.c
Normal file
@@ -0,0 +1,420 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_uart.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide UART driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_peripheral.h"
|
||||
#include "platform_logging.h"
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
#define DMA_INTERRUPT_FLAGS ( DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_FE )
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
|
||||
static IRQn_Type platform_flexcom_irq_numbers[] =
|
||||
{
|
||||
[0] = FLEXCOM0_IRQn,
|
||||
[1] = FLEXCOM1_IRQn,
|
||||
[2] = FLEXCOM2_IRQn,
|
||||
[3] = FLEXCOM3_IRQn,
|
||||
[4] = FLEXCOM4_IRQn,
|
||||
[5] = FLEXCOM5_IRQn,
|
||||
[6] = FLEXCOM6_IRQn,
|
||||
[7] = FLEXCOM7_IRQn,
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Static Function Declarations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_uart_init( platform_uart_driver_t* driver, const platform_uart_t* peripheral, const platform_uart_config_t* config, ring_buffer_t* optional_ring_buffer )
|
||||
{
|
||||
pdc_packet_t pdc_uart_packet, pdc_uart_tx_packet;
|
||||
OSStatus err = kNoErr;
|
||||
sam_usart_opt_t settings;
|
||||
bool hardware_shaking = false;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( ( driver != NULL ) && ( peripheral != NULL ) && ( config != NULL ), exit, err = kParamErr);
|
||||
require_action_quiet( (optional_ring_buffer->buffer != NULL ) && (optional_ring_buffer->size != 0), exit, err = kUnsupportedErr);
|
||||
|
||||
driver->rx_size = 0;
|
||||
driver->tx_size = 0;
|
||||
driver->rx_ring_buffer = optional_ring_buffer;
|
||||
driver->last_transmit_result = kNoErr;
|
||||
driver->last_receive_result = kNoErr;
|
||||
driver->peripheral = (platform_uart_t*)peripheral;
|
||||
#ifndef NO_MICO_RTOS
|
||||
mico_rtos_init_semaphore( &driver->tx_complete, 1 );
|
||||
mico_rtos_init_semaphore( &driver->rx_complete, 1 );
|
||||
mico_rtos_init_semaphore( &driver->sem_wakeup, 1 );
|
||||
mico_rtos_init_mutex ( &driver->tx_mutex );
|
||||
#else
|
||||
driver->tx_complete = false;
|
||||
driver->rx_complete = false;
|
||||
#endif
|
||||
|
||||
/* Set Tx and Rx pin mode to UART peripheral */
|
||||
platform_gpio_peripheral_pin_init( peripheral->tx_pin, ( peripheral->tx_pin_mux_mode | IOPORT_MODE_PULLUP ) );
|
||||
platform_gpio_peripheral_pin_init( peripheral->rx_pin, ( peripheral->rx_pin_mux_mode | IOPORT_MODE_PULLUP ) );
|
||||
|
||||
/* Init CTS and RTS pins (if available) */
|
||||
if ( peripheral->cts_pin != NULL && (config->flow_control == FLOW_CONTROL_CTS || config->flow_control == FLOW_CONTROL_CTS_RTS) )
|
||||
{
|
||||
hardware_shaking = true;
|
||||
platform_gpio_peripheral_pin_init( peripheral->cts_pin, ( peripheral->cts_pin_mux_mode | IOPORT_MODE_PULLUP ) );
|
||||
}
|
||||
|
||||
if ( peripheral->rts_pin != NULL && (config->flow_control == FLOW_CONTROL_CTS || config->flow_control == FLOW_CONTROL_CTS_RTS) )
|
||||
{
|
||||
hardware_shaking = true;
|
||||
platform_gpio_peripheral_pin_init( peripheral->rts_pin, ( peripheral->rts_pin_mux_mode | IOPORT_MODE_PULLUP ) );
|
||||
}
|
||||
|
||||
/* Enable the clock. */
|
||||
if( pmc_is_periph_clk_enabled( peripheral->peripheral_id ) == 0 ){
|
||||
flexcom_enable( peripheral->flexcom_base );
|
||||
}
|
||||
flexcom_set_opmode( peripheral->flexcom_base, FLEXCOM_USART );
|
||||
|
||||
/* Enable the receiver and transmitter. */
|
||||
usart_reset_tx( peripheral->port );
|
||||
usart_reset_rx( peripheral->port );
|
||||
|
||||
/* Disable all the interrupts. */
|
||||
usart_disable_interrupt( peripheral->port, 0xffffffff );
|
||||
|
||||
switch ( config->parity ) {
|
||||
case NO_PARITY:
|
||||
settings.parity_type = US_MR_PAR_NO;
|
||||
break;
|
||||
case EVEN_PARITY:
|
||||
settings.parity_type = US_MR_PAR_EVEN;
|
||||
break;
|
||||
case ODD_PARITY:
|
||||
settings.parity_type = US_MR_PAR_ODD;
|
||||
break;
|
||||
default:
|
||||
err = kParamErr;
|
||||
goto exit;
|
||||
}
|
||||
switch ( config->data_width) {
|
||||
case DATA_WIDTH_5BIT:
|
||||
settings.char_length = US_MR_CHRL_5_BIT;
|
||||
break;
|
||||
case DATA_WIDTH_6BIT:
|
||||
settings.char_length = US_MR_CHRL_6_BIT;
|
||||
break;
|
||||
case DATA_WIDTH_7BIT:
|
||||
settings.char_length = US_MR_CHRL_7_BIT;
|
||||
break;
|
||||
case DATA_WIDTH_8BIT:
|
||||
settings.char_length = US_MR_CHRL_8_BIT;
|
||||
break;
|
||||
case DATA_WIDTH_9BIT:
|
||||
settings.char_length = US_MR_MODE9;
|
||||
break;
|
||||
default:
|
||||
err = kParamErr;
|
||||
goto exit;
|
||||
}
|
||||
settings.baudrate = config->baud_rate;
|
||||
settings.stop_bits = ( config->stop_bits == STOP_BITS_1 ) ? US_MR_NBSTOP_1_BIT : US_MR_NBSTOP_2_BIT;
|
||||
settings.channel_mode= US_MR_CHMODE_NORMAL;
|
||||
|
||||
/* Configure USART in serial mode. */
|
||||
if (!hardware_shaking) {
|
||||
usart_init_rs232( peripheral->port, &settings, sysclk_get_peripheral_hz());
|
||||
} else {
|
||||
usart_init_hw_handshaking( peripheral->port, &settings, sysclk_get_peripheral_hz());
|
||||
}
|
||||
|
||||
/* Enable uart interrupt */
|
||||
NVIC_SetPriority( platform_flexcom_irq_numbers[peripheral->uart_id], 0x06 );
|
||||
NVIC_EnableIRQ( platform_flexcom_irq_numbers[peripheral->uart_id] );
|
||||
|
||||
/* Enable PDC transmit */
|
||||
pdc_enable_transfer( usart_get_pdc_base( peripheral->port ), PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN );
|
||||
pdc_disable_transfer( usart_get_pdc_base( driver->peripheral->port ), PERIPH_PTCR_TXTDIS );
|
||||
|
||||
pdc_uart_packet.ul_addr = (uint32_t)driver->rx_ring_buffer->buffer;
|
||||
pdc_uart_packet.ul_size = (uint32_t)driver->rx_ring_buffer->size;
|
||||
pdc_rx_init( usart_get_pdc_base( peripheral->port ), &pdc_uart_packet, &pdc_uart_packet );
|
||||
|
||||
pdc_uart_tx_packet.ul_addr = (uint32_t)0;
|
||||
pdc_uart_tx_packet.ul_size = (uint32_t)1;
|
||||
|
||||
pdc_tx_init( usart_get_pdc_base( driver->peripheral->port ), &pdc_uart_tx_packet, NULL );
|
||||
|
||||
usart_enable_interrupt( peripheral->port, US_IER_ENDRX | US_IER_RXBUFF | US_IER_RXRDY | US_IER_ENDTX );
|
||||
|
||||
/* Enable the receiver and transmitter. */
|
||||
usart_enable_tx( peripheral->port );
|
||||
usart_enable_rx( peripheral->port );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable( );
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_uart_deinit( platform_uart_driver_t* driver )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
require_action_quiet( ( driver != NULL ), exit, err = kParamErr);
|
||||
|
||||
usart_disable_interrupt( driver->peripheral->port, 0xffffffff );
|
||||
|
||||
NVIC_DisableIRQ( platform_flexcom_irq_numbers[driver->peripheral->uart_id] );
|
||||
|
||||
pdc_disable_transfer( usart_get_pdc_base( driver->peripheral->port ), PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS );
|
||||
|
||||
usart_disable_tx( driver->peripheral->port );
|
||||
usart_disable_rx( driver->peripheral->port );
|
||||
|
||||
if( pmc_is_periph_clk_enabled( driver->peripheral->peripheral_id ) == 1 ){
|
||||
flexcom_disable( driver->peripheral->flexcom_base );
|
||||
}
|
||||
|
||||
platform_gpio_deinit( driver->peripheral->tx_pin );
|
||||
platform_gpio_deinit( driver->peripheral->rx_pin );
|
||||
|
||||
if ( driver->peripheral->cts_pin != NULL )
|
||||
{
|
||||
platform_gpio_deinit( driver->peripheral->cts_pin );
|
||||
}
|
||||
|
||||
if ( driver->peripheral->rts_pin != NULL )
|
||||
{
|
||||
platform_gpio_deinit( driver->peripheral->rts_pin );
|
||||
}
|
||||
|
||||
#ifndef NO_MICO_RTOS
|
||||
mico_rtos_deinit_semaphore(&driver->rx_complete);
|
||||
mico_rtos_deinit_semaphore(&driver->tx_complete);
|
||||
#endif
|
||||
|
||||
driver->peripheral = NULL;
|
||||
memset( driver, 0, sizeof(platform_uart_driver_t) );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_uart_transmit_bytes( platform_uart_driver_t* driver, const uint8_t* data_out, uint32_t size )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
pdc_packet_t pdc_uart_packet;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
#ifndef NO_MICO_RTOS
|
||||
mico_rtos_lock_mutex( &driver->tx_mutex );
|
||||
#endif
|
||||
|
||||
require_action_quiet( ( driver != NULL ) && ( data_out != NULL ) && ( size != 0 ), exit, err = kParamErr);
|
||||
|
||||
/* reset DMA transmission result. the result is assigned in interrupt handler */
|
||||
driver->last_transmit_result = kGeneralErr;
|
||||
driver->tx_size = size;
|
||||
|
||||
pdc_uart_packet.ul_addr = (uint32_t) data_out;
|
||||
pdc_uart_packet.ul_size = size;
|
||||
pdc_tx_init( usart_get_pdc_base( driver->peripheral->port ), &pdc_uart_packet, NULL);
|
||||
|
||||
/* Enable Tx DMA transmission */
|
||||
pdc_enable_transfer( usart_get_pdc_base( driver->peripheral->port ), PERIPH_PTCR_TXTEN );
|
||||
|
||||
#ifndef NO_MICO_RTOS
|
||||
mico_rtos_get_semaphore( &driver->tx_complete, MICO_NEVER_TIMEOUT );
|
||||
#else
|
||||
while( driver->tx_complete == false);
|
||||
driver->tx_complete = false;
|
||||
#endif
|
||||
|
||||
exit:
|
||||
#ifndef NO_MICO_RTOS
|
||||
mico_rtos_unlock_mutex( &driver->tx_mutex );
|
||||
#endif
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_uart_receive_bytes( platform_uart_driver_t* driver, uint8_t* data_in, uint32_t expected_data_size, uint32_t timeout_ms )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
uint32_t transfer_size;
|
||||
|
||||
//platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( ( driver != NULL ) && ( data_in != NULL ) && ( expected_data_size != 0 ), exit, err = kParamErr);
|
||||
require_action_quiet( driver->rx_ring_buffer != NULL , exit, err = kUnsupportedErr);
|
||||
|
||||
while ( expected_data_size != 0 )
|
||||
{
|
||||
transfer_size = MIN(driver->rx_ring_buffer->size / 2, expected_data_size);
|
||||
|
||||
/* Check if ring buffer already contains the required amount of data. */
|
||||
if ( transfer_size > ring_buffer_used_space( driver->rx_ring_buffer ) )
|
||||
{
|
||||
/* Set rx_size and wait in rx_complete semaphore until data reaches rx_size or timeout occurs */
|
||||
driver->rx_size = transfer_size;
|
||||
|
||||
#ifndef NO_MICO_RTOS
|
||||
if ( mico_rtos_get_semaphore( &driver->rx_complete, timeout_ms ) != kNoErr )
|
||||
{
|
||||
driver->rx_size = 0;
|
||||
err = kTimeoutErr;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Reset rx_size to prevent semaphore being set while nothing waits for the data */
|
||||
driver->rx_size = 0;
|
||||
#else
|
||||
driver->rx_complete = false;
|
||||
int delay_start = mico_rtos_get_time();
|
||||
while(driver->rx_complete == false){
|
||||
if(mico_rtos_get_time() >= delay_start + timeout_ms && timeout_ms != MICO_NEVER_TIMEOUT){
|
||||
driver->rx_size = 0;
|
||||
err = kTimeoutErr;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
driver->rx_size = 0;
|
||||
#endif
|
||||
}
|
||||
expected_data_size -= transfer_size;
|
||||
|
||||
// Grab data from the buffer
|
||||
do
|
||||
{
|
||||
uint8_t* available_data;
|
||||
uint32_t bytes_available;
|
||||
|
||||
ring_buffer_get_data( driver->rx_ring_buffer, &available_data, &bytes_available );
|
||||
bytes_available = MIN( bytes_available, transfer_size );
|
||||
memcpy( data_in, available_data, bytes_available );
|
||||
transfer_size -= bytes_available;
|
||||
data_in = ( (uint8_t*)data_in + bytes_available );
|
||||
ring_buffer_consume( driver->rx_ring_buffer, bytes_available );
|
||||
}
|
||||
while ( transfer_size != 0 );
|
||||
}
|
||||
|
||||
require_action( expected_data_size == 0, exit, err = kReadErr);
|
||||
|
||||
exit:
|
||||
//platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t platform_uart_get_length_in_buffer( platform_uart_driver_t* driver )
|
||||
{
|
||||
return ring_buffer_used_space( driver->rx_ring_buffer );
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Interrupt Service Routines
|
||||
******************************************************/
|
||||
|
||||
void platform_uart_irq( platform_uart_driver_t* driver )
|
||||
{
|
||||
uint32_t status = usart_get_status( driver->peripheral->port );
|
||||
uint32_t mask = usart_get_interrupt_mask( driver->peripheral->port );
|
||||
Pdc* pdc_register = usart_get_pdc_base( driver->peripheral->port );
|
||||
|
||||
/* ENDTX flag is set when Tx DMA transfer is done */
|
||||
if ( ( mask & US_IMR_ENDTX ) && ( status & US_CSR_ENDTX ) )
|
||||
{
|
||||
pdc_packet_t dma_packet;
|
||||
|
||||
/* ENDTX is cleared when TCR or TNCR is set to a non-zero value, which effectively
|
||||
* starts another Tx DMA transaction. To work around this, disable Tx before
|
||||
* performing a dummy Tx init.
|
||||
*/
|
||||
pdc_disable_transfer( usart_get_pdc_base( driver->peripheral->port ), PERIPH_PTCR_TXTDIS );
|
||||
|
||||
dma_packet.ul_addr = (uint32_t)0;
|
||||
dma_packet.ul_size = (uint32_t)1;
|
||||
|
||||
pdc_tx_init( usart_get_pdc_base( driver->peripheral->port ), &dma_packet, NULL );
|
||||
|
||||
/* Notifies waiting thread that Tx DMA transfer is complete */
|
||||
#ifndef NO_MICO_RTOS
|
||||
mico_rtos_set_semaphore( &driver->tx_complete );
|
||||
#else
|
||||
driver->tx_complete = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ENDRX flag is set when RCR is 0. RNPR and RNCR values are then copied into
|
||||
* RPR and RCR, respectively, while the RX tranfer continues. We now need to
|
||||
* prepare RNPR and RNCR for the next iteration.
|
||||
*/
|
||||
if ( ( mask & US_IMR_ENDRX ) && ( status & US_CSR_ENDRX ) )
|
||||
{
|
||||
pdc_register->PERIPH_RNPR = (uint32_t)driver->rx_ring_buffer->buffer;
|
||||
pdc_register->PERIPH_RNCR = (uint32_t)driver->rx_ring_buffer->size;
|
||||
}
|
||||
|
||||
/* RXRDY interrupt is triggered and flag is set when a new character has been
|
||||
* received but not yet read from the US_RHR. When this interrupt executes,
|
||||
* the DMA engine already read the character out from the US_RHR and RXRDY flag
|
||||
* is no longer asserted. The code below updates the ring buffer parameters
|
||||
* to keep them current
|
||||
*/
|
||||
if ( ( mask & US_IMR_RXRDY ) )
|
||||
{
|
||||
driver->rx_ring_buffer->tail = driver->rx_ring_buffer->size - pdc_register->PERIPH_RCR;
|
||||
|
||||
// Notify thread if sufficient data are available
|
||||
if ( ( driver->rx_size > 0 ) && ( ring_buffer_used_space( driver->rx_ring_buffer ) >= driver->rx_size ) )
|
||||
{
|
||||
#ifndef NO_MICO_RTOS
|
||||
mico_rtos_set_semaphore( &driver->rx_complete );
|
||||
#else
|
||||
driver->rx_complete = true;
|
||||
#endif
|
||||
driver->rx_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user