Implementasi PPPOS pada stm32f4-discovery

Pernah, sebelum saya ada tugas untuk menyediakan akses ke Internet pada STM32 yang hanya memiliki port COM. Untuk mengatasi masalah ini, saya membutuhkan PPP, atau, tepatnya, PPPoS (Protokol Titik-ke-Titik melalui Serial - salah satu cara untuk mengimplementasikan PPP, digunakan saat menghubungkan melalui port COM).

Dalam proses penyelesaian tugas yang ditetapkan di depan saya, saya menghadapi beberapa kesulitan, salah satunya, menurut pendapat saya, tidak cukupnya cakupan masalah yang terkait dengan PPPoS di Internet. Dengan posting ini saya akan mencoba untuk menutup celah yang ditentukan, sejauh pengetahuan saya akan memungkinkan.

Artikel ini menjelaskan cara membuat proyek untuk System Workbench untuk STM32 dari awal. Menunjukkan contoh bekerja dengan UART. Ada contoh kode untuk mengimplementasikan PPP. Dan tentu saja, contoh pengiriman pesan ke komputer tetangga.

Pendahuluan


PPP (Point-to-Point Protocol) adalah protokol data-link dua poin dari model jaringan OSI. Biasanya digunakan untuk membangun komunikasi langsung antara dua node jaringan, dan dapat memberikan otentikasi koneksi, enkripsi dan kompresi data. Digunakan pada banyak jenis jaringan fisik: kabel null modem, saluran telepon, seluler, dll.

Seringkali ada subspesies dari protokol PPP, seperti Point-to-Point Protocol over Ethernet (PPPoE), yang digunakan untuk terhubung melalui Ethernet, dan kadang-kadang melalui DSL; dan Protokol Point-to-Point over ATM (PPPoA), yang digunakan untuk koneksi melalui ATM Adaptation Layer 5 (AAL5), yang merupakan alternatif PPPoE utama untuk DSL.

PPP adalah keluarga protokol: Link Control Protocol (LCP), Network Control Protocol (NCP), Protokol Otentikasi (PAP, CHAP), Multichannel PPP (MLPPP).

Dari Wikipedia .

Persiapan


Untuk mengatasi masalah yang kita butuhkan:

Besi:


  1. Papan debug stm32f4_discovery:

  2. Adaptor USB ke miniUSB untuk menghubungkan papan ke komputer.
  3. Dua USBtoUART FT232 adapter:

  4. Dua kabel ekstensi USB juga bermanfaat, tidak harus, tetapi hanya nyaman.

Lembut:


  1. Mesin virtual VirtualBox. Anda dapat mengunduhnya di sini . Kami juga mengunduh dan menginstal Paket Ekstensi untuk VirtualBox.
  2. Dua disk instalasi dengan sistem operasi Windows dan Linux. Kami mengambil Windows di sini , Linux di sini .

    Setelah menginstal OS, Anda perlu menginstal add-ons untuk OS tamu. Untuk tugas yang kami miliki cukup sistem 32x, Anda tidak bisa menipu dengan dimasukkannya virtualisasi.
  3. Untuk Windows, kami membutuhkan program yang dapat menerima permintaan dan meresponsnya melalui TCP / IP, dan program terminal untuk bekerja dengan port COM. Unduh PacketSender di sini (klik "Tidak, terima kasih, biarkan saya unduh."), Terminal ada di sini . Selain itu, kita perlu STM32CubeMX untuk pengaturan awal proyek. Unduh dari st.com (setelah pendaftaran, tautannya akan datang melalui email).
  4. Kami menempatkan System Workbench untuk STM32 di OS utama. Unduh dari sini (diperlukan registrasi).

Tahap 1. Membuat proyek


Pertama-tama, buka STM32CubeMX dan buat proyek baru di sana untuk papan stm32f4-discovery kami. Nyalakan RCC, Ethernet (ETH), SYS, USART2, USART3, lalu nyalakan FREERTOS dan LWIP.




Untuk diagnosa, kita membutuhkan LED di papan tulis. Untuk ini, konfigurasikan kaki-kaki PD12-PD15 sebagai GPIO_Output.



Pada tab Konfigurasi Jam, atur frekuensinya, seperti pada gambar di bawah ini.



