Line Follower Robot Using Stm32 - stm32

I'm trying to build a line follower robot using STM32 F334R8, L298N motor driver, three KY-033 sensors, and two 6V DC motors. I'm using stm cube ide. Sensors and driver work just fine but motors don't have any movement with this code. If I manually change outputs as high, motors work but not with the code. I'm new to stm32 programming so I don't know why my code doesn't work. Please help me find the wrong or missing parts.( M1_En = PB13 = right motor enable pin, M2_En = PC5 = left motor enable pin)
void forw(){
HAL_GPIO_WritePin( M1_En_GPIO_Port,M1_En_Pin, 255);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, 1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2, 0);
HAL_GPIO_WritePin( M2_En_GPIO_Port,M2_En_Pin, 255);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4, 1 );
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_5, 0);
}
void left(){
HAL_GPIO_WritePin( M1_En_GPIO_Port,M1_En_Pin, 255);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, 1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2, 0);
HAL_GPIO_WritePin( M2_En_GPIO_Port,M2_En_Pin, 0);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4, 1 );
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_5, 0);
}
void right(){
HAL_GPIO_WritePin( M1_En_GPIO_Port,M1_En_Pin, 0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, 1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2, 0);
HAL_GPIO_WritePin( M2_En_GPIO_Port,M2_En_Pin, 255);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4, 1 );
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_5, 0);
}
while(1){
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9)==0 && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==1 &&
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3)==0) forw();
else if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9)==0 && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0 &&
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3)==1) right();
else if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9)==1 && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0 &&
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3)==0) forw();
}

Related

So I am running an ESP32 and i currently have it set to implement 2 tasks. Core 0 is aborting due to the watch dog timer

Task1 running on core 0
Task2 running on core 1
The response from slave 1 data register 40007 failed!
The response from slave 1 data register 40008 failed!
The response from slave 1 data register 40020 failed!
The response from slave 1 data register 40021 failed!
E (13183) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (13183) task_wdt: - IDLE0 (CPU 0)
E (13183) task_wdt: Tasks currently running:
E (13183) task_wdt: CPU 0: Task1
E (13183) task_wdt: CPU 1: loopTask
E (13183) task_wdt: Aborting.
abort() was called at PC 0x400d606b on core 0
Backtrace: 0x40090bbc:0x3ffbe190 0x40090ded:0x3ffbe1b0 0x400d606b:0x3ffbe1d0 0x40084af5:0x3ffbe1f0 0x400d1585:0x3ffc79b0 0x400d19ef:0x3ffc79d0 0x400d1e85:0x3ffc79f0 0x400d2996:0x3ffc7a10 0x4008d6b9:0x3ffc7a30
Rebooting...
void setup() {
// put your setup code here, to run once:
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// Init in receive mode
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// Modbus communication runs at 9600 baud
Serial2.begin(9600);
// Modbus slave ID 1
node.begin(1, Serial2);
// Callbacks allow us to configure the RS485 transceiver correctly
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
Serial.begin(38400);
while (!Serial); //while not serial Wait...
delay(1500);
Serial.println("Program has Started");
for(int i=0; i<InArraySize; i++){
pinMode(iPins[i],INPUT_PULLUP); //To enable PULL-UP resistors change "INPUT" with "INPUT_PULLUP"
}
for(int i=0; i<OutArraySize; i++){
pinMode(oPins[i],OUTPUT);
}
//interrupt-tag
// start the Modbus RTU client
initTCC();
//rtc1-tag
digitalWrite(13, HIGH);
xTaskCreatePinnedToCore(
Task1code, /* Function to implement the task */
"Task1", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&Task1, /* Task handle. */
0); /* Core where the task should run */
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* Core where the task should run */
/**************************************Bluetooth*****************************************/
/*Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
*/
// esp_task_wdt_init(7, true); //watchdog
// esp_task_wdt_add(Task1); //watchdog
}
void Task1code( void * pvParameter)
{
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;)
{
mainRoutine();
updateRegisters();
}
// esp_task_wdt_reset(); //watchdog
}
void Task2code( void * pvParameter)
{
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID());
for(;;)
{
/**************************************Bluetooth*****************************************/
/*if (Serial.available())
{
SerialBT.write(Serial.read());
}
if (SerialBT.available())
{
Serial.write(SerialBT.read());
}
delay(20);
*/
if ((millis()-pollTemp)>pollInterval){
pollDone=true;
//using mod move (unit id ,place to store data, data target address)
//using mod move (unit id, place to store data, data target address, min value, max value)
nFile[0]=(int16_t)modMove(0x06); //hz xx.x
mainRoutine();
updateRegisters();
nFile[7]=(int16_t)modMove(0x07); //Amps xx.x
mainRoutine();
updateRegisters();
nFile[2]=(int16_t)modMoveScaled(0x13, 0, 1000); //Analog value 1 (0-1000=(0-1000) for a percentage
mainRoutine();
updateRegisters();
nFile[3]=(int16_t)modMoveScaled(0x14, 0, 1000); //Analog value 2 (200-1000)=(0-1000) for a percentage
mainRoutine();
updateRegisters();
nFile[8]=(int16_t)modMove(0x16); //DC Bus Voltage
mainRoutine();
updateRegisters();
nFile[6]=(int16_t)modMove(0xAC); //Motor Rated Current xx.x
} else {
pollDone=false;
}
if (pollDone){
pollTemp=millis();
}
if ((millis()-pollTemp2)>pollInterval2){
pollDone2=true;
Serial.print("The current setpoint setpoint is: ");
Serial.println(nFile[2]);
Serial.print("The current wakeup point setpoint is: ");
Serial.println(nFile[4]);
Serial.print("PSI at setpoint: ");
Serial.println(getBitWord(2, 0, 0));
Serial.print("PSI at wakeup point: ");
Serial.println(getBitWord(2, 0, 1));
Serial.print("Start sleep timer: ");
Serial.println(getBitWord(2, 0, 2));
Serial.print("Hz at 60: ");
Serial.println(getBitWord(2, 0, 3));
Serial.print("Torque <= 46%: ");
Serial.println(getBitWord(2, 0, 4));
Serial.print("Start fault1 timer: ");
Serial.println(getBitWord(2, 0, 5));
Serial.print("Drive Running: ");
Serial.println(getBitWord(2, 0, 7));
Serial.print("Comm Fault: ");
Serial.println(getBitWord(2, 1, 0));
Serial.print("Underload fault: ");
Serial.println(getBitWord(2, 1, 1));
Serial.print("current reset state: ");
Serial.println(!getBitWord(0, 0, 1));
Serial.print("Flosting point torque= ");
Serial.println(fFile[2]);
} else {
pollDone2=false;
}
if (pollDone2){
pollTemp2=millis();
}
}
}

