OV5642 카메라 데이터를 LWIP와 RTOS를 활용하여 Software에 보내는 프로젝트
----------------------------------------------------------------------------------------------------------
LWIP Version : 2.1.2
FreeRTOS version: 10.2.1
CMSIS-RTOS version: 2.00
STM32CubeMX Version: 5.6.1
Firmware Version: STM32Cube_FW_F4_V1.25.0
MCU: STM32F407VET
----------------------------------------------------------------------------------------------------------
LWIP 설정
TCP Buffer Size는 컴퓨터에서 받을 수있는 최고 size (2920Bytes)를 중심으로 계산하여 만들었다.
이전에 LWIP RAW API를 활용하여 개발 하였을 때 문제 없이 사용하였다.
주의!!
LWIP_NETIF_STATUSCALLBACK OPTION은 Firmware Version에 따라 CMSIS-V1으로 만들어져서 컴파일이 안되는 경우가 있었다. Version 확인 필수
Task 종류
기본 Idle Task라고 할 수 있는 defaultTask와 그 외 TcpTask, CameraTask를 만들었다.
아직은 priority 와 Parameter 그리고 Task Switching 하기위한 semaphre나 Mutexes는 설정하지 않았다.
Main.c
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_SPI3_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
StartDefaultTask
void StartDefaultTask(void *argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
osDelay(100);
}
/* USER CODE END StartDefaultTask */
}
CubeMX로 Code 생성 시 MX_LWIP_Init이 생성된다.
MX_LWIP_Init
void MX_LWIP_Init(void)
{
/* IP addresses initialization */
IP_ADDRESS[0] = 192;
IP_ADDRESS[1] = 168;
IP_ADDRESS[2] = 1;
IP_ADDRESS[3] = 111;
NETMASK_ADDRESS[0] = 255;
NETMASK_ADDRESS[1] = 255;
NETMASK_ADDRESS[2] = 255;
NETMASK_ADDRESS[3] = 0;
GATEWAY_ADDRESS[0] = 192;
GATEWAY_ADDRESS[1] = 168;
GATEWAY_ADDRESS[2] = 1;
GATEWAY_ADDRESS[3] = 1;
/* Initilialize the LwIP stack with RTOS */
tcpip_init( NULL, NULL );
/* IP addresses initialization without DHCP (IPv4) */
IP4_ADDR(&ipaddr, IP_ADDRESS[0], IP_ADDRESS[1], IP_ADDRESS[2], IP_ADDRESS[3]);
IP4_ADDR(&netmask, NETMASK_ADDRESS[0], NETMASK_ADDRESS[1] , NETMASK_ADDRESS[2], NETMASK_ADDRESS[3]);
IP4_ADDR(&gw, GATEWAY_ADDRESS[0], GATEWAY_ADDRESS[1], GATEWAY_ADDRESS[2], GATEWAY_ADDRESS[3]);
/* add the network interface (IPv4/IPv6) with RTOS */
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
/* Registers the default network interface */
netif_set_default(&gnetif);
if (netif_is_link_up(&gnetif))
{
/* When the netif is fully configured this function must be called */
netif_set_up(&gnetif);
}
else
{
/* When the netif link is down this function must be called */
netif_set_down(&gnetif);
}
/* Set the link callback function, this function is called on change of link status*/
netif_set_link_callback(&gnetif, ethernetif_update_config);
/* create a binary semaphore used for informing ethernetif of frame reception */
Netif_LinkSemaphore = osSemaphoreNew(1, 1, NULL);
link_arg.netif = &gnetif;
link_arg.semaphore = Netif_LinkSemaphore;
/* Create the Ethernet link handler thread */
/* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */
memset(&attributes, 0x0, sizeof(osThreadAttr_t));
attributes.name = "LinkThr";
attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;
attributes.priority = osPriorityBelowNormal;
osThreadNew(ethernetif_set_link, &link_arg, &attributes);
/* USER CODE END OS_THREAD_NEW_CMSIS_RTOS_V2 */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
MX_LWIP_Init 에서는 IP 설정 후 thread를 생성하여 주기적으로 호출하는데 이 Thread는 Ethernet Cable이 연결되었는지 주기적으로 검사하는 Thread이다.
만약 연결이 되지 않았다면 netif_set_down을 호출하여 연결을 Disconnect 하고
연결이 되었다면 netif_set_up을 호출하여 Ethernet을 연결한다.
앞서 CubeMx에서 언급한 NETIF_CALLBACK 기능을 끄면 위 Thread는 생성되지 않으며 MX_LWIP_Init함수를 호출 할때
Cable이 연결 되어 있지 않으면 연결 후 다시 재부팅하여 MX_LWIP_Init 함수를 호출 해줘야 연결이 된다.
TCP_Task
void Tcp_Task(void *argument)
{
/* USER CODE BEGIN Tcp_Task */
struct netconn *conn, *newconn;
err_t err, accept_err;
struct netbuf *buf;
void *data;
u16_t len;
LWIP_UNUSED_ARG(argument);
conn = netconn_new(NETCONN_TCP);
if (conn!=NULL)
{
err = netconn_bind(conn, NULL, 1460);
if (err == ERR_OK)
{
netconn_listen(conn);
while (1)
{
accept_err = netconn_accept(conn, &newconn);
if (accept_err == ERR_OK)
{
while (netconn_recv(newconn, &buf) == ERR_OK)
{
do
{
netbuf_data(buf, &data, &len);
netconn_write(newconn, data, len, NETCONN_COPY);
}
while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
netconn_close(newconn);
netconn_delete(newconn);
}
osDelay(100);
}
}
else
{
netconn_delete(newconn);
}
}
/* Infinite loop */
/* USER CODE END Tcp_Task */
}
기본적인 구현은 CubeMX를 따라 구현 하였다. 일반적인 Socket Programming과 크게 다르지 않다.
bind,listen,accept 함수 앞에 netconn만 붙이면 위 소스와 흐름이 똑같다.
실제 구현 후 동작 화면
'Firmware > stm32' 카테고리의 다른 글
OV5642_LWIP_RTOS Project -2(Camera API) (0) | 2020.04.24 |
---|---|
OV5642_LWIP_RTOS Project -2(Camera Interface 구현 ) (1) | 2020.04.23 |
OV5642_LWIP_RTOS Project -1(Netconn_write 호출 시 문제) (0) | 2020.04.23 |
OV5642_LWIP_RTOS Project -1(osThreadSetPriority 문제) (0) | 2020.04.17 |
stm32cubeIDE (Eclipse) Import Project (0) | 2019.12.30 |