Selanjutnya, pada tab Konfigurasi, konfigurasikan port USART. Kami akan bekerja dengan mereka dalam mode DMA. Kami memiliki dua port USART, satu akan kami gunakan untuk mengirim dan menerima data melalui PPP, yang kedua untuk logging. Untuk membuatnya bekerja, kita perlu mengkonfigurasi DMA pada RX dan TX untuk kedua port. Untuk semua kaki tuning DMA, atur Medium ke prioritas. Untuk USART2 leg, RX mengatur mode ke "Circular". Pengaturan lainnya dibiarkan secara default.



Anda juga perlu mengaktifkan interupsi global untuk kedua port pada tab "Pengaturan NVIC".

Ini menyelesaikan pengaturan awal proyek di STM32CubeMX. Kami menyimpan file proyek dan melakukan pembuatan kode untuk System Workbench for STM32.



Implementasi


Sekarang mari kita verifikasi bahwa kode yang diunduh mengkompilasi dan berfungsi. Untuk melakukan ini, dalam file main.c dalam fungsi "StartDefaultTask", kami mengganti badan infinite untuk loop (;;) dengan kode LED on dan off.

Seharusnya seperti ini:

/* StartDefaultTask function */ void StartDefaultTask(void const * argument) { /* init code for LWIP */ MX_LWIP_Init(); /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET); osDelay(1000); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET); osDelay(1000); } /* USER CODE END 5 */ } 

Kami mengkompilasi firmware dan mencari. Keempat LED harus berkedip di papan tulis.

Tahap 2. Bekerja dengan USART


Tugas kita selanjutnya adalah memverifikasi operasi USART kita dengan benar.

Hal pertama yang perlu kita lakukan adalah menghubungkan FT232 kita dengan penemuan. Untuk melakukan ini, lihat kaki-kaki mana antarmuka USART bercerai. Saya memilikinya masing-masing PD6 dan PD5 untuk USART2_RX dan USART2_TX.



Serta PD9 dan PD8 untuk USART3_RX dan USART3_TX, masing-masing.



Selain itu, kita membutuhkan kaki GND.

Kami menemukan pin ini di papan dan menghubungkannya ke pin FT232, sementara pin GND di papan bisa apa saja, pin RX di papan harus terhubung ke pin TX di FT232, dan pin TX di papan harus terhubung ke pin RX di FT232. Kesimpulan yang tersisa tidak digunakan.

Tetap menghubungkan FT232 kami ke port USB komputer, serta menghubungkan papan penemuan itu sendiri melalui konektor miniUSB ke komputer (jangan bingung dengan microUSB).

Setelah menghubungkan FT232, OS utama akan menginstal driver untuk mereka, setelah itu perangkat ini akan perlu diteruskan ke tamu Windows di mesin virtual.

Sekarang kami menambahkan kode program yang diperlukan untuk pengoperasian USART kami. Untuk melakukan ini, kita akan menambahkan empat file: usart.h, usart.c, logger.h, logger.c.

Isi File:

file usart.h
 #ifndef _USART_ #define _USART_ #include "stm32f4xx_hal.h" void usart_Open(void); bool usart_Send(char* bArray, int size_bArray); uint16_t usart_Recv(char* bArray, uint16_t maxLength); #endif /* _USART_ */ 

