Using PuTTY to print from STM32 - putty

I want to print messages from my STM32 Nucleo-L073RZ microcontroller. How should I go about it?
Should I use UART? Where can I get the corresponding code?
#include "stm32l0xx.h"
#include "stm32l0xx_nucleo.h"
#include "stm32l0xx_hal.h"
#include "stdio.h"
static void GPIO_Init (void);
static void UART_Init (void);
int main(void)
{
HAL_Init();
GPIO_Init();
printf("Hello");
while(1)
{
}
}
static void GPIO_Init(void)
{
BSP_LED_Init(LED2);
BSP_LED_On(LED2);
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA13*/
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
}
/*Uart Init Function*/
static void UART_Init(void)
{
}
void EXTI4_15_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_PIN)
{
BSP_LED_Toggle(LED2);
counter();
}
int counter()
{
int i;
i = 0;
i++;
printf("/n %d", i);
}
How do I display the counter on my PC? I want the number of times the interrupt is given to be seen on PuTTY. Should I interface an UART or is it possible to print?

You can use UART on the Nucleo
All Nucleo boards have a built-in UART-to-USB module that automatically transmits data to a Serial Port on your computer. If on windows, open your Control Panel, go to Device Manager, and under COM Ports you should see your Nucleo.
Initialize the UART Peripheral
Reference your Nucleo user manual to see which UART pins connect to the USB port (STM32CubeMX might have these already mapped).
When initializing the peripheral, select a baud rate like 9600, and remember it
Configure PuTTy
Enter the COM port of the Nucleo and the Baud Rate that you selected earlier, and select Serial as the transmission method. You might have to disable some of the hardware flow control options if they are enabled
Code to transmit
HAL has functions for transmitting over UART. Something like HAL_UART_Transmit(...). You'll have to look up how to use the function specifically, plenty of great tutorials out there.
I personally use sprintf to print nicely formatted strings over UART like this:
char buf[64];
sprintf(buf, "Value of counter: %d\r\n", i);
// change huartX to your initialized HAL UART peripheral
HAL_UART_Transmit(&huartX, buf, strlen(buf), HAL_MAX_DELAY);

First Add use UART Handler and its init in this function i used UART2 change it to your periph if you use Stm32 Cube or IDE just select the periph it is automatically generated.
Use this function in order to use the print function it's act the same like Printf.
#include <stdint.h>
#include <stdarg.h>
void printmsg(char *format,...) {
char str[80];
/*Extract the the argument list using VA apis */
va_list args;
va_start(args, format);
vsprintf(str, format,args);
HAL_UART_Transmit(&huart2,(uint8_t *)str, strlen(str),HAL_MAX_DELAY);
va_end(args);
}
In your Counter function just Change printf to printmsg
int counter()
{
int i;
i = 0;
i++;
printmsg("/n %d", i);
}
Remember to change Printmsg uart Handler .

Related

erorr on platformIO ide

Hello everyone I wrote the following code in platformIO IDE to read a value from the YL-69 module and display it in 7segment, but I got this error:
error: no 'void SevenSegmentFun::bouncingBall(uint16_t, uint16_t, bool)' member function declared in class 'SevenSegmentFun'
#include <Arduino.h>
#include "SevenSegmentTM1637.h"
const byte PIN_CLK = 2; // define CLK pin (any digital pin)
const byte PIN_DIO = 3; // define DIO pin (any digital pin)
SevenSegmentTM1637 display(PIN_CLK, PIN_DIO);
void setup() {
Serial.begin(9600);
display.begin();
display.setBacklight(100);
display.print("INIT");
delay(1000);
display.clear();
// wait 1000 ms
pinMode(A0,INPUT);
};
// run loop (forever)
void loop() {
int i=analogRead(A0);
display.print(i);
delay(1000);
};
What is wrong? and How can i fix it?

Linux device driver for a Smart Card IC module