STM32F446's CAN transmission completed interrupt not firing :(

I'm working with the CAN Module from the STM32F446RE board which has the MCU mentioned in the title. I'm trying to transmit some data on the UART via Tera Term terminal and take this data and send it via Loopback mode and read it back. For starters I have generated the configuration from CubeMx and written some code to transmit a numerical value which the user enters to the can 'network' and when that happens I want to go into an can completed transmission ISR and print some message on the UART from there to indicate that the transfer was completed.
In the CubeMx I have configured the CAN interrupts like this:
CAN1 TX interrupt enabled
CAN1 RX interrupt enabled(because I will also want to trigger the receive interrupt after I fix this issue)
This is the part of the code(I cannot copy paste all as this is the post will become too long just ask me if I need to provide more of my code):
while (1)
{
/*keep getting what the user enters on the UART untill enter is pressed*/
while(received_data != '\r')
{
HAL_UART_Receive(&huart2,&received_data,1,HAL_MAX_DELAY);
recvd_buffer[buf_indx] = received_data;
buf_indx++;
if(buf_indx > 1)
{
buf_indx = 0;
}
}
if( recvd_buffer[0] == '1' || recvd_buffer[0] == '0')
{
received_data = 0;
buf_indx = 0;
user_data = "\n\rOK. Starting CAN transmission in interrupt mode\n\r";
len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
//CAN will start sending data in non-blocking mode
CAN_Tx(recvd_buffer[0]);
recvd_buffer[0] = 0;
recvd_buffer[1] = 1;
}
else
{
recvd_buffer[0] = 0;
recvd_buffer[1] = 1;
received_data = 0;
user_data = "\n\rInvalid value. Please enter either 1 or 2\n\r";
len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
}
}
Below I have also implemented the 3 Tx mailbox transmit complete callback functions:
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
uint16_t user_data = "\n\rTransmission completed mailbox_0\n\r";
uint16_t len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
{
user_data = "\n\rTransmission completed mailbox_1\n\r";
uint16_t len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)
{
user_data = "\n\rTransmission completed mailbox_2\n\r";
uint16_t len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
This is the CAN_Tx function that makes use of the CAN hal driver to send the data:
void CAN_Tx(uint8_t value)
{
uint8_t mailbox_no;
CAN_TxHeaderTypeDef can_header;
can_header.StdId = 0;
can_header.ExtId = 0;
can_header.IDE = CAN_ID_STD;
can_header.RTR = CAN_RTR_DATA;
can_header.DLC = 1;
can_header.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1, &can_header, value, &mailbox_no);
}
I have debugged the code in main and it seems to work fine. I got no error in the Can_Tx function it returns with success. From my understanding from the datasheet of the microcontroller(secttion 30.8 - bxCAN interrupts) if the timer1 transmit interrupt is enabled than depending on which mailbox was used for transmission one of those callbacks should get executed. However that does not happen the code inside them won't get executed. Please help me understand what I'm doing wrong. Thank you!