file usart.c
 #include "usart.h" #include "logger.h" #include "cmsis_os.h" #define Q_USART2_SIZE 200 xQueueHandle g_qUsart; osThreadId g_usart_rxTaskHandle; extern UART_HandleTypeDef huart2; void usart_rxTask(void); uint8_t bGet[Q_USART2_SIZE] = {0}; uint16_t g_tail = 0; void usart_Open(void) { g_qUsart = xQueueCreate( Q_USART2_SIZE, sizeof( unsigned char ) ); osThreadDef(usart_rxTask_NAME, usart_rxTask, osPriorityNormal, 0, Q_USART2_SIZE/4+128); g_usart_rxTaskHandle = osThreadCreate(osThread(usart_rxTask_NAME), NULL); HAL_UART_Receive_DMA(&huart2, bGet, Q_USART2_SIZE); } void usart_rxTask(void) { for(;;) { uint16_t length = Q_USART2_SIZE - huart2.hdmarx->Instance->NDTR; while(length - g_tail) { uint8_t tmp = bGet[g_tail]; xQueueSendToBack( g_qUsart, &tmp, 100 ); g_tail++; if (g_tail == Q_USART2_SIZE) g_tail = 0; } } } bool usart_Send(char* bArray, int size_bArray) { HAL_StatusTypeDef status; status = HAL_UART_Transmit_DMA(&huart2, bArray, size_bArray); while (HAL_UART_GetState(&huart2) != HAL_UART_STATE_READY) { if (HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_RX) break; osDelay(1); } if (status == HAL_OK) return true; return false; } uint16_t usart_Recv(char* bArray, uint16_t maxLength) { uint8_t tmp = 0; uint16_t length = 0; while(uxQueueMessagesWaiting(g_qUsart)) { xQueueReceive( g_qUsart, &tmp, 100 ); bArray[length] = tmp; length++; if (length >= maxLength) break; } return length; } 

file logger.h
 #ifndef _LOGGER_ #define _LOGGER_ void logger(const char *format, ...); #endif /* _LOGGER_ */ 

file logger.c
 #include "logger.h" #include "stm32f4xx_hal.h" #include <stdarg.h> extern UART_HandleTypeDef huart3; #define MAX_STRING_SIZE 1024 HAL_StatusTypeDef logger_Send(char* bArray, uint32_t size_bArray) { HAL_StatusTypeDef status; for(int i=0;i<5;i++) { status = HAL_UART_Transmit_DMA(&huart3, bArray, size_bArray); if (status == HAL_OK) break; osDelay(2); } while (HAL_UART_GetState(&huart3) != HAL_UART_STATE_READY) { osDelay(1); } return status; } void logger(const char *format, ...) { char buffer[MAX_STRING_SIZE]; va_list args; va_start (args, format); vsprintf(buffer, format, args); va_end(args); buffer[MAX_STRING_SIZE-1]=0; logger_Send(buffer, strlen(buffer)); } 

Kami membutuhkan usart untuk mengirim dan menerima data di usart2. Ini akan menjadi antarmuka utama kami untuk berkomunikasi dengan server PPP.

Kami membutuhkan Logger untuk mengimplementasikan pencatatan dengan mengirim pesan ke terminal. Fungsi void usart_Open (void) membentuk antrian dan memulai tugas servis antrian ini. Fungsi ini harus diselesaikan sebelum menggunakan USART. Kemudian semuanya sederhana, fungsi bool usart_Send (char * bArray, int size_bArray) mengirimkan data ke port, dan
uint16_t usart_Recv (char * bArray, uint16_t maxLength) mendapatkannya dari antrian di mana fungsi void usart_rxTask (void) telah menambahkannya.

Untuk logger, ini masih lebih sederhana, tidak perlu mendapatkan data, oleh karena itu, baik tugas antrian maupun tugas antrian tidak diperlukan.

Di awal file main.h , Anda perlu menambahkan beberapa definisi yang menggambarkan tipe bool, yang tidak tersedia dalam C.

 /* USER CODE BEGIN Includes */ typedef unsigned char bool; #define true 1 #define false 0 /* USER CODE END Includes */ 

Sekarang saatnya untuk memeriksa fungsionalitas kode yang dihasilkan. Untuk melakukan ini, dalam file main.c , ubah kode tugas yang sudah diketahui "StartDefaultTask"

 /* USER CODE BEGIN 4 */ #include "usart.h" #include "logger.h" #define MAX_MESSAGE_LENGTH 100 /* USER CODE END 4 */ /* StartDefaultTask function */ void StartDefaultTask(void const * argument) { /* init code for LWIP */ MX_LWIP_Init(); /* USER CODE BEGIN 5 */ usart_Open(); /* Infinite loop */ uint8_t send[] = "Send message\r\n"; uint8_t recv[MAX_MESSAGE_LENGTH] = {0}; uint16_t recvLength = 0; for(;;) { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET); osDelay(1000); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET); osDelay(1000); if (usart_Send(send, sizeof(send)-1)) logger("SEND - %s", send); recvLength = usart_Recv(recv, MAX_MESSAGE_LENGTH-1); if (recvLength) { recv[recvLength] = 0; logger("RECV - %s\r\n", recv); } } /* USER CODE END 5 */ } 

