/******************************************************************************
版权所有：	@copyright (C) 2024-2034 HaiYang Technology Corp. All rights reserved.
文件名称：	shm.c
文件版本：	01.01
创建作者：	zhaoyang
创建日期：	2025-08-21
功能说明：	共享内存驱动
其它说明：
修改记录：
*/
#include "bsp_shm.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <pthread.h>
#include <stdbool.h>
#include "bsp_share.h"


uint8_t *SHM_BASE_R = NULL; //共享内存---读(从裸核读取数据)---开始地址
uint8_t *SHM_BASE_W = NULL; //共享内存---写(向裸核写入数据)---开始地址



struct  test_data_s
{
	uint16_t A;//标志A，写buf和crc前，A++
	uint8_t  buf[1000];
	uint16_t crc;// buf的crc
	uint16_t B;//标志B，写buf和crc后，B++，且A=B

};

struct dev_co {
    char                    *name;
    pthread_t               thread_id;
    //int                     fd_co; //mailbox 暂时去掉
   	int                     fd_shm_w;
    int                     fd_shm_r;

    uint8_t                 *shm_w;
    uint8_t                 *shm_r;

    //struct co_io            coio; //mailbox 暂时去掉
};

struct dev_co *pco0;


static inline void dmsg_u8(uint8_t *data, int length, char *str)
{
	int i, j;
	int tmp;

	printf("%s:\n", str);
	for (i = 0; i < (length / 16); i++)
	{
		for (j = 0; j < 16; j++)
			printf("%02x ", data[i * 16 + j]);
		printf("\n");
	}
	tmp = (length / 16) * 16;
	for (i = 0; i < (length % 16); i++)
		printf("%02x ", data[tmp + i]);
	if (length % 16)
		printf("\n");
}


/******************************************************************************
函数名称：	shm_read
函数版本：	01.01
创建作者：	zhaoyang
创建日期：	2025-08-21
函数说明：	读取共享内存的数据.
参数说明：	
addr：所以读取共享内存的地址
len：需要读取数据的长度
out_data：输出buf
out_data_size:输出buf的长度

返回值：	成功返回读取数据的长度, 失败返回-1
修改记录：	
*/
int shm_read(uint32_t addr, uint32_t len, uint8_t *out_data, uint32_t out_data_size)
{
	uint32_t i=0;
	
	if(SHM_BASE_R == NULL)
		return -1;

	if(out_data == NULL)
		return -1;
	if((len == 0) || (out_data_size == 0))
		return -1;

	for(i=0;i < len; i++)
	{
		if((addr+i) >= SHM_MAX_SIZE)
			return -1;

		if(i >= out_data_size)
			return -1;

		out_data[i] = SHM_BASE_R[addr+i];
	}

	return i;
}

/******************************************************************************
函数名称：	shm_write
函数版本：	01.01
创建作者：	zhaoyang
创建日期：	2025-08-21
函数说明：	向共享内存写入数据.
参数说明：	
addr：共享内存的地址
data：写入数据
len:写入数据长度

返回值：	成功返回写入数据的长度, 失败返回-1
修改记录：	
*/
int shm_write(uint32_t addr, uint8_t *data, uint32_t len)
{
	uint32_t i=0;

	if(SHM_BASE_W == NULL)
		return -1;

	if(data == NULL)
		return -1;
	if(len == 0 )
		return -1;

	for(i=0;i < len; i++)
	{
		if((addr+i) >= SHM_MAX_SIZE)
			return -1;

		SHM_BASE_W[addr+i] = data[i];
	}

	return i;
}