Ethernet Shield Not Appearing on Network

I am currently working on a project that involves an arduino uno and an ethernet shield. I am using a sketch from Randomnerdtutorials.com (with slight changes to fit my router) which I will provide. The server that the ethernet shield creates does show up and work when I put the IP address in the URL bar (192.168.1.178:8080) The ethernet shield itself however does not show up on my list of attached devices to my Netgear router. It does occasionally but then disappears. Any ideas? I looked at another thread that stated to replace
Ethernet.begin(mac, ip, gateway, subnet);
with
Ethernet.begin(mac);
but that did not work. Any ideas are welcome. Here is the full code
/*
Created by Rui Santos
Visit: http://randomnerdtutorials.com for more arduino projects
Arduino with Ethernet Shield
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>
int led = 4;
Servo microservo;
int pos = 0;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 178 }; // ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = { 192, 168, 1, 130 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(8080); //server port
String readString;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
pinMode(led, OUTPUT);
microservo.attach(7);
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip, gateway, subnet);
// Ethernet.begin(mac);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// Create a client connection
EthernetClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 100) {
//store characters to string
readString += c;
//Serial.print(c);
}
//if HTTP request has ended
if (c == '\n') {
Serial.println(readString); //print to serial monitor for debuging
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
client.println();
client.println("<HTML>");
client.println("<HEAD>");
client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
client.println("<link rel='stylesheet' type='text/css' href='http://randomnerdtutorials.com/ethernetcss.css' />");
client.println("<TITLE>Random Nerd Tutorials Project</TITLE>");
client.println("</HEAD>");
client.println("<BODY>");
client.println("<H1>Random Nerd Tutorials Project</H1>");
client.println("<hr />");
client.println("<br />");
client.println("<H2>Arduino with Ethernet Shield</H2>");
client.println("<br />");
client.println("Turn On LED");
client.println("Turn Off LED<br />");
client.println("<br />");
client.println("<br />");
client.println("Rotate Left");
client.println("Rotate Right<br />");
client.println("<p>Created by Rui Santos. Visit http://randomnerdtutorials.com for more projects!</p>");
client.println("<br />");
client.println("</BODY>");
client.println("</HTML>");
delay(1);
//stopping client
client.stop();
//controls the Arduino if you press the buttons
if (readString.indexOf("?button1on") >0){
digitalWrite(led, HIGH);
}
if (readString.indexOf("?button1off") >0){
digitalWrite(led, LOW);
}
if (readString.indexOf("?button2on") >0){
for(pos = 0; pos < 180; pos += 3) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
microservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
if (readString.indexOf("?button2off") >0){
for(pos = 180; pos>=1; pos-=3) // goes from 180 degrees to 0 degrees
{
microservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
//clearing string for next read
readString="";
}
}
}
}
}
Looks like the problem is with DHCP. Try
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
else{Serial.println("DHCP OK!");
and see if it gives DHCP failure

How to get the audio stream from PJSIP when there is no audio hardware device

I want to use PJSIP's C API to record the incoming audio to a file on a machine with no hardware sound device .
I'm unsure about the details, but the sparse documentation for PJSIP suggests it should be
possible through the pjsua_set_null_snd_dev() call.
In the fully functioning (Windows biased) example below the call pjmedia_aud_dev_default_param(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, &param) returns PJMEDIA_AUD_INVALID_DEV in the status.
The code generates this same error on Linux (Ubuntu 14) and Windows 10 when there are no hardware audio devices present.
If there is an hardware audio device driver installed the exact same code works fine on both OSes.
I have compiled the PJSIP libraries with PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO enabled.
On Linux the presence of the module snd-dummy does not help.
How do I get access to the audio data stream from a SIP call after calling pjsua_set_null_snd_dev()?
#include <pjlib.h>
#include <pjlib-util.h>
#include <pjnath.h>
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjsip_simple.h>
#include <pjsua-lib/pjsua.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pj/log.h>
#include <pj/os.h>
int main(int, char **)
{
// Create pjsua first!
pj_status_t status = pjsua_create();
if (status != PJ_SUCCESS)
{
fprintf(stderr,"pjsua_create error\n");
return -1;
}
// Init pjsua
pjsua_config cfg;
pjsua_logging_config log_cfg;
pjsua_config_default(&cfg);
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4;
status = pjsua_init(&cfg, &log_cfg, NULL);
if (status != PJ_SUCCESS)
{
fprintf(stderr,"pjsua_init error\n");
return -1;
}
// Proactively list known audio devices so we are sure there are NONE
pjmedia_aud_dev_info info[64];
unsigned info_count = 64;
pjsua_enum_aud_devs(info, &info_count);
fprintf(stderr,"Listing known sound devices, total of [%u]\n", info_count);
for (unsigned i = 0; i<info_count; ++i)
{
fprintf(stderr,"Name [%s]", info[i].name);
}
// Add transport
pjsua_transport_config tcfg;
pjsua_transport_id trans_id;
pjsua_transport_config_default(&tcfg);
tcfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &trans_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_transport_create error\n");
return -1;
}
// Initialization is done, now start pjsua
status = pjsua_start();
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_start error\n");
return -1;
}
// Set NULL sound
status = pjsua_set_null_snd_dev();
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_set_null_snd_dev error");
return -1;
}
// Register to a SIP server by creating SIP account, I happen use use Asterisk
pjsua_acc_id acc_id;
fprintf(stderr, "Setting up SIP server registration\n");
{
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
cfg.id = pj_str("sip:6001#10.0.0.21");
cfg.reg_uri = cfg.id; // same as ID
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str("*");
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str("6001");
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str("teddy");
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_acc_add error\n");
return -1;
}
}
fprintf(stderr, "Waiting for SIP server registration to complete....\n");
Sleep(2000); // sleep 2 seconds
// Call extension 9 on my Asterisk server at 10.0.0.21:5060
pj_str_t sip_target(pj_str("sip:9#10.0.0.21"));
fprintf(stderr, "Making call to [%s]\n", sip_target.ptr);
pjsua_call_id call_id;
status = pjsua_call_make_call(acc_id, &sip_target, 0, NULL, NULL, &call_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_call_make_call error\n");
return -1;
}
pj_pool_t * pool = nullptr;
pjmedia_port * wav = nullptr;
pjmedia_aud_stream *strm = nullptr;
pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav-audio", 1000, 1000, NULL);
if (nullptr == pool)
{
fprintf(stderr,"Pool creation failed\n");
return -1;
}
// 8kHz, single channel 16bit MS WAV format file
status = pjmedia_wav_writer_port_create(pool, "test.wav", 8000, 1, 320, 16, PJMEDIA_FILE_WRITE_PCM, 0, &wav);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error creating WAV file\n");
return -1;
}
pjmedia_aud_param param;
//////////////////////////////////////////////////////
// FAILURE HERE : This is the function call which returns PJMEDIA_AUD_INVALID_DEV
//////////////////////////////////////////////////////
status = pjmedia_aud_dev_default_param(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, &param);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjmedia_aud_dev_default_param()");
return -1;
}
param.dir = PJMEDIA_DIR_CAPTURE;
param.clock_rate = PJMEDIA_PIA_SRATE(&wav->info);
param.samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
param.channel_count = PJMEDIA_PIA_CCNT(&wav->info);
param.bits_per_sample = PJMEDIA_PIA_BITS(&wav->info);
status = pjmedia_aud_stream_create(&param, &test_rec_cb, &test_play_cb, wav, &strm);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error opening the sound stream");
return -1;
}
status = pjmedia_aud_stream_start(strm);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error starting the sound device");
return -1;
}
// Spend some time allowing the called party to pick up and recording to proceed
Sleep(10000); // sleep 10 seconds
// Clean up code omitted
return 0;
}
Apologies to the pure of heart for the mix of C and C++ above.
Solved this by loading the Alsa module snd-dummy.
Look in /lib/modules/YOUR_KERNEL_VERSION/modules.dep if its mentioned.
If you have it then load it with modprobe snd-dummy
Otherwise recompile your Kernel to include it as a module or follow the installation in the link above.

setsockopt() get EBADF in mmaped netlink

Im trying to use memory map I/O netlink to transfer bulk packets from kernel to user space, and I followed a guide document from Patrick McHardy 1. However, when I try to setup the shared ring buffer in user space by using:
setsockopt(sock_fd, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req));
setsockopt(sock_fd, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req));
Both functions return -1, and the errno is 1, which means the descriptor is invalid. Im confused about that because I also referred to many other source codes and they can setup the ring successfully.
My code is almost the same as Patrick's 1:
int sock_fd = -1;
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_DECODE);
if (sock_fd < 0)
return -1;
bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));
/* init the mmap buffer */
unsigned int block_size = 16 * getpagesize();
struct nl_mmap_req req = {
.nm_block_size = block_size,
.nm_block_nr = 64,
.nm_frame_size = 16384,
.nm_frame_nr = 64 * block_size / 16384,
};
/* Configure ring parameters */
if (setsockopt(sock_fd, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req)) < 0){
if(errno > 0)
printf("%d\n", errno);
}
if (setsockopt(sock_fd, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req)) < 0){
if(errno > 0)
printf("%d", errno);
exit(1);
}
This code is built in Ubuntu 14.04, and kernel version is 3.13.0-74-generic.
Anyone idea about it? Thanks a lot.