Selain itu, kita perlu memberikan lebih banyak memori ke tumpukan tugas kita. Untuk melakukan ini, dalam panggilan ke fungsi osThreadDef (), file main.c, Anda perlu memperbaiki 128 dengan 128 * 10 untuk mendapatkan ini:

 osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, <b>128*10</b>); 

Kami mengkompilasi dan menginstal. LED berkedip dengan cara yang sama seperti pada tugas sebelumnya.

Untuk melihat hasil pekerjaan kami, Anda perlu menjalankan program Terminal di mesin virtual kami. Satu contoh program untuk port logging, yang kedua untuk utama. Lihat di manajer perangkat nomor port apa yang ditetapkan untuk FT232 Anda. Jika nomor telah ditetapkan lebih dari 10, tugaskan kembali.

Saat memulai instance kedua dari program, kesalahan dapat terjadi, tutup jendela dengan kesalahan dan terus bekerja dengan program.

Untuk kedua port, kami membuat koneksi pada 115200 baud, bit data - 8, paritas - tidak ada, stop bit - 1, handshaking - tidak ada.

Jika Anda melakukan semuanya dengan benar, maka di jendela terminal untuk usart2 pesan "Kirim pesan" akan dikirim. Pesan yang sama akan digandakan di jendela terminal untuk logger hanya dengan awalan "KIRIM -"

Jika di jendela terminal untuk usart2 Anda mengetik beberapa teks di bidang "Kirim" dan klik tombol yang sesuai di sebelah kanan bidang ini, maka di jendela logger Anda akan melihat pesan yang sama dengan awalan "RECV -"

Pada gambar di bawah ini: di sebelah kiri adalah logger, di sebelah kanan adalah usart2.



Tahap 3. Memulai dengan PPP


Sebagai bagian dari tugas ini, kami akan meningkatkan koneksi PPP. Pertama-tama, aktifkan penggunaan PPP, ubah nilai yang didefinisikan oleh PPP_SUPPORT dalam file ppp_opts.h menjadi 1. Kemudian kita mendefinisikan kembali definisi yang diperlukan dalam file lwipopts.h,

 /* USER CODE BEGIN 1 */ #define MEMP_NUM_SYS_TIMEOUT 8 #define CHECKSUM_GEN_IP 1 #define CHECKSUM_GEN_TCP 1 /* USER CODE END 1 */ 

Pada saat yang sama, definisi lama perlu dikomentari.

