宏定义编写技巧__调试技巧【原创】
带颜色打印:
printk("\033[1;33;40m misc.c InterIoctl() action=%d\033[0m\r\n", action);
方法一、
1 #ifndef _PMU_DUMMY_ 2 3 #define _PMU_DUMMY_ 4 5 6 7 #define PAX_PMU_DUMMY_DEBUG_ENABLE 8 9 10 11 #ifdef PAX_PMU_DUMMY_DEBUG_ENABLE 12 13 #define PAX_PMU_DUMMY_DEBUG(x...) do{printk("\r\n");printk(x);printk("\r\n");}while(0) 14 15 #else 16 17 #define PAX_PMU_DUMMY_DEBUG(x...) 18 19 #endif 20 21 22 23 #define REGULATOR_DUMMY "dummy_regulator" 24 25 26 27 #endif
方法二、
1 #define DEBUG_ENABLE 1 2 3 4 5 #if DEBUG_ENABLE 6 7 #define PRINT(fmt, args...) do{\ 8 9 printf("<%s>【*%s()*】(%d):", __FILE__, __func__, __LINE__);\ 10 11 printf(fmt, ##args);\ 12 13 }while(0) 14 15 #else 16 17 #define PRINT(fmt, args...) 18 19 #endif
方法三、
1 // 带格式的打印调试 2 int Serial_Printf(char *fmt, ...) 3 { 4 va_list args; 5 int printed = 0; 6 7 uint8 printf_buf[MAX_PRINTF_LEN]; 8 9 va_start(args, fmt); 10 printed = vsprintf((char*)printf_buf, fmt, args); 11 va_end(args); 12 13 printf_buf[MAX_PRINTF_LEN-1] = '\0'; 14 SerialPrintString(printf_buf); 15 16 return printed; 17 }
1 /* 2 打印一个字符串 3 str不可以包含0x00,除非结尾 4 */ 5 void SerialPrintString(uint8 str[]) 6 { 7 HalUARTWrite (SBP_UART_PORT, str, osal_strlen((char*)str)); 8 }
1 //#define DEBUG 2 3 #ifdef DEBUG 4 #define DEBUG_PRINT(format, ...) Serial_Printf(format, ##__VA_ARGS__) 5 #define DEBUG_PRINT_BUFF(title, buff, len, display_char) \ 6 Serial_PrintBuffer(title, buff, len, display_char) 7 #else 8 #define DEBUG_PRINT(format, ...) 9 #define DEBUG_PRINT_BUFF(title, buff, len, display_char) 10 #endif
方法四、
//console.c #include <stdio.h> #include <string.h> #include <stdbool.h> #include <pthread.h> #include <stdarg.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include "Console.h" /*----------------------------------------------------------*/ /*! \brief Structure which will be copied into shared memory, in order to synchronize console output from * different processes and threads. */ /*----------------------------------------------------------*/ typedef struct { ///If set to true, there is an segmented print ongoing (Start, Continue, Exit). bool criticalSection; ///Handle of the shared mutex. pthread_mutex_t mutex; } shared_data; /*----------------------------------------------------------*/ /*! \brief Pointer to the shared memory instance. */ /*----------------------------------------------------------*/ static shared_data* data = NULL; void show_read(unsigned char *str, unsigned char *buff, unsigned int len) { ConsolePrintfStart("serial-RX: %s [", str); for (int i = 0; i < len; i++) { ConsolePrintfContinue("%02X ", buff[i]); } ConsolePrintfExit("]\r\n"); } void ConsoleInit(void) { pthread_mutexattr_t attr; int prot = PROT_READ | PROT_WRITE; int flags = MAP_SHARED | MAP_ANONYMOUS; data = (shared_data*)mmap(NULL, sizeof(shared_data), prot, flags, -1, 0); data->criticalSection = false; pthread_mutexattr_init(&attr); pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&data->mutex, &attr); } void ConsoleDeinit(void) { munmap(data, sizeof(data)); data = NULL; } void ConsolePrintf(const char *statement, ...) { int err; if (NULL == data) { printf("ConsolePrintf data was null\n"); while (true); } if (0 != (err = pthread_mutex_lock(&data->mutex))) { printf("ConsolePrintf, pthread_mutex_lock error: %d\n", err); } if (NULL != statement) { va_list args; va_start(args, statement); vprintf(statement, args); va_end(args); } if (0 != (err = pthread_mutex_unlock(&data->mutex))) { printf("ConsolePrintf, pthread_mutex_unlock error: %d\n", err); while (true); } } void ConsolePrintfStart(const char *statement, ...) { int err; if (NULL == data) { printf("ConsolePrintfStart data was null\n"); while (true); } if (0 != (err = pthread_mutex_lock(&data->mutex))) { printf("ConsolePrintfStart, pthread_mutex_lock error: %d\n", err); } data->criticalSection = true; if (NULL != statement) { va_list args; va_start(args, statement); vprintf(statement, args); va_end(args); } } void ConsolePrintfContinue(const char *statement, ...) { if (NULL == data) { printf("ConsolePrintfContinue data was null\n"); while (true); } if (!data->criticalSection) { printf("ConsolePrintfContinue not in critical section\n"); while (true); } if (NULL != statement) { va_list args; va_start(args, statement); vprintf(statement, args); va_end(args); } } void ConsolePrintfExit(const char *statement, ...) { int err; if (NULL == data) { printf("ConsolePrintfExit data was null\n"); while (true); } if (!data->criticalSection) { printf("ConsolePrintfExit not in critical section\n"); while (true); } if (NULL != statement) { va_list args; va_start(args, statement); vprintf(statement, args); va_end(args); } data->criticalSection = false; if (0 != (err = pthread_mutex_unlock(&data->mutex))) { printf("ConsolePrintfExit, pthread_mutex_unlock error: %d\n", err); while (true); } }
//console.h /*----------------------------------------------------------*/ /*! \file * \brief This file contains C-functions starting with "Console" to provide * process and thread safe access to the console output. */ /*----------------------------------------------------------*/ #ifndef _CONSOLE_H_ #define _CONSOLE_H_ #define RESETCOLOR "\033[0m" #define GREEN "\033[0;32m" #define RED "\033[0;31m" #define YELLOW "\033[1;33m" #define BLUE "\033[0;34m" #ifdef __cplusplus extern "C" { #endif void show_read(unsigned char *str, unsigned char *buff, unsigned int len); /*----------------------------------------------------------*/ /*! \brief Initializes the resources needed to synchronize between processes and threads. * \note This function must be called before any other function of this component. * */ /*----------------------------------------------------------*/ void ConsoleInit(void); /*----------------------------------------------------------*/ /*! \brief Destroys the resources needed to synchronize between processes and threads. * \note After this function, any other function (except ConsoleInit) must not be called. * */ /*----------------------------------------------------------*/ void ConsoleDeinit(void); /*----------------------------------------------------------*/ /*! \brief Uses the board specific PRINT mechanism and provides thread and process safety. * */ /*----------------------------------------------------------*/ void ConsolePrintf(const char *statement, ...); /*----------------------------------------------------------*/ /*! \brief Starts to print and stay blocked after exit of this function * */ /*----------------------------------------------------------*/ void ConsolePrintfStart(const char *statement, ...); /*----------------------------------------------------------*/ /*! \brief Continue to print and stay blocked after exit of this function * \note ConsolePrintfStart must be called before and when finished ConsolePrintfExit must be called. * \note This function may be called multiple times. */ /*----------------------------------------------------------*/ void ConsolePrintfContinue(const char *statement, ...); /*----------------------------------------------------------*/ /*! \brief Continue to print and unblock after finishing. * \note ConsolePrintfStart must be called before. ConsolePrintfContinue may have been called before multiple times. */ /*----------------------------------------------------------*/ void ConsolePrintfExit(const char *statement, ...); #ifdef __cplusplus } #endif #endif //_CONSOLE_H_
#ifndef _BASE_H_ #define _BASE_H_ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <errno.h> #include <string.h> #include <signal.h> #include <unistd.h> #include <fcntl.h> #include <setjmp.h> #include <sys/mman.h> #include "uart.h" #include "Console.h" //#define DEBUG #ifdef DEBUG #define DEBUG_PRINT(format, ...) ConsolePrintf(format, ##__VA_ARGS__); #define SHOW_READ(format, ...) show_read(format, ##__VA_ARGS__); #else #define DEBUG_PRINT(format, ...) #define SHOW_READ(format, ...) #endif #define FALSE 0 #define TRUE 1 typedef unsigned char BYTE; // 8-bit typedef unsigned short WORD; // 16-bit typedef unsigned long DWORD; // 32-bit typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned long long uint64; /* takes a byte out of a uint32 : var - uint32, ByteNum - byte to take out (0 - 3) */ #define BREAK_UINT32( var, ByteNum ) \ (uint8)((uint32)(((var) >>((ByteNum) * 8)) & 0x00FF)) #define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \ ((uint32)((uint32)((Byte0) & 0x00FF) \ + ((uint32)((Byte1) & 0x00FF) << 8) \ + ((uint32)((Byte2) & 0x00FF) << 16) \ + ((uint32)((Byte3) & 0x00FF) << 24))) #define BUILD_UINT16(loByte, hiByte) \ ((uint16)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8))) #define HI_UINT16(a) (((a) >> 8) & 0xFF) #define LO_UINT16(a) ((a) & 0xFF) #define BUILD_UINT8(hiByte, loByte) \ ((uint8)(((loByte) & 0x0F) + (((hiByte) & 0x0F) << 4))) #define HI_UINT8(a) (((a) >> 4) & 0x0F) #define LO_UINT8(a) ((a) & 0x0F) #endif
printk 调试方法
方法1:
//#define MY_DEBUG
#ifdef MY_DEBUG
#define MY_DBG(x...) do{printk(x);}while(0)
#else
#define MY_DBG(x...)
#endif
方法2:
驱动可以如下写:
#define MY_LEVEL1 (1 << 0)
#define MY_LEVEL2 (1 << 1)
unsigned int my_trace_param=0;
module_param_named(trace, my_trace_param, uint, S_IRUGO|S_IWUSR);
#define MY_DBG(flag, msg...) \
do { \
if (my_trace_param & flag) \
printk(KERN_ERR "zbh-debug: " msg); \
} while (0)
MY_DBG(MY_LEVEL1, "Goodbye module exit1.\r\n");
MY_DBG(MY_LEVEL2, "Goodbye module exit2.\r\n");
MY_DBG(MY_LEVEL2, "Goodbye module exit3.\r\n");
测试:
insmod my_printk_driver.ko
echo 2 > /sys/module/my_printk_driver/parameters/trace
这样就可以选择到底打印哪一条语句,用来动态调试开关,默认关打印
code:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include<linux/slab.h> //kmalloc
#include<asm/io.h> //ioremap
#include<linux/device.h> //class_create/device_create
#include <asm/uaccess.h>
#include <linux/pwm.h>
#include <linux/cdev.h>
#include <pax/gpio_cfg.h>
#include <pax/bcm5830x_gpio_def.h>
#include <mach/iproc_regs.h>
#include <mach/memory.h>
#include <mach/iomux.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#define PWM_IOC_MAGIC 'n'
#define PWM_CONFIG _IOW(PWM_IOC_MAGIC, 1, int)
#define PWM_DISABLE _IOW(PWM_IOC_MAGIC, 2, int)
#define ONE_PWM_CONFIG _IOW(PWM_IOC_MAGIC, 3, int)
#define ONE_PWM_DISABLE _IOW(PWM_IOC_MAGIC, 4, int)
#define ONE_PWM_WHILE_10000 _IOW(PWM_IOC_MAGIC, 5, int)
#define SET_PWM_GPIO _IOW(PWM_IOC_MAGIC, 6, int)
#define SET_PWM_POLATIRY _IOW(PWM_IOC_MAGIC, 7, int)
#define READ_ONEPLUSE_COUNTER _IOW(PWM_IOC_MAGIC, 8, int)
#define SET_PWM_FUNC _IOW(PWM_IOC_MAGIC, 9, int)
#define SET_PWM_WHILE _IOW(PWM_IOC_MAGIC, 10, int)
#define ONE_PWM_DOORBELL _IOW(PWM_IOC_MAGIC, 11, int)
#define MY_LEVEL1 (1 << 0)
#define MY_LEVEL2 (1 << 1)
unsigned int my_trace_param = 0;
module_param_named(trace, my_trace_param, uint, S_IRUGO|S_IWUSR);
#define MY_DBG(flag, msg...) \
do { \
if (my_trace_param & flag) \
printk(KERN_ERR "zbh-bbl: " msg); \
} while (0)
static int ttime = 0;
static int pmode = 0; // pmode=0 ----> asiu_pwmc , pmode=1 ----> onepluse
module_param(ttime, int, 0);
module_param(pmode, int, 0);
//module_param(period, int, 0);
#define HELLO_MAJOR 230
int hello_major = HELLO_MAJOR;
module_param(hello_major, int, 0);
static struct cdev *hello_cdev = NULL;
static struct class *dev_class = NULL;
static struct device *dev_device = NULL;
static int hello_open(struct inode *inode, struct file *filp);
static int hello_release(struct inode *inode, struct file *filp);
static int hello_open(struct inode *inode, struct file *filp)
{
printk("hello_open is OK\r\n");
return 0;
}
static int hello_release(struct inode *inode, struct file *filp)
{
printk("hello_release is OK\r\n");
printk("pwm disable and free\r\n");
return 0;
}
struct file_operations hello_ops = {
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
//.unlocked_ioctl = hello_ioctl,
};
static int __init hello_init(void)
{
dev_t devno;
int ret;
devno = MKDEV(hello_major, 0);
ret = register_chrdev_region(devno, 1, "zbh_hello");
if (!ret) {
printk("register dev OK.\r\n");
}
else {
printk("register dev failed.\r\n");
}
hello_cdev = cdev_alloc();
cdev_init(hello_cdev, &hello_ops);
cdev_add(hello_cdev, devno, 1);
hello_cdev->owner = THIS_MODULE;
hello_cdev->ops = &hello_ops;
dev_class = class_create(THIS_MODULE, "dev_class");
if (IS_ERR(dev_class)) {
printk(KERN_ERR "class_create() failed for dev_class\n");
ret = -EINVAL;
goto out_err_1;
}
dev_device = device_create(dev_class, NULL, devno, NULL, "zbh_hello");
if (IS_ERR(dev_device)) {
printk(KERN_ERR "device_create failed.\r\n");
ret = -ENODEV;
goto out_err_2;
}
printk("Hello module init OK.\r\n");
return 0;
out_err_2:
class_destroy(dev_class);
out_err_1:
unregister_chrdev_region(MKDEV(hello_major, 0), 1);
cdev_del(hello_cdev);
return ret;
}
static void __exit hello_exit(void)
{
cdev_del(hello_cdev);
device_destroy(dev_class, MKDEV(hello_major, 0));
class_destroy(dev_class);
unregister_chrdev_region(MKDEV(hello_major, 0), 1);
MY_DBG(MY_LEVEL1, "Goodbye module exit1.\r\n");
MY_DBG(MY_LEVEL2, "Goodbye module exit2.\r\n");
MY_DBG(MY_LEVEL2, "Goodbye module exit3.\r\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("zhangbinghua");
MODULE_DESCRIPTION("zhangbh debug driver");
#ifdef MISC_RF_NEEDED
#define RF_MISC_CTRL(name, dev_id) \
static ACTION_DATA name ={ \
.dev_Id=dev_id, \
.boot_on=BOOT_POWEROFF, \
.flag=FLAG_ACTION_BASE|FLAG_ACTION_SLEEP, \
}
#define __RF_MISC(name) RF_MISC_CTRL(name, #name)
#define RF_MISC(name) __RF_MISC(rf_##name)
RF_MISC(red);
RF_MISC(green);
RF_MISC(blue);
#endif