I'm trying to run Zephyr Logging by using DMA on UART on STM32L432KC.
That's simple main loop:
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(example, LOG_LEVEL_DBG);
int main(void)
{
while (1) {
LOG_INF("main loop");
k_msleep(1000);
}
}
That's full configuration:
CONFIG_SOC_SERIES_STM32L4X=y
CONFIG_SOC_STM32L432XX=y
# Enable MPU
CONFIG_ARM_MPU=y
# Enable HW stack protection
CONFIG_HW_STACK_PROTECTION=y
# enable uart driver
CONFIG_SERIAL=y
# enable GPIO
CONFIG_GPIO=y
# Enable Clocks
CONFIG_CLOCK_CONTROL=y
# console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_UART_ASYNC_API=y
# enable DMA
CONFIG_DMA=y
# enable pin controller
CONFIG_PINCTRL=y
# config logging
CONFIG_LOG=y
CONFIG_LOG_BACKEND_UART_ASYNC=y
CONFIG_LOG_MODE_IMMEDIATE=y
Then build it and flash:
west flash -b nucleo_l432kc
In logs I see following output:
*** Booting Zephyr OS build zephyr-v3.2.0-863-g78809549ee4c ***
[00:00:01.001,000] <inf> example: main loop
When I change CONFIG_LOG_MODE_IMMEDIATE=y to CONFIG_LOG_MODE_DEFERRED=y it prints log every second like I expect.
I discovered that code stops here on k_sem_take(&sem, K_FOREVER) and this uart_callback is never called to release this mutex.
Also discovered when following options are enabled it's working fine with CONFIG_LOG_MODE_DEFERRED=y option:
CONFIG_LOG_PROCESS_THREAD=y
CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100
But that makes me wondering why another thread must be created? DMA is no blocking. Really confusing.
What am I missing? I would like to delegate all logging to DMA buffer with Logging subsystem features, without additional threads and buffering. Is there someone experienced who can point what is wrong?
I am writing a C program with the aim of configuring a peripheral device (the CS5368 ADC) via the I2C interface of a Dante Brooklyn II, a board based on a Microblaze soft-core processor running uClinux 2.4.
I have implemented the configuration following the Dante OEM docs for guidance, however when running my program I am encountering an "Operation not permitted" (EPERM) error when attempting to write data to I2C using i2c_smbus_write_byte_data.
Here is the section of code containing the culprit call to i2c_smbus_write_byte_data:
// Set ADC I2S to "Slave mode all speeds".
printf("Set the CS5368 I2S mode to slave\n");
unsigned char adc_dif = 0x01; // I2S mode
unsigned char adc_mode = 0x03; // Slave mode all speeds
unsigned char data = 0x90 | (adc_dif << 2) | adc_mode;
result = i2c_smbus_write_byte_data(i2c_fd, CS5368_GCTL_MDE, data);
if (result < 0) {
perror("Failed to write to the 'Global Mode Control' register");
return -1;
}
Here is the code within context of the full source of the small program. The program begins by resetting the CS5368 via a GPIO pin before doing the configuration via I2C.
EPERM is returned whether or not I have the CS5368 wired up. I've been able to successfully configure the CS5368 using the I2C interface of an Arduino Uno, so the issue does not appear to be related to the CS5368.
To run the program I login to the board via telnet as root, so I doubt the error has anything to do with user permissions.
The OEM docs state:
The Brooklyn II module can operate as an I2C controller running at
100Khz and using 7 bit addressing mode. It supports multi-master
operation. I2C devices can be accessed from user application running
on the Brooklyn II module. The interface supports the SMBus (System
Management Bus) protocol, which is a subset from the I2C protocol.
It goes on to list the supported i2c_smbus_* functions including i2c_smbus_write_byte_data, so the issue does not appear to be related to lack of support for SMBus or I2C.
I came across a related issue where a user was getting an EPERM error code when attempting to use the I2C write API, however the solution appears to have been to use the i2c_smbus_* API instead which I am already doing.
Any advice on what could be causing this error code to be returned or how to debug the issue further would be greatly appreciated!
Edit: In case it helps, here is the full output, starting from logging onto the board via telnet after having moved the exe to /tmp via ftp:
$ telnet 169.254.72.245
Trying 169.254.72.245...
Connected to 169.254.72.245.
Escape character is '^]'.
login: root
Password:
BusyBox v1.23.2 (2018-05-31 11:33:18 AEST) hush - the humble shell
/ # cd /tmp
/var/tmp # ./cs5368-i2c-config
Open GPIO device
Set GPIO tristate outputs
Set GPIO pins low
Sleep for 10 secs
Set GPIO pins high
Close GPIO file descriptor
Searching for I2C device
Opening /dev/i2c-0
Setting I2C_SLAVE 4c...
I2C Interface found: /dev/i2c-0
Set the CS5368 as the slave
Set the CS5368 I2S mode to slave
Failed to write to the 'Global Mode Control' register: Operation not permitted
I have a Qt5.12.4 MinGw64 app where I want to catch a USB event. In Windows 10 the MS driver for STM/USB emits error messages and I can use that as a trigger. Inelegant but it works, until I try to run it in a Win7-8.1 app where the driver is a third party STM driver with a VCP wrapper. I am thinking I need to adopt libusb to try and catch the ports change of state, but I am at a loss as how to proceed. I can see the port info in Device Manager, I just dont know how to get to it. Some of the questions going through my head....
1) Can I just make an OS call to read the port info? (if so, how?)
2) Can libusb and QSerialport co-exist on the same port?
3) What calls to LibUSB1.0 do I make to query the port status?
4) Is there a Windows cli utility like lsusb (wmic??) where I could scrape the data?
5) Which solution is likely to be the best cross platform solution?
I am using this trigger to start dfuse as a process that does a firmware update automatically on my STM board.
I have looked over the libusb1.0 docs but I do not understand just how I can use it. If that is correct solution, an example of how to query the Com port data and state would be most appreciated.
I tried using qDebug() to print out all of the serialportInfo data, while in serial or DFU state, but there is nothing there that is useful that I can use as a trigger.
USB serial mode = Serial port info is: ("COM3", "USB Serial Device", "Microsoft", "00000000001A", "\\.\COM3", "483", "5740", "1", " no data", "1")
USB DFU mode = Serial port info is: ("COM3", "N/A", "N/A", "N/A", "\\.\COM3", "N/A", "N/A", "no data", " no data", "no data")
I need some direction as to how to grab this port info so I dont really have any code that matters, but I am including an excerpt of my working process function.
This code works just fine to actually perform the firmware load. I just need a way to actually trigger it from a USB port change of state
void updateDevice_Dialog::update_firmware(QString fileName)
{
qDebug() << "Updating firmware: " << fileName ;
QDir dir;
ui->progress_label->setText("Preparing to update Firmware .....");
if(dir.setCurrent(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)+"/firmware"))
{
QSettings settings;
QString comPort = settings.value("USBPort").toString();
ui->progress_label->setText("Setting port to: "+comPort+" and starting download .....");
ui->avr_progressBar->setValue(0);
ui->avr_progressBar->setRange(0,100);
ui->avr_progressBar->setHidden(false);
progress_steps = 0; //reset avrProcess line output counter;
qDebug() << "Starting process for stm-dfu on serial port: " << comPort;
connect(avr_Process,SIGNAL(error(QProcess::ProcessError)),this,SLOT(process_error(QProcess::ProcessError)));
connect(avr_Process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(process_finished(int,QProcess::ExitStatus)));
connect(avr_Process,SIGNAL(readyReadStandardOutput()),this,SLOT(process_readLine()));
connect(avr_Process,SIGNAL(errorOccurred(QProcess::ProcessError)),avr_Process,SLOT(kill()));
connect(avr_Process,SIGNAL(error(QProcess::ProcessError)),ui->avr_progressBar,SLOT(close()));
QString dfu_command = "\""+QCoreApplication::applicationDirPath()+"/Tools/\"dfusecommand -c -d --v --fn "
"\""+QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)+"/firmware/\""+fileName;
qDebug().noquote() << "dfu command string is: "<< dfu_command << " Current dir is: " << dir.currentPath();
avr_Process->start(dfu_command);
avr_Process->waitForFinished(20000);
}
}
From the perspective of the host system, rebooting the microcontroller into DFU will look like the original device was disconnected, and a completely different device was plugged in shortly afterwards.
If you need to watch for this, set up a libusb hotplug callback so that you'll be notified when the DFU device is attached.
hello I am newby to irda sockets. I have a macbook pro that has a built-in Apple IR reciver. I am using visual studio 2013,
#include <af_irda.h>
#include <winsock2.h>
#incude <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
int main()
{
WORD wVersion = MAKEWORD(2,2);
WSADATA wSaData;
if(WSAStartup(wVersion), &wSaData))
{
cout << "Failed to initialize winsock library!\n";
return 1;
}
int irSock = socket(AF_IRDA, SOCK_STREAM, 0);
if(irSock == SOCKET_ERROR)
{
cout << "Socket creation failed! error code: " << WSAGetLastError() << endl;
}
//the socket creation failed with 10047
cout << endl << endl << endl;
system("pause");
return 0;
}
does this mean that my laptop doesn't have irda adapter?? if so what is IR receiver then?? can't we use IR receiver to write irda socket applications???
*** please anyhelp is highly appreciated
1- socket creation failed and WSAGetLastError() returns 10047 when the address family is not supported. (ie: the error doesn't belong to hardware but to platform)
on windows7, 8, 10 (almost all new windows OSs exclude irDA support) we get this error while on windows xp, linux fedora the socket creation succeeds BUT this doesn't mean that your laptop/pc is necessarily provided with irDA adapter.
2- IR receiver is not an irDA adapter:
An IR receiver is just a dumb receiver that reads IR commands (that was a tough one!). IRDA is a complex bidirectional protocol involving reliable communication with acknowledgments typically used to transfer files or emulate a serial interface between hand held devices and a laptop or PC. Or, as Wannabe said, you want an IR receiver since IRDA doesn't know how to listen to remote commands.
This is first time i am writing a driver for linux SPI framework for ADS7846.
Found this excellent tutorial to understand the concept of linux SPI :---
http://www.jumpnowtek.com/index.php?option=com_content&view=article&id=57&Itemid=62
It also have a sample co-de.
https://github.com/scottellis/spike/blob/part3/spike.c
1> Few points which i was not able to get why we are using semaphore
befor accessing -- spike_dev.user_buff.
do we really need semaphore ? Because at a time my application program willonly read() or write() or open() the driver ?
2> Also to select the chip select we are using :--
/* specify a chip select line */
SPI_BUS_CS1
Here why we are not specifing which PORT will the CS - line be connected to ?
3> As what i have read spinlock should be used with interupt handler. Also what is the use of this spinlock in the driver.
Here we do not have spi Interupt handler.But while accessing -- spi_async & spi_device -- we are using spinlock ?
spin_lock_irqsave
spi_async
spin_unlock_irqrestore
4> Also can we have multiple "protocol drivers" registered to same SPI device ?
Any suggestion will be appreciated.
2> it is could be mentioned in .controllerdata the bus num and chipselect is to enumerate the SPI devices
3> it is used for taks which can sleep