| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 | /* * Copyright (c) 2022 Actions Technology Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */#include <soc.h>#include <board.h>#include <device.h>#include <drivers/uart.h>#include <drivers/uart_dma.h>#include <logging/log.h>#include <gps/gps.h>#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endifLOG_MODULE_REGISTER(gps_3352, LOG_LEVEL_INF);#define CONFIG_GPS_DEV_NAME "gps"#define GPS_UERT_DEV_NAME CONFIG_UART_2_NAME#ifdef CONFIG_SENSOR_GPS_UART_DMA#define GPS_DATA_BUFFER_SIZE 100#else#define UART_FIFO_MAX 16#define GPS_DATA_BUFFER_SIZE 100#endif // CONFIG_SENSOR_GPS_UART_DMAstruct ag3352_data {	const struct device *uart_gpio_dev;#ifdef CONFIG_SENSOR_GPS_UART_DMA	uint8_t temp_buff[GPS_DATA_BUFFER_SIZE];#else	uint8_t gps_data[2][GPS_DATA_BUFFER_SIZE];	uint8_t gpa_data_cur;	uint8_t gpa_data_prev;#endif // CONFIG_SENSOR_GPS_UART_DMA	gps_notify_t notify;	struct k_work gps_work;};static struct ag3352_data ag3352_data;#ifdef CONFIG_SENSOR_GPS_UART_DMAvoid uart_ctrl_rx_dma_start(struct device *dev){	uart_dma_receive(dev, ag3352_data.temp_buff, GPS_DATA_BUFFER_SIZE);	/* timeout���������Ƿ�����     */	// hrtimer_start(&g_tool_data.timer, UART_CTRL_RX_DMA_TIMEOUT_US, 0);}static void uart_ctrl_rx_dma_handler(const struct device *dma_dev, void *user_data,				     uint32_t channel, int status){	LOG_INF("%s", ag3352_data.temp_buff);	// hrtimer_stop(&g_tool_data.timer);	// ring_buf_put(&g_tool_data.rx_ringbuf, g_tool_data.temp_buff, UART_CTRL_RX_TEMP_BUF_SIZE);	uart_ctrl_rx_dma_start((struct device *)ag3352_data.uart_gpio_dev);}#elsestatic void uart_fifo_callback(const struct device *dev, void *user_data){	uint8_t rx_buff[UART_FIFO_MAX];	int read_size;	static uint8_t cnt;	uart_irq_update(dev);	if (uart_irq_rx_ready(dev)) {		read_size = uart_fifo_read(dev, rx_buff, UART_FIFO_MAX);		if (read_size == UART_FIFO_MAX)			LOG_ERR("uart fifo buffer overflow");		for (int i = 0; i < read_size; i++) {			switch (rx_buff[i]) {			case '$':				if (ag3352_data.gpa_data_cur)					ag3352_data.gpa_data_cur = 0;				else					ag3352_data.gpa_data_cur = 1;				memset(ag3352_data.gps_data[ag3352_data.gpa_data_cur], 0,				       sizeof(ag3352_data.gps_data[ag3352_data.gpa_data_cur]));				cnt = 0;				ag3352_data.gps_data[ag3352_data.gpa_data_cur][cnt] = rx_buff[i];				break;			case '\n':				cnt++;				ag3352_data.gps_data[ag3352_data.gpa_data_cur][cnt] = rx_buff[i];				ag3352_data.gpa_data_prev = ag3352_data.gpa_data_cur;				k_work_submit(&ag3352_data.gps_work);				break;			default:				cnt++;				ag3352_data.gps_data[ag3352_data.gpa_data_cur][cnt] = rx_buff[i];				/* protection data cannot exceed boundary */				if (cnt >= GPS_DATA_BUFFER_SIZE)					cnt--;				break;			}		}	}}#endif // CONFIG_SENSOR_GPS_UART_DMAstatic void ag3352_enable(const struct device *dev){	struct ag3352_data *data = (struct ag3352_data *)dev->data;	sys_write32(0x3, HGLFCLK_CTL);	sys_write32((sys_read32(CMU_DEVCLKEN1) | (1 << 31)), CMU_DEVCLKEN1);	sys_write32(0x101e, 0x400680F4); //GPIO61 set 0x1E: LOSCOUT	gps_reset_pin_ctl();	gps_wake_up_pin_ctl(true);#ifdef CONFIG_SENSOR_GPS_UART_DMA	uart_ctrl_rx_dma_start((struct device *)data->uart_gpio_dev);#else	uart_irq_rx_enable(data->uart_gpio_dev);#endif // CONFIG_SENSOR_GPS_UART_DMA}static void ag3352_disable(const struct device *dev){	struct ag3352_data *data = (struct ag3352_data *)dev->data;	// gps_wake_up_pin_ctl(false);#ifdef CONFIG_SENSOR_GPS_UART_DMA	uart_dma_receive_stop((struct device *)data->uart_gpio_dev);#else	uart_irq_rx_disable(data->uart_gpio_dev);#endif // CONFIG_SENSOR_GPS_UART_DMA}static void ag3352_register_notify(const struct device *dev, gps_notify_t notify){	LOG_INF("ag3352_init");	struct ag3352_data *data = (struct ag3352_data *)dev->data;	data->notify = notify;}static void ag3352_unregister_notify(const struct device *dev, gps_notify_t notify){	struct ag3352_data *data = (struct ag3352_data *)dev->data;	data->notify = NULL;}static const struct gps_dev_driver_api ag3352_api = {	.enable = ag3352_enable,	.disable = ag3352_disable,	.inquiry = NULL,	.register_notify = ag3352_register_notify,	.unregister_notify = ag3352_unregister_notify,};static void _gps_work_handler(struct k_work *work){	struct gps_value val = { 0 };	//LOG_INF("gps nmea: %s\r\n", ag3352_data.gps_data[ag3352_data.gpa_data_prev]);	if (ag3352_data.notify) {#ifdef CONFIG_SENSOR_GPS_UART_DMA#else		val.gps_nmea_data = ag3352_data.gps_data[ag3352_data.gpa_data_prev];#endif // CONFIG_SENSOR_GPS_UART_DMA		ag3352_data.notify(NULL, &val);	}}static int ag3352_init(const struct device *dev){	struct ag3352_data *data = (struct ag3352_data *)dev->data;	LOG_INF("ag3352_init");	gps_power_pin_ctl(true);	gps_power095_pin_ctl(true);	gps_reset_pin_ctl();	data->uart_gpio_dev = device_get_binding(GPS_UERT_DEV_NAME);	if (data->uart_gpio_dev == NULL) {		LOG_ERR("Couldn't find gps uart");		return -ENODEV;	}	k_work_init(&data->gps_work, _gps_work_handler);#ifdef CONFIG_SENSOR_GPS_UART_DMA	uart_dma_receive_init((struct device *)data->uart_gpio_dev, uart_ctrl_rx_dma_handler, NULL);	uart_rx_dma_switch((struct device *)data->uart_gpio_dev, TRUE, NULL, NULL);#else	uart_irq_callback_set(data->uart_gpio_dev, uart_fifo_callback);	data->gpa_data_cur = 0;#endif // CONFIG_SENSOR_GPS_UART_DMA	return 0;}#if IS_ENABLED(CONFIG_GPS)DEVICE_DEFINE(ag3352, CONFIG_GPS_DEV_NAME, &ag3352_init, NULL, &ag3352_data, NULL, POST_KERNEL, 60,	      &ag3352_api);#endif
 |