I have a smart card IC module, and I want to create a Linux device driver for it. This module is using SPI as the controlling line and has an interrupt line to indicate whether a card is ready. I know how to create a SPI device in Linux kernel and how to read data in the kernel when the interruption happens. But I have no idea on how to transfer the data to the user space (maybe need to create a device node for it), and how to give the user space a interruption to notify it. Does anyone have some suggestion?
One way you can go about this is by creating a devfs entry and then having the interested process open that device and receive asynchronous notification from the device driver using fasync.
Once you have the notification in user space you can notify other interested processes by any means you deem fit.
I am writing a small trimmed down example illustrating this feature.
On the driver side
/* Appropriate headers */
static int myfasync(int fd, struct file *fp, int on);
static struct fasync_struct *fasyncQueue;
static struct file_operations fops =
{
.open = charDriverOpen,
.release = charDriverClose,
.read = charDriverRead,
.write = charDriverWrite,
.unlocked_ioctl = charDriverCtrl,
// This will be called when the FASYNC flag is set
.fasync = myfasync,
};
static int __init charDriverEntry()
{
// Appropriate init for the driver
// Nothing specific needs to be done here with respect to
// fasync feature.
}
static int myfasync(int fd, struct file *fp, int on)
{
// Register the process pointed to by fp to the list
// of processes to be notified when any event occurs
return fasync_helper(fd, fp, 1, &fasyncQueue);
}
// Now to the part where we want to notify the processes listed
// in fasyncQueue when something happens. Here in this example I had
// implemented the timer. Not getting in to the details of timer func
// here
static void send_signal_timerfn(unsigned long data)
{
...
printk(KERN_INFO "timer expired \n");
kill_fasync(&fasyncQueue, SIGIO, POLL_OUT);
...
}
On the user land process side
void my_notifier(int signo, siginfo_t *sigInfo, void *data)
{
printf("Signal received from the driver expected %d got %d \n",SIGIO,signo);
}
int main()
{
struct sigaction signalInfo;
int flagInfo;
signalInfo.sa_sigaction = my_notifier;
signalInfo.sa_flags = SA_SIGINFO;
sigemptyset(&signalInfo.sa_mask);
sigaction(SIGIO, &signalInfo, NULL);
int fp,i;
fp = open("/dev/myCharDevice",O_RDWR);
if (fp<0)
printf("Failed to open\n");
/*New we will own the device so that we can get the signal from the device*/
// Own the process
fcntl(fp, F_SETOWN, getpid());
flagInfo = fcntl(fp, F_GETFL);
// Set the FASYNC flag this triggers the fasync fops
fcntl(fp, F_SETFL, flagInfo|FASYNC);
...
}
Hope this clears things up.
For more detailed reading I suggest you read this

User space netlink socket receives empty messages from kernel space

