I can send data from STM32WL55JC1 to Spirit1. However, I can't receive data from Spirit1 to STM32WL55JC1 and get interrupt from LoRa. Interrupt is always zero. The communication modulation is GFSK.
Also, I need some resources about STM32WL55JC1 and Spirit1.
Thank you.
Here are LoRa modulations parameters:
#define RF_FREQUENCY 868000000 /* Hz */
#define TX_OUTPUT_POWER 14 /* dBm */
#define FSK_FDEV 20000 /* Hz */
#define FSK_DATARATE 38400 /* bps */
#define FSK_BANDWIDTH 100000 /* Hz */
#define FSK_PREAMBLE_LENGTH 5 /* Same for Tx and Rx */
#define FSK_SYNCWORD_LENGTH 4
#define PAYLOAD_LEN 25
#define MAX_DATA_LEN 32
SUBGRF_SetBufferBaseAddress( 0x00,0x80 );
SUBGRF_SetRfFrequency(RF_FREQUENCY); //NOT THESE
SUBGRF_SetRfTxPower(TX_OUTPUT_POWER);
SUBGRF_SetStopRxTimerOnPreambleDetect(false);
ModulationParams_t modParams;
modParams.PacketType = PACKET_TYPE_GFSK;
modParams.Params.Gfsk.Bandwidth = SUBGRF_GetFskBandwidthRegValue(FSK_BANDWIDTH);
modParams.Params.Gfsk.BitRate = FSK_DATARATE;
modParams.Params.Gfsk.Fdev = FSK_FDEV;
modParams.Params.Gfsk.ModulationShaping = MOD_SHAPING_G_BT_1;
SUBGRF_SetModulationParams(&modParams);
packetParams.PacketType = PACKET_TYPE_GFSK;
packetParams.Params.Gfsk.AddrComp = RADIO_ADDRESSCOMP_FILT_OFF;
packetParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
packetParams.Params.Gfsk.DcFree = RADIO_DC_FREE_OFF;
packetParams.Params.Gfsk.HeaderType = RADIO_PACKET_VARIABLE_LENGTH;
packetParams.Params.Gfsk.PayloadLength = PAYLOAD_LEN;
packetParams.Params.Gfsk.PreambleLength = (FSK_PREAMBLE_LENGTH << 3); //bytes to bits!!
packetParams.Params.Gfsk.PreambleMinDetect = RADIO_PREAMBLE_DETECTOR_OFF; //RADIO_PREAMBLE_DETECTOR_08_BITS;
packetParams.Params.Gfsk.SyncWordLength = (FSK_SYNCWORD_LENGTH << 3);
SUBGRF_SetPacketParams(&packetParams);
SUBGRF_SetSyncWord((uint8_t[]){0x88, 0x88, 0x88, 0x88});
//SUBGRF_SetWhiteningSeed(0x01FF);
SUBGRF_SetTxParams(RFO_LP, 14, RADIO_RAMP_40_US); //default comment
I am trying to develop a Local Sensor Network example that is in the Stm32wljc1 Library. Receive Function was added by me:
SUBGRF_SetDioIrqParams(IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, IRQ_RADIO_NONE, IRQ_RADIO_NONE);
SUBGRF_SetSwitch(NULL, RFSWITCH_RX);
packetParams.Params.Gfsk.PayloadLength = 32;
SUBGRF_SetPacketParams(&packetParams);
RadioStandby();
SUBGRF_SetRx(0);
uint8_t *rLen;
SUBGRF_GetPayload(rxData,rLen,255);
SUBGRF_GetRxBufferStatus(rLen,rxData);
uint8_t rssiValue = SUBGRF_GetRssiInst();
uint8_t packetType = SUBGRF_GetPacketType();
SUBGRF_ClearIrqStatus(IRQ_RADIO_ALL);
HAL_Delay(100);
RadioSleep();
Related
I have some troubles with reading data from ccs811 air sensors registers for example I want to recreate an example from css811_Programming_Guide which is reading from the hardware ID register presented below:
example from css811_Programming_Guide
To do so I am using esp-idf driver/i2c:
#include "task_air_sensor.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/i2c.h"
static const char *TAG = "i2c-simple-example";
// defines for master
#define I2C_MASTER_SCL_IO 2 /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO 1 /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 4000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */
// defines for ccs_811
#define STATUS_REG 0x00
#define MEAS_MODE_REG 0x01
#define ALG_RESULT_DATA 0x02
#define ENV_DATA 0x05
#define NTC_REG 0x06
#define THRESHOLDS 0x10
#define BASELINE 0x11
#define HW_ID_REG 0x20
#define ERROR_ID_REG 0xE0
#define APP_START_REG 0xF4
#define SW_RESET 0xFF
#define CCS_811_ADDRESS 0x5B
#define CCS_811_WHO_AM_I 0x81
#define GPIO_WAKE 0x5
#define DRIVE_MODE_IDLE 0x0 /*!< Drive mode */
#define DRIVE_MODE_1SEC 0x10 /*!< Drive mode */
#define DRIVE_MODE_10SEC 0x20 /*!< Drive mode */
#define DRIVE_MODE_60SEC 0x30 /*!< Drive mode */
#define INTERRUPT_DRIVEN 0x8
#define THRESHOLDS_ENABLED 0x4
#define ERROR_NOT_A_CCS811 -1
typedef struct
{
uint16_t eco2;
uint16_t tvoc;
uint8_t status;
uint8_t error_id;
uint16_t raw_data;
} ccs811_measurement_t;
ccs811_measurement_t current_data;
static esp_err_t i2c_master_init(void);
static esp_err_t i2c_sensor_init(void);
static esp_err_t i2c_get_sensor_data(void);
uint8_t i2c_buff[8];
bool wake_gpio_enabled = true;
void task_air_sensor(void *pvParameter)
{
printf("Start of Task Air Sensor\n");
ESP_ERROR_CHECK(i2c_master_init());
ESP_LOGI(TAG, "I2C Master initialized successfully");
// ESP_ERROR_CHECK(i2c_sensor_init());
// ESP_LOGI(TAG, "I2C Sensor initialized successfully");
while(1)
{
printf("App in Task Air Sensor\n");
i2c_sensor_init();
i2c_get_sensor_data();
printf("status register = %d\n", current_data.status);
vTaskDelay(30 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
/**
* #brief i2c master initialization
*/
static esp_err_t i2c_master_init(void)
{
i2c_port_t i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
/**
* #brief test code to operate on CCS811 air quality sensor
*
* 1. set drive mode in Measure Mode Register
* _________________________________________________________________
* | start | slave_addr + wr_bit + ack | write 1 byte + ack | stop |
* --------|---------------------------|---------------------|------|
* 2. wait more than 24 ms
* 3. read data
* ______________________________________________________________________________________
* | start | slave_addr + rd_bit + ack | read 1 byte + ack | read 1 byte + nack | stop |
* --------|---------------------------|--------------------|--------------------|------|
*/
static esp_err_t i2c_sensor_init(void)
{
i2c_port_t i2c_num = I2C_MASTER_NUM;
esp_err_t ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, MEAS_MODE_REG, ACK_CHECK_EN);
i2c_master_write_byte(cmd, DRIVE_MODE_1SEC, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK)
{
ESP_LOGI(TAG,"Error during setting drive mode.\n");
return ret;
}
vTaskDelay(30 / portTICK_PERIOD_MS);
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, HW_ID_REG, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK)
{
ESP_LOGI(TAG,"Error during writing to HAW_ID_REG.\n");
return ret;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(cmd, &i2c_buff[0], NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if(i2c_buff[0] != CCS_811_WHO_AM_I)
{
printf("i2c_buff[0] = %d \n", i2c_buff[0]);
ESP_LOGI(TAG,"Error during reading from HW_ID_REG.\n");
return ERROR_NOT_A_CCS811;
}
return ret;
}
static esp_err_t i2c_get_sensor_data(void)
{
i2c_port_t i2c_num = I2C_MASTER_NUM;
esp_err_t ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, STATUS_REG, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK)
{
ESP_LOGI(TAG,"Error during writing to STATUS_REG.\n");
return ret;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | READ_BIT, ACK_VAL);
i2c_master_read_byte(cmd, ¤t_data.status, NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK)
{
ESP_LOGI(TAG,"Error during reading from STATUS_REG.\n");
return ret;
}
return ret;
}
After uploading the code and monitoring outputs I get some incorrect data:
App in Task Air Sensor
i2c_buff[0] = 3
i2c-simple-example: Error during reading from HW_ID_REG.
status register = 3
However when I'm monitoring i2c bus with logic analyzer I get the correct data that I was expecting.
reading i2c bus by logic analyzer
(address is different than the one in Programming Guide intentionally)
Is anyone know why below condition in function static esp_err_t i2c_sensor_init(void) is fullfiled?
if(i2c_buff[0] != CCS_811_WHO_AM_I)
{
printf("i2c_buff[0] = %d \n", i2c_buff[0]);
ESP_LOGI(TAG,"Error during reading from HW_ID_REG.\n");
return ERROR_NOT_A_CCS811;
}
According to data from analyzer it should be equal to 0x81 (CCS_811_WHO_AM_I) rather than 3 :/
Hi can you try something like this?
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (I2C_SCD41 << 1) | I2C_MASTER_WRITE, 1);
i2c_master_write(cmd, &data[0],2,1);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (I2C_SCD41 << 1) | I2C_MASTER_READ, 1);
i2c_master_read(cmd,&data[0],8,I2C_MASTER_ACK);
i2c_master_read_byte(cmd, &data[8], I2C_MASTER_NACK);
i2c_master_stop(cmd);
status = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
if (status != 0) ESP_LOGE("I2C","%d:%s",status,esp_err_to_name(status));
i2c_cmd_link_delete(cmd);
Do you see the difference?
I'm trying to implement polling functionality into my simple Linux kernel module called gpio_driver for my Raspberry Pi which should notify the user space poll function about the change of state of one of the GPIO pins (button push).
What I did in my gpio_driver is set the internal pull down on my GPIO_04 pin and direction to input, so when I press the button connected to the pin on one side and +5V on the other, it should generate a pulse which should notify the user space poll function that the button push happened and end the user space program.
The user space program code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <poll.h>
int main(int argc, char *argv[])
{
char str[256];
struct pollfd pfd;
int fd, gpio;
char buf[8];
sprintf(str, "/dev/gpio_driver");
if ((fd = open(str, O_RDONLY)) < 0)
{
fprintf(stderr, "Failed, gpio %d not exported.\n", gpio);
exit(1);
}
pfd.fd = fd;
pfd.events = POLLPRI;
lseek(fd, 0, SEEK_SET); /* consume any prior interrupt */
read(fd, buf, sizeof buf);
poll(&pfd, 1, -1); /* wait for interrupt */
lseek(fd, 0, SEEK_SET); /* consume interrupt */
read(fd, buf, sizeof buf);
exit(0);
}
Complete driver code (poll function implementation at the end of file):
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/ktime.h>
#include <linux/hrtimer.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
MODULE_LICENSE("Dual BSD/GPL");
/* if defined, timer callback will implement LED0 flashing and
SW0 reading after each interval */
#define TEST
// timer interval defined as (TIMER_SEC + TIMER_NANO_SEC)
#define TIMER_SEC 0
#define TIMER_NANO_SEC 250*1000*1000 /* 250ms */
// NOTE: Check Broadcom BCM8325 datasheet, page 91+
// NOTE: GPIO Base address is set to 0x7E200000,
// but it is VC CPU BUS address, while the
// ARM physical address is 0x3F200000, what
// can be seen in pages 5-7 of Broadcom
// BCM8325 datasheet, having in mind that
// total system ram is 0x3F000000 (1GB - 16MB)
// instead of 0x20000000 (512 MB)
/* GPIO registers base address. */
#define BCM2708_PERI_BASE (0x3F000000)
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000)
#define GPIO_ADDR_SPACE_LEN (0xB4)
//--
//Handle GPIO: 0-9
/* GPIO Function Select 0. */
#define GPFSEL0_OFFSET (0x00000000)
//Handle GPIO: 10-19
/* GPIO Function Select 1. */
#define GPFSEL1_OFFSET (0x00000004)
//Handle GPIO: 20-29
/* GPIO Function Select 2. */
#define GPFSEL2_OFFSET (0x00000008)
//Handle GPIO: 30-39
/* GPIO Function Select 3. */
#define GPFSEL3_OFFSET (0x0000000C)
//Handle GPIO: 40-49
/* GPIO Function Select 4. */
#define GPFSEL4_OFFSET (0x00000010)
//Handle GPIO: 50-53
/* GPIO Function Select 5. */
#define GPFSEL5_OFFSET (0x00000014)
//--
//GPIO: 0-31
/* GPIO Pin Output Set 0. */
#define GPSET0_OFFSET (0x0000001C)
//GPIO: 32-53
/* GPIO Pin Output Set 1. */
#define GPSET1_OFFSET (0x00000020)
//--
//GPIO: 0-31
/* GPIO Pin Output Clear 0. */
#define GPCLR0_OFFSET (0x00000028)
//GPIO: 32-53
/* GPIO Pin Output Clear 1. */
#define GPCLR1_OFFSET (0x0000002C)
//--
//GPIO: 0-31
/* GPIO Pin Level 0. */
#define GPLEV0_OFFSET (0x00000034)
//GPIO: 32-53
/* GPIO Pin Level 1. */
#define GPLEV1_OFFSET (0x00000038)
//--
//GPIO: 0-53
/* GPIO Pin Pull-up/down Enable. */
#define GPPUD_OFFSET (0x00000094)
//GPIO: 0-31
/* GPIO Pull-up/down Clock Register 0. */
#define GPPUDCLK0_OFFSET (0x00000098)
//GPIO: 32-53
/* GPIO Pull-up/down Clock Register 1. */
#define GPPUDCLK1_OFFSET (0x0000009C)
//--
/* PUD - GPIO Pin Pull-up/down */
typedef enum {PULL_NONE = 0, PULL_DOWN = 1, PULL_UP = 2} PUD;
//--
//000 = GPIO Pin 'x' is an input
//001 = GPIO Pin 'x' is an output
// By default GPIO pin is being used as an input
typedef enum {GPIO_DIRECTION_IN = 0, GPIO_DIRECTION_OUT = 1} DIRECTION;
//--
/* GPIO pins available on connector p1. */
#define GPIO_02 (2)
#define GPIO_03 (3)
#define GPIO_04 (4)
#define GPIO_05 (5)
#define GPIO_06 (6)
#define GPIO_07 (7)
#define GPIO_08 (8)
#define GPIO_09 (9)
#define GPIO_10 (10)
#define GPIO_11 (11)
#define GPIO_12 (12)
#define GPIO_13 (13)
#define GPIO_14 (14)
#define GPIO_15 (15)
#define GPIO_16 (16)
#define GPIO_17 (17)
#define GPIO_18 (18)
#define GPIO_19 (19)
#define GPIO_20 (20)
#define GPIO_21 (21)
#define GPIO_22 (22)
#define GPIO_23 (23)
#define GPIO_24 (24)
#define GPIO_25 (25)
#define GPIO_26 (26)
#define GPIO_27 (27)
/* Declaration of gpio_driver.c functions */
int gpio_driver_init(void);
void gpio_driver_exit(void);
static int gpio_driver_open(struct inode *, struct file *);
static int gpio_driver_release(struct inode *, struct file *);
static ssize_t gpio_driver_read(struct file *, char *buf, size_t , loff_t *);
static ssize_t gpio_driver_write(struct file *, const char *buf, size_t , loff_t *);
static unsigned int gpio_driver_poll(struct file *, poll_table *);
/* Structure that declares the usual file access functions. */
struct file_operations gpio_driver_fops =
{
open : gpio_driver_open,
release : gpio_driver_release,
read : gpio_driver_read,
write : gpio_driver_write,
poll : gpio_driver_poll
};
static DECLARE_WAIT_QUEUE_HEAD(gpio_driver_wait);
/* Declaration of the init and exit functions. */
module_init(gpio_driver_init);
module_exit(gpio_driver_exit);
/* Major number. */
int gpio_driver_major;
/* Buffer to store data. */
#define BUF_LEN 80
char* gpio_driver_buffer;
/* Virtual address where the physical GPIO address is mapped */
void* virt_gpio_base;
/*
* GetGPFSELReg function
* Parameters:
* pin - number of GPIO pin;
*
* return - GPFSELn offset from GPIO base address, for containing desired pin control
* Operation:
* Based on the passed GPIO pin number, finds the corresponding GPFSELn reg and
* returns its offset from GPIO base address.
*/
unsigned int GetGPFSELReg(char pin)
{
unsigned int addr;
if(pin >= 0 && pin <10)
addr = GPFSEL0_OFFSET;
else if(pin >= 10 && pin <20)
addr = GPFSEL1_OFFSET;
else if(pin >= 20 && pin <30)
addr = GPFSEL2_OFFSET;
else if(pin >= 30 && pin <40)
addr = GPFSEL3_OFFSET;
else if(pin >= 40 && pin <50)
addr = GPFSEL4_OFFSET;
else /*if(pin >= 50 && pin <53) */
addr = GPFSEL5_OFFSET;
return addr;
}
/*
* GetGPIOPinOffset function
* Parameters:
* pin - number of GPIO pin;
*
* return - offset of the pin control bit, position in control registers
* Operation:
* Based on the passed GPIO pin number, finds the position of its control bit
* in corresponding control registers.
*/
char GetGPIOPinOffset(char pin)
{
if(pin >= 0 && pin <10)
pin = pin;
else if(pin >= 10 && pin <20)
pin -= 10;
else if(pin >= 20 && pin <30)
pin -= 20;
else if(pin >= 30 && pin <40)
pin -= 30;
else if(pin >= 40 && pin <50)
pin -= 40;
else /*if(pin >= 50 && pin <53) */
pin -= 50;
return pin;
}
/*
* SetInternalPullUpDown function
* Parameters:
* pin - number of GPIO pin;
* pull - set internal pull up/down/none if PULL_UP/PULL_DOWN/PULL_NONE selected
* Operation:
* Sets to use internal pull-up or pull-down resistor, or not to use it if pull-none
* selected for desired GPIO pin.
*/
void SetInternalPullUpDown(char pin, PUD pull)
{
unsigned int gppud_offset;
unsigned int gppudclk_offset;
unsigned int tmp;
unsigned int mask;
/* Get the offset of GPIO Pull-up/down Register (GPPUD) from GPIO base address. */
gppud_offset = GPPUD_OFFSET;
/* Get the offset of GPIO Pull-up/down Clock Register (GPPUDCLK) from GPIO base address. */
gppudclk_offset = (pin < 32) ? GPPUDCLK0_OFFSET : GPPUDCLK1_OFFSET;
/* Get pin offset in register . */
pin = (pin < 32) ? pin : pin - 32;
/* Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither
to remove the current Pull-up/down). */
iowrite32(pull, virt_gpio_base + gppud_offset);
/* Wait 150 cycles – this provides the required set-up time for the control signal */
/* Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to
modify – NOTE only the pads which receive a clock will be modified, all others will
retain their previous state. */
tmp = ioread32(virt_gpio_base + gppudclk_offset);
mask = 0x1 << pin;
tmp |= mask;
iowrite32(tmp, virt_gpio_base + gppudclk_offset);
/* Wait 150 cycles – this provides the required hold time for the control signal */
/* Write to GPPUD to remove the control signal. */
iowrite32(PULL_NONE, virt_gpio_base + gppud_offset);
/* Write to GPPUDCLK0/1 to remove the clock. */
tmp = ioread32(virt_gpio_base + gppudclk_offset);
mask = 0x1 << pin;
tmp &= (~mask);
iowrite32(tmp, virt_gpio_base + gppudclk_offset);
}
/*
* SetGpioPinDirection function
* Parameters:
* pin - number of GPIO pin;
* direction - GPIO_DIRECTION_IN or GPIO_DIRECTION_OUT
* Operation:
* Sets the desired GPIO pin to be used as input or output based on the direcation value.
*/
void SetGpioPinDirection(char pin, DIRECTION direction)
{
unsigned int GPFSELReg_offset;
unsigned int tmp;
unsigned int mask;
/* Get base address of function selection register. */
GPFSELReg_offset = GetGPFSELReg(pin);
/* Calculate gpio pin offset. */
pin = GetGPIOPinOffset(pin);
/* Set gpio pin direction. */
tmp = ioread32(virt_gpio_base + GPFSELReg_offset);
if(direction)
{ //set as output: set 1
mask = 0x1 << (pin*3);
tmp |= mask;
}
else
{ //set as input: set 0
mask = ~(0x1 << (pin*3));
tmp &= mask;
}
iowrite32(tmp, virt_gpio_base + GPFSELReg_offset);
}
/*
* GetGpioPinDirection function
* Parameters:
* pin - number of GPIO pin;
* Operation:
* Gets the desired GPIO pin's direction and returns 0 for IN and 1 for OUT.
*/
int GetGpioPinDirection(char pin)
{
unsigned int GPFSELReg_offset;
unsigned int tmp;
unsigned int mask;
/* Get base address of function selection register. */
GPFSELReg_offset = GetGPFSELReg(pin);
/* Calculate gpio pin offset. */
pin = GetGPIOPinOffset(pin);
/* Get gpio pin direction. */
tmp = ioread32(virt_gpio_base + GPFSELReg_offset);
mask = 0x1 << (pin*3);
tmp &= mask;
tmp=tmp>>(pin*3);
return tmp;
}
/*
* SetGpioPin function
* Parameters:
* pin - number of GPIO pin;
* Operation:
* Sets the desired GPIO pin to HIGH level. The pin should previously be defined as output.
*/
void SetGpioPin(char pin)
{
unsigned int GPSETreg_offset;
unsigned int tmp;
/* Get base address of gpio set register. */
GPSETreg_offset = (pin < 32) ? GPSET0_OFFSET : GPSET1_OFFSET;
pin = (pin < 32) ? pin : pin - 32;
/* Set gpio. */
tmp = 0x1 << pin;
iowrite32(tmp, virt_gpio_base + GPSETreg_offset);
}
/*
* ClearGpioPin function
* Parameters:
* pin - number of GPIO pin;
* Operation:
* Sets the desired GPIO pin to LOW level. The pin should previously be defined as output.
*/
void ClearGpioPin(char pin)
{
unsigned int GPCLRreg_offset;
unsigned int tmp;
/* Get base address of gpio clear register. */
GPCLRreg_offset = (pin < 32) ? GPCLR0_OFFSET : GPCLR1_OFFSET;
pin = (pin < 32) ? pin : pin - 32;
/* Clear gpio. */
tmp = 0x1 << pin;
iowrite32(tmp, virt_gpio_base + GPCLRreg_offset);
}
/*
* GetGpioPinValue function
* Parameters:
* pin - number of GPIO pin;
*
* return - the level read from desired GPIO pin
* Operation:
* Reads the level from the desired GPIO pin and returns the read value.
*/
char GetGpioPinValue(char pin)
{
unsigned int GPLEVreg_offset;
unsigned int tmp;
unsigned int mask;
/* Get base address of gpio level register. */
GPLEVreg_offset = (pin < 32) ? GPLEV0_OFFSET : GPLEV1_OFFSET;
pin = (pin < 32) ? pin : pin - 32;
/* Read gpio pin level. */
tmp = ioread32(virt_gpio_base + GPLEVreg_offset);
mask = 0x1 << pin;
tmp &= mask;
return (tmp >> pin);
}
/*
* Initialization:
* 1. Register device driver
* 2. Allocate buffer
* 3. Initialize buffer
* 4. Map GPIO Physical address space to virtual address
* 5. Initialize GPIO pin
*/
int gpio_driver_init(void)
{
int result = -1;
printk(KERN_INFO "Inserting gpio_driver module\n");
/* Registering device. */
result = register_chrdev(0, "gpio_driver", &gpio_driver_fops);
if (result < 0)
{
printk(KERN_INFO "gpio_driver: cannot obtain major number %d\n", gpio_driver_major);
return result;
}
gpio_driver_major = result;
printk(KERN_INFO "gpio_driver major number is %d\n", gpio_driver_major);
/* Allocating memory for the buffer. */
gpio_driver_buffer = kmalloc(BUF_LEN, GFP_KERNEL);
if (!gpio_driver_buffer)
{
result = -ENOMEM;
goto fail_no_mem;
}
/* Initialize data buffer. */
memset(gpio_driver_buffer, 0, BUF_LEN);
/* map the GPIO register space from PHYSICAL address space to virtual address space */
virt_gpio_base = ioremap(GPIO_BASE, GPIO_ADDR_SPACE_LEN);
if(!virt_gpio_base)
{
result = -ENOMEM;
goto fail_no_virt_mem;
}
/* Initialize GPIO pin. */
SetGpioPinDirection(GPIO_04, GPIO_DIRECTION_IN);
SetInternalPullUpDown(GPIO_04, PULL_DOWN); // rising edge
return 0;
fail_no_virt_mem:
/* Freeing buffer gpio_driver_buffer. */
if (gpio_driver_buffer)
{
kfree(gpio_driver_buffer);
}
fail_no_mem:
/* Freeing the major number. */
unregister_chrdev(gpio_driver_major, "gpio_driver");
return result;
}
/*
* Cleanup:
* 1. stop the timer
* 2. release GPIO pins (clear all outputs, set all as inputs and pull-none to minimize the power consumption)
* 3. Unmap GPIO Physical address space from virtual address
* 4. Free buffer
* 5. Unregister device driver
*/
void gpio_driver_exit(void)
{
printk(KERN_INFO "Removing gpio_driver module..\n");
/* Clear GPIO pins. */
ClearGpioPin(GPIO_04);
/* Set GPIO pins as inputs and disable pull-ups. */
SetGpioPinDirection(GPIO_04, GPIO_DIRECTION_IN);
SetInternalPullUpDown(GPIO_04, PULL_NONE);
/* Unmap GPIO Physical address space. */
if (virt_gpio_base)
{
iounmap(virt_gpio_base);
}
/* Freeing buffer gpio_driver_buffer. */
if (gpio_driver_buffer)
{
kfree(gpio_driver_buffer);
}
/* Freeing the major number. */
unregister_chrdev(gpio_driver_major, "gpio_driver");
}
/* File open function. */
static int gpio_driver_open(struct inode *inode, struct file *filp)
{
/* Success. */
return 0;
}
/* File close function. */
static int gpio_driver_release(struct inode *inode, struct file *filp)
{
/* Success. */
return 0;
}
/* File read function */
static ssize_t gpio_driver_read(struct file *filp, char *buf, size_t len, loff_t *f_pos)
{
/* Size of valid data in gpio_driver - data to send in user space. */
int data_size = 0;
/* Copy GPIO pin state to user space. */
gpio_driver_buffer[0]=GetGpioPinValue(GPIO_04);
/* TODO: fill gpio_driver_buffer here. */
if (*f_pos == 0)
{
/* Get size of valid data. */
data_size = strlen(gpio_driver_buffer);
/* Send data to user space. */
if (copy_to_user(buf, gpio_driver_buffer, data_size) != 0)
{
return -EFAULT;
}
else
{
(*f_pos) += data_size;
return data_size;
}
}
else
{
return 0;
}
}
/* File write function */
static ssize_t gpio_driver_write(struct file *filp, const char *buf, size_t len, loff_t *f_pos)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EPERM; // Operation not permitted error
}
static unsigned int gpio_driver_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(filp, &gpio_driver_wait, wait);
if(GetGpioPinValue(GPIO_04)!=0)
gpio_driver_buffer[0] = 1;
if(gpio_driver_buffer[0] == 1)
{
mask |= POLLIN | POLLPRI;
wake_up_interruptible(&gpio_driver_wait);
}
gpio_driver_buffer[0] = 0;
return mask;
}
However, when I run my user space program, it doesn't react to my button pushes and it never exits. I'm pretty new to polling all the code written in the driver related to polling and user program I picked up online from different sources and some books (mainly Linux Device Drivers, 3rd edition, chapter 6). What am I doing wrong?
I'm trying to read information from an MPU6050 sensor using the SAM4S-EK2 dev board, with an ATSAM4SD32C microcontroler, showing the data in the on-board LCD display. However, when I try to read the data, the received value that shows up in the LCD is always the same.
What am I doing wrong?
I'm using Atmel Studio 7 with ASF version 3.32.0
Here is my current code:
#include <asf.h>
#define TWI_CLK 200000
#define ADDRESS 0x68
#define READ 0x3b
#define ILI93XX_LCD_CS 1
twi_options_t opt;
struct ili93xx_opt_t g_ili93xx_display_opt;
void configure_lcd()
{
/** Enable peripheral clock */
pmc_enable_periph_clk(ID_SMC);
/** Configure SMC interface for Lcd */
smc_set_setup_timing(SMC, ILI93XX_LCD_CS, SMC_SETUP_NWE_SETUP(2)
| SMC_SETUP_NCS_WR_SETUP(2)
| SMC_SETUP_NRD_SETUP(2)
| SMC_SETUP_NCS_RD_SETUP(2));
smc_set_pulse_timing(SMC, ILI93XX_LCD_CS, SMC_PULSE_NWE_PULSE(4)
| SMC_PULSE_NCS_WR_PULSE(4)
| SMC_PULSE_NRD_PULSE(10)
| SMC_PULSE_NCS_RD_PULSE(10));
smc_set_cycle_timing(SMC, ILI93XX_LCD_CS, SMC_CYCLE_NWE_CYCLE(10)
| SMC_CYCLE_NRD_CYCLE(22));
smc_set_mode(SMC, ILI93XX_LCD_CS, SMC_MODE_READ_MODE
| SMC_MODE_WRITE_MODE);
/** Initialize display parameter */
g_ili93xx_display_opt.ul_width = ILI93XX_LCD_WIDTH;
g_ili93xx_display_opt.ul_height = ILI93XX_LCD_HEIGHT;
g_ili93xx_display_opt.foreground_color = COLOR_BLACK;
g_ili93xx_display_opt.background_color = COLOR_WHITE;
/** Switch off backlight */
aat31xx_disable_backlight();
/** Initialize LCD */
ili93xx_init(&g_ili93xx_display_opt);
/** Set backlight level */
aat31xx_set_backlight(AAT31XX_AVG_BACKLIGHT_LEVEL);
ili93xx_set_foreground_color(COLOR_WHITE);
ili93xx_draw_filled_rectangle(0, 0, ILI93XX_LCD_WIDTH,
ILI93XX_LCD_HEIGHT);
/** Turn on LCD */
ili93xx_display_on();
ili93xx_set_cursor_position(0, 0);
}
int main (void)
{
sysclk_init();
board_init();
configure_lcd();
pio_configure(PIOB, PIO_PERIPH_B, (PIO_PB5A_TWCK1 | PIO_PB4A_TWD1), PIO_OPENDRAIN);
pmc_enable_periph_clk(ID_TWI1);
opt.master_clk = sysclk_get_peripheral_hz();
opt.speed = TWI_CLK;
twi_enable_master_mode(TWI1);
twi_master_init(TWI1, &opt);
twi_packet_t packet;
uint8_t answer[20];
answer[0]=0x00;
//pacote.addr[0] = 0x6b;
//pacote.addr_length = 1;
//pacote.buffer = &resposta;
//pacote.chip = ENDERECO_SENSOR;
//pacote.length = 1;
//
//if(twi_master_write(TWI1, &pacote) == TWI_SUCCESS)
//{
//ili93xx_set_foreground_color(COLOR_WHITE);
//ili93xx_draw_filled_rectangle(0, 0, 200, 200);
//ili93xx_set_foreground_color(COLOR_BLACK);
//ili93xx_draw_string(0, 0, "Enviou");
//}
while(1)
{
packet.addr[0] = READ;
packet.addr_length = 1;
packet.buffer = &answer;
packet.chip = ADDRESS;
packet.length = 14;
twi_master_read(TWI1, &packet);
char a[20];
int16_t b;
b = (answer[2] << 8 | answer[3]);
sprintf(a,"%i",b);
ili93xx_set_foreground_color(COLOR_WHITE);
ili93xx_draw_filled_rectangle(95, 175, 240, 200);
ili93xx_set_foreground_color(COLOR_BLACK);
ili93xx_draw_string(100, 180, a);
delay_ms(100);
}
}
I am trying to implement a flexcan communication using a k66f micro controller. As an initial step I just want to send a message through the tx pin. I am basing my program on an example from NXP.
I am very new to C and specially to micro controller programming. The code I run gets stuck in the following line:
/* Wait until CAN Message send out. */
while (!FLEXCAN_GetMbStatusFlags(base, 1 << mbIdx))
{
}
I don't know how exactly the meaning of the code since as I understand, FLEXCAN_GetMbStatusFlags is not a function.
Thanks in advance.
the micro controller is nxp's k66f.
Edit: This is the example
#include "fsl_debug_console.h"
#include "fsl_flexcan.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define EXAMPLE_CAN CAN0
#define EXAMPLE_CAN_CLKSRC kCLOCK_BusClk
#define EXAMPLE_FLEXCAN_IRQn CAN0_ORed_Message_buffer_IRQn
#define EXAMPLE_FLEXCAN_IRQHandler CAN0_ORed_Message_buffer_IRQHandler
#define RX_MESSAGE_BUFFER_NUM (8)
#define TX_MESSAGE_BUFFER_NUM (9)
int status;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
volatile bool rxComplete = false;
flexcan_frame_t txFrame, rxFrame;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* #brief Main function
*/
int main(void)
{
flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
/* Initialize board hardware. */
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
PRINTF("\r\n==FlexCAN loopback functional example -- Start.==\r\n\r\n");
/* Init FlexCAN module. */
/*
* flexcanConfig.clkSrc = kFLEXCAN_ClkSrcOsc;
* flexcanConfig.baudRate = 125000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.enableDoze = false;
*/
FLEXCAN_GetDefaultConfig(&flexcanConfig);
flexcanConfig.clkSrc = kFLEXCAN_ClkSrcPeri;
//flexcanConfig.enableLoopBack = true;
FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, CLOCK_GetFreq(EXAMPLE_CAN_CLKSRC));
/* Setup Rx Message Buffer. */
mbConfig.format = kFLEXCAN_FrameFormatStandard;
mbConfig.type = kFLEXCAN_FrameTypeData;
mbConfig.id = FLEXCAN_ID_STD(0x123);
FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
/* Setup Tx Message Buffer. */
FLEXCAN_SetTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
/* Enable Rx Message Buffer interrupt. */
FLEXCAN_EnableMbInterrupts(EXAMPLE_CAN, 1 << RX_MESSAGE_BUFFER_NUM);
EnableIRQ(EXAMPLE_FLEXCAN_IRQn);
/* Prepare Tx Frame for sending. */
txFrame.format = kFLEXCAN_FrameFormatStandard;
txFrame.type = kFLEXCAN_FrameTypeData;
txFrame.id = FLEXCAN_ID_STD(0x123);
txFrame.length = 8;
txFrame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x11) | CAN_WORD0_DATA_BYTE_1(0x22) | CAN_WORD0_DATA_BYTE_2(0x33) |
CAN_WORD0_DATA_BYTE_3(0x44);
txFrame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x55) | CAN_WORD1_DATA_BYTE_5(0x66) | CAN_WORD1_DATA_BYTE_6(0x77) |
CAN_WORD1_DATA_BYTE_7(0x88);
/* Send data through Tx Message Buffer using polling function. */
status=FlEXCAN_TransferSendBlocking(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, &txFrame);
PRINTF("status= %d \r\n", status);
PRINTF("Send message from MB%d to MB%d\r\n", TX_MESSAGE_BUFFER_NUM, RX_MESSAGE_BUFFER_NUM);
PRINTF("tx word0 = 0x%x\r\n", txFrame.dataWord0);
PRINTF("tx word1 = 0x%x\r\n", txFrame.dataWord1);
/* Waiting for Message receive finish. */
while (!rxComplete)
{
}
PRINTF("\r\nReceved message from MB%d\r\n", RX_MESSAGE_BUFFER_NUM);
PRINTF("rx word0 = 0x%x\r\n", rxFrame.dataWord0);
PRINTF("rx word1 = 0x%x\r\n", rxFrame.dataWord1);
/* Stop FlexCAN Send & Receive. */
FLEXCAN_DisableMbInterrupts(EXAMPLE_CAN, 1 << RX_MESSAGE_BUFFER_NUM);
PRINTF("\r\n==FlexCAN loopback functional example -- Finish.==\r\n");
while (1)
{
__WFI();
}
}
void EXAMPLE_FLEXCAN_IRQHandler(void)
{
/* If new data arrived. */
if (FLEXCAN_GetMbStatusFlags(EXAMPLE_CAN, 1 << RX_MESSAGE_BUFFER_NUM))
{
FLEXCAN_ClearMbStatusFlags(EXAMPLE_CAN, 1 << RX_MESSAGE_BUFFER_NUM);
FLEXCAN_ReadRxMb(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &rxFrame);
rxComplete = true;
}
}
I am trying to make a very simple USART program which send the received character back to the transmitter and represent the equivalent binary number by flashing 8 leds in my breadboard.
Here is the code:
#define F_CPU 1000000UL // set the CPU clock
#define BAUD 9600 // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) // set baudrate value for UBRR
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <inttypes.h>
#include "led.h"
// function to initialize UART
void uart_init (void)
{
UBRRH=(BAUDRATE>>8);
UBRRL=BAUDRATE; //set baud rate
UCSRB|=(1<<TXEN)|(1<<RXEN); //enable receiver and transmitter
UCSRC|=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);// 8bit data format
}
// function to send data
void uart_transmit (unsigned char data)
{
while (!( UCSRA & (1<<UDRE))); // wait while register is free
UDR = data; // load data in the register
}
// function to receive data
unsigned char uart_receive (void)
{
while(!(UCSRA) & (1<<RXC)); // wait while data is being received
return UDR; // return 8-bit data
}
// main function: entry point of program
int main (void)
{
unsigned char a = 0;
char buffer[10] = 0;
DDRB = 0xFF;
uart_init(); // initialize UART
while(1)
{
a=uart_receive(); // save the received data in a variable
uart_transmit(a); // send it back
blink(a - 0); // print in the led
_delay_ms(100); // wait before next attempt
}
return 0;
}
The problem I am facing is that none of the registers related to the USART seem to be recognized by the compiler. See an example of the compilation error I am getting:
'UBRRH' undeclared (first use in this function)
Am I missing an include here?
It seems that code you have is not for ATMEGA168, the errors you are getting are due to some registers that doesnt exist in ATMEGA168. In ATMEGA168, there is more than one UART, so the register names are numbered. You can use UBRR0H instead of UBRRH, for example.
Try this:
#ifdef UDR0
#define UBRRH UBRR0H
#define UBRRL UBRR0L
#define UDR UDR0
#define UCSRA UCSR0A
#define UDRE UDRE0
#define RXC RXC0
#define UCSRB UCSR0B
#define RXEN RXEN0
#define TXEN TXEN0
#define RXCIE RXCIE0
#define UCSRC UCSR0C
#define URSEL
#define UCSZ0 UCSZ00
#define UCSZ1 UCSZ01
#define UCSRC_SELECT 0
#else
#define UCSRC_SELECT (1 << URSEL)
#endif
#define BAUD 9600UL
#define UBRRVAL (F_CPU/(BAUD*16)-1)
#define USE_SLEEP 1
void uart_init() {
/* set baud rate */
UBRRH = UBRRVAL >> 8;
UBRRL = UBRRVAL & 0xff;
/* set frame format: 8 bit, no parity, 1 bit */
UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
/* enable serial receiver and transmitter */
#if !USE_SLEEP
UCSRB = (1 << RXEN) | (1 << TXEN);
#else
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
#endif
}
void uart_putc(uint8_t c) {
if(c == '\n')
uart_putc('\r');
/* wait until transmit buffer is empty */
while(!(UCSRA & (1 << UDRE)));
/* send next byte */
UDR = c;
}
uint8_t uart_getc()
{
/* wait until receive buffer is full */
#if USE_SLEEP
uint8_t sreg = SREG;
sei();
while(!(UCSRA & (1 << RXC)))
sleep_mode();
SREG = sreg;
#else
while(!(UCSRA & (1 << RXC)));
#endif
uint8_t b = UDR;
if(b == '\r')
b = '\n';
return b;
}
int main(){
DDRB = 0xff;
uint8_t data = 0;
uart_init();
while(1){
data = uart_getc();
uart_putc(data);
blink(a - 0);
_delay_ms(100);
}
return 0;
}