Sekarang kita memodifikasi file lwip.c, masukkan kode berikut ke dalam blok β€œ/ * USER CEGE BEGIN 0 * /”:

 /* USER CODE BEGIN 0 */ #include "usart.h" #include "pppos.h" #include "sio.h" #include "dns.h" #include "ppp.h" static ppp_pcb *ppp; struct netif pppos_netif; void PppGetTask(void const * argument) { uint8_t recv[2048]; uint16_t length = 0; for(;;) { length=usart_Recv(recv, 2048); if (length) { pppos_input(ppp, recv, length); logger("read - PppGetTask() len = %d\n", length); } osDelay(10); } } #include "ip4_addr.h" #include "dns.h" static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { struct netif *pppif = ppp_netif(pcb); LWIP_UNUSED_ARG(ctx); switch(err_code) { case PPPERR_NONE: /* No error. */ { logger("ppp_link_status_cb: PPPERR_NONE\n\r"); logger(" our_ip4addr = %s\n\r", ip4addr_ntoa(netif_ip4_addr(pppif))); logger(" his_ipaddr = %s\n\r", ip4addr_ntoa(netif_ip4_gw(pppif))); logger(" netmask = %s\n\r", ip4addr_ntoa(netif_ip4_netmask(pppif))); } break; case PPPERR_PARAM: /* Invalid parameter. */ logger("ppp_link_status_cb: PPPERR_PARAM\n"); break; case PPPERR_OPEN: /* Unable to open PPP session. */ logger("ppp_link_status_cb: PPPERR_OPEN\n"); break; case PPPERR_DEVICE: /* Invalid I/O device for PPP. */ logger("ppp_link_status_cb: PPPERR_DEVICE\n"); break; case PPPERR_ALLOC: /* Unable to allocate resources. */ logger("ppp_link_status_cb: PPPERR_ALLOC\n"); break; case PPPERR_USER: /* User interrupt. */ logger("ppp_link_status_cb: PPPERR_USER\n"); break; case PPPERR_CONNECT: /* Connection lost. */ logger("ppp_link_status_cb: PPPERR_CONNECT\n"); break; case PPPERR_AUTHFAIL: /* Failed authentication challenge. */ logger("ppp_link_status_cb: PPPERR_AUTHFAIL\n"); break; case PPPERR_PROTOCOL: /* Failed to meet protocol. */ logger("ppp_link_status_cb: PPPERR_PROTOCOL\n"); break; case PPPERR_PEERDEAD: /* Connection timeout. */ logger("ppp_link_status_cb: PPPERR_PEERDEAD\n"); break; case PPPERR_IDLETIMEOUT: /* Idle Timeout. */ logger("ppp_link_status_cb: PPPERR_IDLETIMEOUT\n"); break; case PPPERR_CONNECTTIME: /* PPPERR_CONNECTTIME. */ logger("ppp_link_status_cb: PPPERR_CONNECTTIME\n"); break; case PPPERR_LOOPBACK: /* Connection timeout. */ logger("ppp_link_status_cb: PPPERR_LOOPBACK\n"); break; default: logger("ppp_link_status_cb: unknown errCode %d\n", err_code); break; } } // Callback used by ppp connection static u32_t ppp_output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { LWIP_UNUSED_ARG(pcb); LWIP_UNUSED_ARG(ctx); if (len > 0) { if (!usart_Send(data, len)) return 0x05; } logger("write - ppp_output_cb() len = %d\n", len); return len; } void pppConnect(void) { ppp = pppos_create(&pppos_netif, ppp_output_cb, ppp_link_status_cb, NULL); ppp_set_default(ppp); osThreadId PppGetTaskHandle; osThreadDef(PPP_GET_TASK_NAME, PppGetTask, osPriorityNormal, 0, 128*10); PppGetTaskHandle = osThreadCreate(osThread(PPP_GET_TASK_NAME), NULL); err_t err = ppp_connect(ppp,0); if (err == ERR_ALREADY) { logger("Connected successfully"); } for(int i=0;i<40;i++) { osDelay(500); if (ppp->phase >= PPP_PHASE_RUNNING) break; } } /* USER CODE END 0 */ 

Kemudian, dalam fungsi MX_LWIP_Init (), di blok β€œ/ * USER CODE BEGIN 3 * /” kami menambahkan panggilan ke fungsi pppConnect ().

Selain itu, Anda perlu meningkatkan ukuran heap, untuk ini, dalam file FreeRTOSConfig.h, Anda perlu mengomentari definisi configTOTAL_HEAP_SIZE, dan pada akhir file, di / * USER CODE BEGIN Definisikan * / blok, nyatakan dengan nilai baru.

 /* USER CODE BEGIN Defines */ /* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */ #define configTOTAL_HEAP_SIZE ((size_t)1024*30) /* USER CODE END Defines */ 

Juga, dalam file usart.c, ubah nilai definisi Q_USART2_SIZE menjadi 2048.

Pengaturan koneksi dimulai dengan fungsi MX_LWIP_Init (); itu dibuat secara otomatis; kami baru saja menambahkan panggilan ke fungsi pppConnect () padanya. Dalam fungsi ini, tugas yang melayani koneksi PPPOS diluncurkan. Fungsi pppos_create () perlu diberikan alamat fungsi yang akan melayani pengiriman pesan dan output informasi tentang mengubah status koneksi. Bagi kami, ini adalah fungsi masing-masing ppp_output_cb () dan ppp_link_status_cb (). Selain itu, fungsi pppConnect () akan memulai tugas melayani pesan yang diterima. Pada akhir operasinya, fungsi pppConnect () akan menunggu koneksi ke server dibuat, dan kemudian menyelesaikan operasinya.