Disclaimer - I have to admit that it's the 1'st time I'm using this kernel interface (socket).
I'm currently working on a design of a kernel module that is based on a netlink socket .
I'm using Ubuntu14.04 and linux kernel 4.
As a starter, I wanted to make sure that I can use the netlink socket in both directions.
I've written an application that does the following:
1) User send a message to kernel via the netlink socket.
2) Kernel, upon receiving the message – sends "ABCD" string message to a workqueue.
3) When the "ABCD" message is received by the workqueue, it calls a function (named - my_wq_function) which send it back to the user space via netlink socket.
4) In the user space I'm using a recvmsg function (blocking until a message is received) and displays the "ABCD" message.
My problem is that the return value from the recvmsg function is 20 (instead of 4), and the data itself (i.e. NLMSG_DATA) is empty.
During the debug I tried to change the message to "ABCD1234" and got a return value of 24 bytes, however the data is still empty.
I also verified that my entire path until the point of sending the "ABCD" from kernel to the socket is OK.
Not sure what I'm doing wrong here & will highly appreciate your help.
Thanks in advance, MotiC.
my code example can be found below:
User space code:
printf("netlink receiver thread started...\n");
nlh_rcv = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
while(true) //endless loop on netlink socket
{
memset(nlh_rcv, 0, NLMSG_SPACE(MAX_PAYLOAD));
iov_rcv.iov_base = (void *)nlh_rcv;
iov_rcv.iov_len = nlh_rcv->nlmsg_len;
msg_rcv.msg_name = (void *)&dest_addr;
msg_rcv.msg_namelen = sizeof(dest_addr);
msg_rcv.msg_iov = &iov;
msg_rcv.msg_iovlen = 1;
ret=recvmsg(sock_fd, &msg_rcv, 0);
printf("errno=%i bytes=%i message from kernel: %s\n",errno, ret, (char*)NLMSG_DATA(nlh_rcv));
uint8_t mymsg[100];
memcpy(mymsg, NLMSG_DATA(nlh_rcv), 100);
printf("message from kernel: %s\n",mymsg);
}
Kernel space code:
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <net/sock.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
MODULE_LICENSE("GPL");
#include "rf_Kdriver_main.h"
//------ definitions ------------------------------------------------------------------------------------------------------------
#define NETLINK_USER 31
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sock *nl_sk = NULL;
struct nlmsghdr *nlh;
struct nlmsghdr *nlh_out;
struct sk_buff *skb_out;
char buf_to_user[100];
int pid;
//------------------------------------------------------------------------------------------------------------------------------
struct workqueue_struct *my_wq;
typedef struct {
struct work_struct my_work;
uint8_t msg_to_pc[128];
uint8_t msg_len;
} my_work_t;
my_work_t *work, *work2;
//-----------------------------------------------------------------------------------------------------------------------------
static void my_wq_function( struct work_struct *work)
{
int res;
my_work_t *my_work = (my_work_t *)work;
skb_out = nlmsg_new(my_work->msg_len,0);
if (!skb_out)
{
printk("Failed to allocate new skb\n");
return;
}
nlh_out = nlmsg_put(skb_out, 0, 0, NLMSG_DONE,my_work->msg_len, 0);
NETLINK_CB(skb_out).dst_group = 0;
memcpy((char*)NLMSG_DATA(nlh_out), my_work->msg_to_pc , my_work->msg_len);
printk( "dequeue message to pc=%s len=%i\n", (char*)NLMSG_DATA(nlh_out), (int)strlen((char*)NLMSG_DATA(nlh_out)));
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res<0)
printk("Failed to send message from kernel to user\n");
kfree( (void *)work );
return;
}
//-----------------------------------------------------------------------------------------------------------------------------
int send_up_msg_to_workque(uint8_t msg_to_pc[], uint8_t msg_len)
{
int ret=0;
work = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL);
if (work) {
INIT_WORK( (struct work_struct *)work, my_wq_function );
memcpy(work->msg_to_pc, msg_to_pc, msg_len);
work->msg_len = msg_len;
ret = queue_work( my_wq, /*(struct work_struct *)RR*/work );
printk("kuku ret=%i msg=%s\n",ret,work->msg_to_pc);
}
return ret;
}
//------------------------------------------------------------------------------------------------------------------------------
static void netlink_recv_msg(struct sk_buff *skb)
{
char *msg = "ABCD1234";
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
nlh=(struct nlmsghdr*)skb->data;
printk(KERN_INFO "Netlink at kernel received msg payload: %s\n",(char*)NLMSG_DATA(nlh));
//rr
pid = nlh->nlmsg_pid;
send_up_msg_to_workque((uint8_t*) msg, strlen(msg));
}
//-------------------------------------------------------------------------------------------------------------------------------------
struct netlink_kernel_cfg cfg = {
.input = netlink_recv_msg,
};
static int __init rf_driver_start(void)
{
printk(KERN_INFO "Loading RF Driver module1...\n");
my_wq = create_workqueue("my_queue");
if (!my_wq)
{
printk("Failed to create work queue\n");
}
printk("Entering: %s\n",__FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
if(!nl_sk)
{
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
//--------------------------------------------------------------------------------------------------------------
static void __exit rf_driver_end(void)
{
netlink_kernel_release(nl_sk);
flush_workqueue(my_wq);
destroy_workqueue(my_wq);
printk(KERN_INFO "RF Driver exit...\n");
}
module_init(rf_driver_start);
module_exit(rf_driver_end);
Update,
I changed my user space function to:
char buf[100];
ret=recv(sock_fd, buf, 100, 0);
instead of:
ret=recvmsg(sock_fd, &msg_rcv, 0);
and it works...
does anyone have an idea regarding this strange behavior ?
Thanks.
Can you please paste complete userspace code.
I guess 'len' int this code is the issue:
memset(nlh_rcv, 0, NLMSG_SPACE(MAX_PAYLOAD));
iov_rcv.iov_len = nlh_rcv->nlmsg_len; << check to what value is it getting initialized.

MicroBlaze MCS Fixed Timer Interrupts

I'm trying to get a fixed timer in a MicroBlaze MCS core to call a function to toggle some LEDs as a proof of concept.
Here is my code I have now
#include <xparameters.h>
#include <xiomodule.h>
#include <xiomodule_l.h>
XIOModule gpo1;
volatile u32 ct = 0;
void timerTick(void* ref){
ct++;
XIOModule_DiscreteWrite(&gpo1, 1, ct);
XIOModule_DiscreteWrite(&gpo1, 2, ct);
}
int main() {
XIOModule_Initialize(&gpo1, XPAR_IOMODULE_0_DEVICE_ID);
XIOModule_Start(&gpo1);
XIOModule_EnableIntr(XPAR_IOMODULE_0_BASEADDR, XIN_IOMODULE_FIT_1_INTERRUPT_INTR);
XIOModule_Connect(&gpo1, XIN_IOMODULE_FIT_1_INTERRUPT_INTR, timerTick, NULL);
while (1) {
}
}
The GPO stuff works. If I put it in the while loop I can get the LEDs to toggle as expected. However, as the code currently is, timerTick() never gets called. I am really confused on how to properly setup the interrupt and I haven't been able to find any documentation on this. The best I could find was http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_4/pg048-microblaze-mcs.pdf which covers more about the hardware of the core and not how to program it.
What is the proper way to enable and connect an interrupt?
I found the solution thanks to this forum post http://forums.xilinx.com/t5/Embedded-Development-Tools/Can-not-fire-MicroBlaze-MCS-interrupt/td-p/256372
#include <xparameters.h>
#include <xiomodule.h>
#include <xiomodule_l.h>
XIOModule gpo1;
volatile u32 ct = 0;
void timerTick(void* ref) {
ct++;
XIOModule_DiscreteWrite(&gpo1, 1, ct);
XIOModule_DiscreteWrite(&gpo1, 2, ct);
}
int main() {
XIOModule_Initialize(&gpo1, XPAR_IOMODULE_0_DEVICE_ID);
microblaze_register_handler(XIOModule_DeviceInterruptHandler, XPAR_IOMODULE_0_DEVICE_ID);
XIOModule_Start(&gpo1);
XIOModule_Connect(&gpo1, XIN_IOMODULE_FIT_1_INTERRUPT_INTR, timerTick, NULL);
XIOModule_Enable(&gpo1,XIN_IOMODULE_FIT_1_INTERRUPT_INTR);
microblaze_enable_interrupts();
while (1) {
}
}

writing basic keyboard interrupt handler, throws "Unknown key released"

I have written a rudimentary keyboard interrupt handler. It uses shared interrupts and is used to print to /var/log/messages which key got pressed. But i get the following error when i try to use arrow keys and rest of the keys work fine.
Aug 19 18:59:06 vim kernel: [ 112.485102] atkbd serio0: Unknown key released (translated set 2, code 0xe0 on isa0060/serio0).
Aug 19 18:59:06 vim kernel: [ 112.485108] atkbd serio0: Use 'setkeycodes e060 ' to make it known.
Pasting the code.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <asm/io.h>
/* This function services keyboard interrupts */
irq_handler_t irq_handler (int irq, void *dev_id, struct pt_regs *regs) {
static unsigned char scancode;
/*
Read keyboard status
*/
scancode = inb (0x60);
if ((scancode == 0x01) || (scancode == 0x81))
{
printk ("You pressed Esc !\n");
}
}
return (irq_handler_t) IRQ_HANDLED;
}
/* Initialize the module and Register the IRQ handler */
static int __init keybrd_int_register(void)
{
int result;
/* Request IRQ 1, the keyboard IRQ */
result = request_irq (1, (irq_handler_t) irq_handler, IRQF_SHARED, "keyboard_stats_irq", (void *)(irq_handler));
if (result)
printk(KERN_INFO "can't get shared interrupt for keyboard\n");
return result;
}
/* Remove the interrupt handler */
static void __exit keybrd_int_unregister(void) {
free_irq(1, (void *)(irq_handler)); /* i can't pass NULL, this is a shared interrupt handler! */
}
MODULE_LICENSE ("GPL");
module_init(keybrd_int_register);
module_exit(keybrd_int_unregister);
Can anyone please give me some clue on why this arrow keys stop working when i insert my module and start working whey i remove them?
I am running my code on a Virtual Machine.
The reason was due to some VM screw up. It works fine on base linux hosts. You can see the full implementation of code (naive) # https://github.com/vigith/Linux-Device-Drivers/tree/master/keyboard

Resources