static void *thread_co_test(void *arg)
{
//	struct dev_co *co = (struct dev_co *)arg;
//	uint8_t *shm0 = co->shm_w;
//	uint8_t *shm1 = co->shm_r;
    int i;
    int state = 0;
//	int ret;
//	uint16_t crc = 0;
//	int crc_err_cnt = 0;
//	int cnt_alive = 0;
//	int cnt_busy = 0;
//	int cnt_crcerr = 0;
//	int cnt_good = 0;

	uint8_t test_buf_r[2000];
//	uint8_t test_buf_r_record[2000];
	uint8_t test_buf_w[2000];
    int nr = 0;
//	uint8_t lastcode = 0;
//	int cnt = 0;
//	int last_A = 0;
//	int last_B = 0;
//	struct  test_data_s *p_rec_buf = (struct  test_data_s*)test_buf_r;
//	uint16_t temval = 0;
	

	memset(test_buf_r, 0, 2000);
	memset(test_buf_w, 0, 2000);

    state = 1;

    while (1) {

		sleep(5);

		nr++;

		//读 分两种接口
		dmsg_u8(SHM_BASE_R, 10, "read:");

		shm_read(10, 10, test_buf_r, 2000);
		dmsg_u8(test_buf_r, 10, "shm_read:");


		//写 分两种接口
		for(i = 0; i< 10; i++)
			SHM_BASE_W[i] = nr+i;

		for(i = 0; i< 10; i++)
			test_buf_w[i] = nr+i+10;

	  	shm_write(10, test_buf_w, 10);

		
		
#if 0
      if (state == 1) {

			last_A = shm1[0]+((uint16_t)shm1[1]<<8);
			last_B = shm1[sizeof(struct  test_data_s)-2]+((uint16_t)shm1[sizeof(struct  test_data_s)-1]<<8);
			if(last_A == last_B)
			{
				//idle
				memcpy(&test_buf_r,shm1,sizeof(struct  test_data_s));

				if((p_rec_buf->A == p_rec_buf->B) && (p_rec_buf->A == last_A) && (last_A == shm1[0]+((uint16_t)shm1[1]<<8)) 
					&& (last_B == shm1[sizeof(struct  test_data_s)-2]+((uint16_t)shm1[sizeof(struct  test_data_s)-1]<<8)))
				{
					//在拷贝过程中，数据没有被修改
					crc = CrcStr(p_rec_buf->buf,sizeof(p_rec_buf->buf));
					if(crc != p_rec_buf->crc)
					{
						#if 0
						printf("crc err!!! cal crc=%04X, read crc=%04X\n",  crc,p_rec_buf->crc);
						dmsg_u8(test_buf_r, sizeof(struct  test_data_s), "test_buf_r");
						dmsg_u8(shm1, sizeof(struct  test_data_s), "shm1");
						printf("p_rec_buf->A=%d, last_A=%d\n",  p_rec_buf->A,last_A);
						#endif
						
						cnt_crcerr++;
					}
					else
					{
						cnt_good++;
					}

				}
				else
				{
					//busy 裸核正在写数据
					cnt_busy++;

				}

			}
			else
			{
				//busy 裸核正在写数据
				cnt_busy++;
				
			}


			if(cnt_alive++ > 100000)
			{
				cnt_alive = 0;
				printf("cnt_busy=%d, cnt_crcerr=%d, cnt_good=%d\n",  cnt_busy,cnt_crcerr,cnt_good);
				printf("cal crc=%04X, read crc=%04X\n",  crc,p_rec_buf->crc);

			}

		 	usleep(10);

      }

#endif

	  
    }



	
    printf("thread co exit\r\n");    
    pthread_exit(NULL);
}

//测试代码
void shm_test(void)
{
	int ret;
	
	if((ret = pthread_create(&pco0->thread_id, NULL, thread_co_test, pco0)) == 0)
		printf("thread co0 create success\r\n");
	else
		printf("thread co0 create fail ret=%d\r\n", ret);

}



/******************************************************************************
函数名称：	shm_init
函数版本：	01.01
创建作者：	zhaoyang
创建日期：	2025-08-21
函数说明：	shm初始化.
参数说明：	
					无					
返回值：	成功返回0, 失败返回-1
修改记录：	
*/
int shm_init(void)
{
//	int ret;

	int i;
    unsigned int *tmp_buf;

	SHM_BASE_R = NULL;
	SHM_BASE_W = NULL;

	pco0 = malloc(sizeof(struct dev_co));

	memset(pco0, 0, sizeof(struct dev_co));

    if (shmem_init(&shmem_fd)) {
        printf("shmem_init failed!\n");
        return -1;
    }                         
	
	tmp_buf = mmap(NULL, shmem_fd.linux_read_len, PROT_READ|PROT_WRITE, 
		       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
	if (tmp_buf <= 0) {
        printf("mmap failed!\n");
        return -1;
    }
	
	printf("tmp_buf:%lx\n", (unsigned long)tmp_buf);

	SHM_BASE_R = shmem_fd.linux_read->data; //共享内存---读(从裸核读取数据)---开始地址
	SHM_BASE_W = shmem_fd.linux_write->data; //共享内存---写(向裸核写入数据)---开始地址

	//初始化shm区
	//暂时初始化参数区
	for(i=0;i<SHM_ADDR_U_ADC_1;i++)
	{
		SHM_BASE_R[i] = 0;
		SHM_BASE_W[i] = 0;
	}
	
	// shm_test();//zhaoyang for test
	return 0;	
}

/******************************************************************************
函数名称：	shm_exit
函数版本：	01.01
创建作者：	zhaoyang
创建日期：	2025-08-21
函数说明：	shm反初始化.
参数说明：	无					
返回值：	总是返回0.
修改记录：	
*/
int shm_exit(void)
{
	//pthread_join(pco0->thread_id, NULL);
	return 0;
}




 
 
 
 