Bekerja dengan jaringan akan dilakukan pada tingkat yang lebih tinggi, segera setelah LWIP memutuskan bahwa perlu mengirim pesan ke jaringan, fungsi ppp_output_cb () akan dipanggil secara otomatis. Respons dari jaringan akan diterima oleh fungsi PppGetTask (), sebagai bagian dari tugas melayani pesan yang masuk, dan ditransfer ke usus LWIP. Jika status koneksi berubah, fungsi ppp_link_status_cb () akan dipanggil secara otomatis.

Terakhir, kami akan memodifikasi tugas StartDefaultTask. Sekarang akan terlihat seperti ini:

 void StartDefaultTask(void const * argument) { /* init code for LWIP */ // MX_LWIP_Init(); /* USER CODE BEGIN 5 */ usart_Open(); MX_LWIP_Init(); /* Infinite loop */ for(;;) { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET); osDelay(1000); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET); osDelay(1000); } /* USER CODE END 5 */ } 

Selesai, Anda dapat mengkompilasi dan flash.

Pada titik ini, Anda harus memulai server PPP. Untuk melakukan ini, Anda harus terlebih dahulu menggunakan mesin virtual dengan Linux. Saya menggunakan Ubuntu 16.04 x32. Setelah menginstal sistem operasi, Anda perlu mengkonfigurasi penggunaan port COM.

Pada bagian ini, kita tidak perlu mesin virtual dengan Windows, kita dapat mematikannya dengan aman. Kami menghubungkan kedua FT232 di Linux.

Di Linux, sebelum Anda mulai bekerja dengan port COM, Anda harus mengizinkan pengguna untuk menggunakannya. Untuk melakukan ini, jalankan perintah berikut:

 sudo addgroup USERNAME dialout 

di mana USERNAME adalah nama pengguna saat ini.

Untuk melihat port yang tersedia di sistem COM, Anda perlu menjalankan perintah:

 dmesg | grep tty 



Kami melihat bahwa ada dua port ttyUSB dalam sistem. Kita tidak bisa langsung mengatakan mana yang logger dan mana yang usart2. Anda hanya perlu memeriksanya secara bergantian.

Pertama, jalankan perintah untuk membaca dari satu port:

 stty -F /dev/ttyUSB0 115200 cat /dev/ttyUSB0 

lalu dari yang lain:

 stty -F /dev/ttyUSB1 115200 cat /dev/ttyUSB1 

Di mana kita melihat gambar seperti itu, yaitu logger.



Anda dapat meninggalkan jendela ini, itu tidak akan mengganggu kami.

Selanjutnya, Anda harus mengizinkan paket yang dikirim dari papan kami untuk meninggalkan batas subnet mereka. Untuk melakukan ini, konfigurasikan iptables. Kami melakukan tindakan berikut:

1. Buka jendela konsol baru
2. Anda perlu mencari tahu ip Anda dan nama antarmuka jaringan (jalankan perintah ifconfig )



3. Jalankan perintah konfigurasi nat

 sudo echo 1 | sudo tee -a /proc/sys/net/ipv4/ip_forward > /dev/null sudo echo 1 | sudo tee -a /proc/sys/net/ipv4/ip_dynaddr > /dev/null sudo iptables -F FORWARD sudo iptables -F -t nat sudo iptables -t nat -A POSTROUTING -o enp0s3 -j SNAT --to-source 192.168.10.196 sudo iptables -t nat -L 

di mana enp0s3 adalah nama antarmuka jaringan
192.168.10.196 - alamat IP Anda
/ proc / sys / net / ipv4 / - path ke file yang sesuai.

Perintah-perintah ini dapat ditulis ulang menjadi file batch dan menjalankannya setiap kali sebelum memulai server PPP. Anda dapat menambahkannya ke autorun, tetapi saya tidak.

Sekarang kita siap untuk memulai server, tetap hanya untuk membuat file pengaturan. Saya menyebutnya " pppd.conf ", saya sarankan menggunakan pengaturan berikut:

 nodetach noauth passive local debug lock 192.168.250.1:192.168.250.2 /dev/ttyUSB1 115200 lcp-echo-interval 10 lcp-echo-failure 1 cdtrcts 

Kami menulis ulang pengaturan dalam file dan kemudian Anda dapat memulai server. Ini dilakukan dengan perintah sudo pppd ./pppd.conf

Server PPPD harus dimulai sebelum dimulainya penemuan, jadi setelah dimulainya PPPD Anda harus mengklik tombol "Reset" yang terletak di papan tulis.

Jika Anda melakukan semuanya dengan benar, Anda akan melihat gambar berikut:



Menjalankan pppd di sebelah kiri, logger di sebelah kanan.

Tahap 4. Kami mengirim tas


Pada tahap ini, kita membutuhkan kedua mesin virtual. Linux untuk pppd dan Windows untuk menerima paket. Untuk menyederhanakan tugas, Anda perlu kedua mesin berada di subnet yang sama, solusi yang ideal adalah menentukan koneksi Network Bridge untuk kedua mesin dalam pengaturan jaringan VirtualBox, dan menonaktifkan firewall di Windows.

Kami memulai mesin virtual dan mengkonfigurasi koneksi ppp dari papan penemuan dengan pppd. Di Windows, kami menemukan alamat IP mesin (perintah ipconfig), saya mendapatkannya 192.168.10.97.

Luncurkan Pengirim Paket dan konfigurasikan sebagai berikut:



Sekarang lagi, ubah tugas StartDefaultTask di file main.c.

 /* USER CODE BEGIN 4 */ #include "logger.h" #include "sockets.h" typedef uint32_t SOCKET; /* USER CODE END 4 */ /* StartDefaultTask function */ void StartDefaultTask(void const * argument) { /* init code for LWIP */ // MX_LWIP_Init(); /* USER CODE BEGIN 5 */ usart_Open(); MX_LWIP_Init(); /* Infinite loop */ uint8_t sendStr[]="Test message TCP/IP."; uint8_t resvStr[100]={0}; int resvLength = 0; struct sockaddr_in sockAddr; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons( 6565 ); uint32_t addr = inet_addr("192.168.10.97"); sockAddr.sin_addr.s_addr = addr; SOCKET socket = NULL; int nError = 0; /* Infinite loop */ for(;;) { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET); osDelay(1000); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET); osDelay(1000); socket = socket( AF_INET, SOCK_STREAM, 0 ); nError = connect( socket, (struct sockaddr*)&sockAddr, sizeof(sockAddr) ); if ( nError == 0 ) { nError = send( socket, sendStr, sizeof(sendStr)-1, 0 ); if ( nError < 0 ) logger("SEND ERROR %d\n", nError); else { logger("SEND - %s\n", sendStr); resvLength = 0; while(resvLength < 1) resvLength = lwip_recv( socket, resvStr, sizeof(resvStr), MSG_WAITALL); resvStr[resvLength]=0; logger("GET - %s\n", resvStr); } lwip_close(socket); } else logger("CONNECT ERROR %d\n", nError); } /* USER CODE END 5 */ } 

Sebagai nilai variabel addr, kami menggunakan alamat mesin Windows, nomor port 6565.
Pesan terkirim "Tes pesan TCP / IP.", Respons "Pesan diterima."

Di sini Anda dapat melihat bahwa fungsi PPP tidak secara langsung digunakan untuk mengirim dan menerima pesan. Semua pekerjaan terjadi di tingkat yang lebih tinggi, dan fungsi kami dipanggil secara otomatis.

Kami mengkompilasi dan menginstal.

Hasil menghubungkan ke pppd terlihat di mesin Linux:



Permintaan yang diterima dan respons yang dikirim dapat dilihat dalam program Pengirim Paket pada mesin Windows:



Nah, itu saja, paket yang kami kirim dari papan penemuan pergi ke port COM, sampai ke server pppd, dikirim ke port Windows 6565 dari mesin, di sana ia berhasil diterima, sebagai tanggapan terhadapnya paket lain dikirim yang melewati ini jalan di arah yang berlawanan dan berhasil diadopsi di papan tulis. Anda mungkin dapat mengirim pesan ke mesin apa pun di Internet.

β†’ Kode proyek lengkap dapat diunduh di sini

Source: https://habr.com/ru/post/id419037/


All Articles