Merge pull request #1703 from sgjava/master

Make arm-linux use dynamic buffer everywhere

> @olikraus was there something else you were waiting on besides ifdef change?

thats it :-)
This commit is contained in:
olikraus 2021-11-20 19:57:31 +01:00 committed by GitHub
commit 6b365b6337
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 164 additions and 9 deletions

View File

@ -1376,6 +1376,11 @@ void u8g2_SetBufferCurrTileRow(u8g2_t *u8g2, uint8_t row) U8G2_NOINLINE;
void u8g2_FirstPage(u8g2_t *u8g2);
uint8_t u8g2_NextPage(u8g2_t *u8g2);
// Add ability to set buffer pointer
#ifdef __ARM_LINUX__
#define U8G2_USE_DYNAMIC_ALLOC
#endif
#ifdef U8G2_USE_DYNAMIC_ALLOC
#define u8g2_SetBufferPtr(u8g2, buf) ((u8g2)->tile_buf_ptr = (buf));
#define u8g2_GetBufferSize(u8g2) ((u8g2)->u8x8.display_info->tile_width * 8 * (u8g2)->tile_buf_height)

View File

@ -0,0 +1,61 @@
# Chosse proper compiler for your PI
# NanoPi: arm-linux-gnueabi-gcc
# Raspberry Pi Zero: arm-linux-gnueabi-gcc
# Raspberry Pi 2: arm-linux-gnueabihf-gcc
# OrangePi Zero: arm-linux-gnueabihf-gcc
# NanoPi NEO: arm-linux-gnueabihf-gcc
# NanoPi NEO Plus 2: arm-linux-gnueabihf-gcc
# C-SKY Linux: csky-linux-gcc
CC=arm-linux-gnueabi-gcc
# IP Address of your PI
PI=pi@raspberrypi.local
TARGET=u8g2_sw_i2c_thread
IDIR= -I ../../../drivers -I ../../../../../csrc -I ../../../port
SRCDIR=../../../../../csrc
OBJDIR=../../../obj
OUTDIR=../../../bin
LDIR= -L ../../../lib
LIBS= -lm -lpthread
CFLAGS= $(IDIR) -W -Wall -D __ARM_LINUX__
OBJ+=u8g2_sw_i2c_thread.o\
../../../port/u8g2port.o\
../../../drivers/gpio.o\
../../../drivers/spi.o\
../../../drivers/i2c.o\
OBJ+=$(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o, $(wildcard $(SRCDIR)/*.c))
all: directories $(TARGET)
directories:
@mkdir -p $(OBJDIR)
@mkdir -p $(OUTDIR)
$(TARGET):$(OBJ)
@echo Generating $(TARGET) ...
@$(CC) -o $(OUTDIR)/$@ $(OBJ) $(LDIR) $(LIBS)
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) -c -o $@ $< $(CFLAGS) $(LDIR) $(LIBS)
clean:
@echo RM -rf $(OBJDIR)/
@rm -rf $(OBJ)
@rm -rf $(OBJDIR)
@echo RM -rf $(OUTDIR)/
@rm -rf $(OUTDIR)
upload:
scp $(OUTDIR)/$(TARGET) $(PI):~/
run:
ssh $(PI)

View File

@ -0,0 +1,81 @@
/*
* Run three displays drawing random lines. This proves you can use U8g2 to run
* multiple displays in a thread safe way.
*/
#include "u8g2port.h"
#include <pthread.h>
#include <string.h>
#include <errno.h>
// Encapsulate each thread's info
struct display {
uint8_t gpio_chip;
uint8_t scl;
uint8_t sda;
uint8_t res;
unsigned long delay;
};
typedef struct display display_t;
/*
* Draw random lines with 50 ms delay.
*/
void* do_display(void *arg) {
display_t disp = *((display_t*) arg);
pthread_t id = pthread_self();
uint8_t h, w, y1, y2;
printf("Thread %lu start\n", id);
u8g2_t u8g2;
// Initialization
u8g2_Setup_ssd1306_i2c_128x32_univision_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c,
u8x8_arm_linux_gpio_and_delay);
init_i2c_sw(&u8g2, disp.gpio_chip, disp.scl, disp.sda, disp.res,
disp.delay);
u8g2_InitDisplay(&u8g2);
h = u8g2_GetDisplayHeight(&u8g2);
w = u8g2_GetDisplayWidth(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr);
for (int i = 1; i < 200; ++i) {
u8g2_ClearBuffer(&u8g2);
y1 = rand() % h;
y2 = rand() % h;
u8g2_DrawLine(&u8g2, 0, y1, w - 1, y2);
u8g2_SendBuffer(&u8g2);
sleep_ms(50);
}
u8g2_SetPowerSave(&u8g2, 1);
// Close and deallocate GPIO resources
done_user_data(&u8g2);
printf("Thread %lu end\n", id);
return NULL;
}
int main(void) {
pthread_t id_1;
pthread_t id_2;
pthread_t id_3;
void *retval_1;
void *retval_2;
void *retval_3;
display_t display_1 = { 0, 14, 13, U8X8_PIN_NONE, 0 };
display_t display_2 = { 0, 15, 16, U8X8_PIN_NONE, 0 };
display_t display_3 = { 0, 198, 199, U8X8_PIN_NONE, 0 };
pthread_create(&id_1, NULL, &do_display, &display_1);
pthread_create(&id_2, NULL, &do_display, &display_2);
pthread_create(&id_3, NULL, &do_display, &display_3);
pthread_join(id_1, (void**) &retval_1);
pthread_join(id_2, (void**) &retval_2);
pthread_join(id_3, (void**) &retval_3);
printf("Done\n");
return 0;
}

View File

@ -142,7 +142,8 @@ public:
}
void initSpiHw(uint8_t gpio_chip, uint8_t bus, uint8_t dc, uint8_t res,
uint8_t cs, unsigned int spi_mode, uint32_t max_speed) {
init_spi_hw_advanced(&u8g2, gpio_chip, bus, dc, res, cs, spi_mode, max_speed);
init_spi_hw_advanced(&u8g2, gpio_chip, bus, dc, res, cs, spi_mode,
max_speed);
}
void initSpiHw(uint8_t gpio_chip, uint8_t bus, uint8_t dc, uint8_t res,
uint8_t cs) {
@ -209,15 +210,10 @@ public:
}
bool begin(void) {
/* note: call to u8x8_utf8_init is not required here, this is done in the setup procedures before */
#ifndef U8G2_USE_DYNAMIC_ALLOC
initDisplay();
clearDisplay();
setPowerSave(0);
return 1;
#else
return 0;
#endif
}
void beginSimple(void) {

View File

@ -1,7 +1,9 @@
/*
* This code should support multiple displays since GPIO pin handles have been
* This code supports multiple displays since GPIO pin handles have been
* moved into user_data_struct. I2C and SPI handles are global since they can be
* shared by multiple devices (think I2C with different address sharing bus).
*
* So far I have tested this with 3 software I2C displays. See examples.
*/
#include "u8g2port.h"
@ -46,8 +48,12 @@ void sleep_ns(unsigned long nanoseconds) {
* Allocate user_data_struct, set common values and set user_ptr.
*/
user_data_t* init_user_data(u8g2_t *u8g2) {
// Dynamically allocate u8x8_buffer_struct
// Dynamically allocate user data_struct
user_data_t *user_data = (user_data_t*) malloc(sizeof(user_data_t));
// Dynamically allocate internal buffer
user_data->int_buf = (uint8_t*)malloc(u8g2_GetBufferSize(u8g2));
// We need a unique buffer for each display in order to be thread friendly
u8g2_SetBufferPtr(u8g2, user_data->int_buf);
for (int i = 0; i < U8X8_PIN_CNT; ++i) {
user_data->pins[i] = NULL;
}
@ -122,12 +128,16 @@ void init_spi_sw(u8g2_t *u8g2, uint8_t gpio_chip, uint8_t dc, uint8_t res,
void done_user_data(u8g2_t *u8g2) {
user_data_t *user_data = u8g2_GetUserPtr(u8g2);
if (user_data != NULL) {
// Close all GPIO pins
for (int i = 0; i < U8X8_PIN_CNT; ++i) {
if (user_data->pins[i] != NULL) {
gpio_close(user_data->pins[i]);
gpio_free(user_data->pins[i]);
}
}
// Free internal buffer
free(user_data->int_buf);
// Free user data struct
free(user_data);
u8g2_SetUserPtr(u8g2, NULL);
}

View File

@ -28,7 +28,7 @@ struct user_data_struct {
uint8_t bus;
// Index into buffer
uint8_t index;
// Display buffer, I2C should send 32 bytes max and SPI 128 bytes max
// Callback buffer, I2C should send 32 bytes max and SPI 128 bytes max
uint8_t buffer[128];
// Nanosecond delay for U8X8_MSG_DELAY_I2C
unsigned long delay;
@ -36,6 +36,8 @@ struct user_data_struct {
unsigned int spi_mode;
// SPI max speed
uint32_t max_speed;
// Internal buffer
uint8_t *int_buf;
};
typedef struct user_data_struct user_data_t;